astro query:docs

- Index
- Modules

### Navigation

- astroquery v0.4.11 »
- Module code »
- astroquery.nist »

# Source code for astroquery.nist.core

    # Licensed under a 3-clause BSD style license - see LICENSE.rst

    import html
    import re

    import astropy.units as u
    from astropy.table import Table

    from ..query import BaseQuery
    from ..utils import async_to_sync, prepend_docstr_nosections
    from . import conf
    from ..exceptions import TableParseError

    __all__ = ['Nist', 'NistClass']

    def _strip_blanks(table):
        """
        Remove blank lines from table (included for "human readability" but
        useless to us...
        returns a single string joined by \n newlines

        Parameters
        ----------
        table : str
           table to strip as a string

        Returns
        -------
        single string joined by newlines.
        """
        numbersletters = re.compile("[0-9A-Za-z]")
        if isinstance(table, str):
            table = table.split('\n')
        table = [line for line in table if numbersletters.search(line)]
        return "\n".join(table)

    @async_to_sync
    class NistClass(BaseQuery):
        URL = conf.server
        TIMEOUT = conf.timeout
        unit_code = {'Angstrom': 0,
                     'nm': 1,
                     'um': 2}
        energy_level_code = {'cm-1': 0, 'invcm': 0, 'cm': 0,
                             'ev': 1, 'eV': 1, 'EV': 1, 'electronvolt': 1,
                             'R': 2, 'Rydberg': 2, 'rydberg': 2}
        order_out_code = {'wavelength': 0,
                          'multiplet': 1}
        wavelength_unit_code = {'vacuum': 3,
                                'vac+air': 4}

        def _args_to_payload(self, *args, **kwargs):
            """
            Serves the same purpose as `~NistClass.query` but returns
            the raw HTTP response rather than a `~astropy.table.Table` object.

            Parameters
            ----------
            minwav : `astropy.units.Quantity` object
                The lower wavelength for the spectrum in appropriate units.
            maxwav : `astropy.units.Quantity` object
                The upper wavelength for the spectrum in appropriate units.
            linename : str or iterable of str, optional
                The spectrum/spectra to fetch. Defaults to "H I"
            energy_level_unit : str, optional
                The energy level units must be one of the following:
                'R', 'Rydberg', 'rydberg', 'cm', 'cm-1', 'EV', 'eV',
                'electronvolt', 'ev', 'invcm' Defaults to 'eV'.
            output_order : str, optional
                Decide ordering of output. Must be one of following:
                ['wavelength', 'multiplet']. Defaults to 'wavelength'.
            wavelength_type : str, optional
                Must be one of 'vacuum' or 'vac+air'. Defaults to 'vacuum'.
            get_query_payload : bool, optional
                If true then returns the dictionary of query parameters, posted to
                remote server. Defaults to `False`.

            Returns
            -------
            request_payload : dict
                The dictionary of parameters sent with the HTTP request

            """
            request_payload = {}
            linename = kwargs["linename"]
            request_payload["spectra"] = linename if isinstance(linename, str) else "; ".join(linename)
            (min_wav, max_wav, wav_unit) = _parse_wavelength(args[0], args[1])
            request_payload["low_w"] = min_wav
            request_payload["upp_w"] = max_wav
            request_payload["unit"] = wav_unit
            request_payload["submit"] = "Retrieve Data"
            request_payload["format"] = 1  # ascii
            request_payload["line_out"] = 0  # All lines
            request_payload["en_unit"] = Nist.energy_level_code[
                kwargs["energy_level_unit"]]
            request_payload["output_type"] = 0  # entirely rather than pagewise
            request_payload["bibrefs"] = 1
            request_payload["show_obs_wl"] = 1
            request_payload["show_calc_wl"] = 1
            request_payload["order_out"] = Nist.order_out_code[
                kwargs['output_order']]
            request_payload["max_low_enrg"] = ""
            request_payload["show_av"] = Nist.wavelength_unit_code[
                kwargs['wavelength_type']]
            request_payload["max_upp_enrg"] = ""
            request_payload["tsb_value"] = 0
            request_payload["min_str"] = ""
            request_payload["A_out"] = 0
            request_payload["f_out"] = "on"
            request_payload["intens_out"] = "on"
            request_payload["max_str"] = ""
            request_payload["allowed_out"] = 1
            request_payload["forbid_out"] = 1
            request_payload["min_accur"] = ""
            request_payload["min_intens"] = ""
            request_payload["conf_out"] = "on"
            request_payload["term_out"] = "on"
            request_payload["enrg_out"] = "on"
            request_payload["J_out"] = "on"
            request_payload["g_out"] = "on"
            request_payload["page_size"] = 15
            request_payload["remove_js"] = "on"
            request_payload["show_wn"] = 1
            return request_payload

        @prepend_docstr_nosections("\n" + _args_to_payload.__doc__)
        def query_async(self, minwav, maxwav, *, linename="H I",
                        energy_level_unit='eV', output_order='wavelength',
                        wavelength_type='vacuum', get_query_payload=False):
            """
            Returns
            -------
            response : `requests.Response` object
                The response of the HTTP request.
            """
            request_payload = self._args_to_payload(
                minwav, maxwav, linename=linename,
                energy_level_unit=energy_level_unit, output_order=output_order,
                wavelength_type=wavelength_type)
            if get_query_payload:
                return request_payload

            response = self._request("GET", url=Nist.URL, params=request_payload,
                                     timeout=Nist.TIMEOUT)
            return response

        def _parse_result(self, response, *, verbose=False):
            """
            Parses the results from the HTTP response to `astropy.table.Table`.

            Parameters
            ----------
            response : `requests.Response`
                The HTTP response object

            Returns
            -------
            table : `astropy.table.Table`
            """

            pre_re = re.compile("<pre>(.*)</pre>", flags=re.DOTALL)
            links_re = re.compile(r"<a.*?>\s*(\w+)\s*</a>")
            content = str(response.text)

            try:
                pre = pre_re.findall(content)[0]
            except IndexError:
                raise Exception("Result did not contain a table")
            try:
                table = _strip_blanks(pre)
                table = links_re.sub(r'\1', table)
                table = html.unescape(table)
                table = Table.read(table, format='ascii.fixed_width', data_start=3, delimiter='|')
                return table
            except Exception as ex:
                self.response = response
                self.table_parse_error = ex
                raise TableParseError("Failed to parse asciitable! The raw "
                                      "response can be found in self.response, "
                                      "and the error in self.table_parse_error.")

    Nist = NistClass()

    def _parse_wavelength(min_wav, max_wav):
        """
        Helper function to return wavelength and units in form accepted by NIST

        Parameters
        ----------
        min_wav : `astropy.units.Quantity` object
            The lower wavelength in proper units.
        max_wav : `astropy.units.Quantity` object
            The upper wavelength in proper units.

        Returns
        -------
        tuple : (number, number, number)
            The value of lower, upper wavelength and their unit.
        """
        max_wav = max_wav.to(min_wav.unit)
        wav_unit = min_wav.unit.to_string()
        if wav_unit not in Nist.unit_code:
            max_wav = max_wav.to(u.angstrom).value
            min_wav = min_wav.to(u.angstrom).value
            wav_unit = Nist.unit_code['Angstrom']
        else:
            max_wav = max_wav.value
            min_wav = min_wav.value
            wav_unit = Nist.unit_code[wav_unit]
        return (min_wav, max_wav, wav_unit)