<commit_before># Licensed under a 3-clause BSD style license - see LICENSE.rst
from __future__ import print_function

import tempfile
import re
import warnings
from collections import namedtuple
from xml.dom.minidom import parseString
from datetime import datetime

import astropy.units as u
import astropy.coordinates as coord
import astropy.utils.data as aud
import astropy.io.votable as votable
from astropy import __version__ as ASTROPY_VERSION
from astropy.io import fits

from ..query import BaseQuery
from ..utils.class_or_instance import class_or_instance
from ..utils import commons
from . import (HUBBLE_CONSTANT,
               CORRECT_REDSHIFT,
               OUTPUT_COORDINATE_FRAME,
               OUTPUT_EQUINOX,
               SORT_OUTPUT_BY)
from . import NED_SERVER, NED_TIMEOUT

__all__ = ["Ned"]


class Ned(BaseQuery):
    # make configurable
    BASE_URL = NED_SERVER()
    OBJ_SEARCH_URL = BASE_URL + 'nph-objsearch'
    ALL_SKY_URL = BASE_URL + 'nph-allsky'
    DATA_SEARCH_URL = BASE_URL + 'nph-datasearch'
    IMG_DATA_URL = BASE_URL + 'imgdata'
    SPECTRA_URL = BASE_URL + 'NEDspectra'
    TIMEOUT = NED_TIMEOUT()
    Options = namedtuple('Options', ('display_name', 'cgi_name'))

    PHOTOMETRY_OUT = {1: Options('Data as Published and Homogenized (mJy)', 'bot'),
                      2: Options('Data as Published', 'pub'),
                      3: Options('Homogenized Units (mJy)', 'mjy')}

    @class_or_instance
    def query_object(self, object_name, get_query_payload=False, verbose=False):
        """
        Queries objects by name from the NED Service and returns the Main Source Table.

        Parameters
        ----------
        object_name : str
            name of the identifier to query.
        get_query_payload : bool, optional
            if set to `True` then returns the dictionary sent as the HTTP request.
            Defaults to `False`
        verbose : bool, optional.
            When set to `True` displays warnings if the returned VOTable does not
            conform to the standard. Defaults to `False`.

        Returns
        -------
        result : `astropy.table.Table`
            The result of the query as an `astropy.table.Table` object.

        """
        # for NED's object by name
        response = self.query_object_async(object_name, get_query_payload=get_query_payload)
        if get_query_payload:
            return response
        result = self._parse_result(response, verbose=verbose)
        return result

    @class_or_instance
    def query_object_async(self, object_name, get_query_payload=False):
        """
        Serves the same purpose as `Ned.query_object` but returns the raw HTTP response rather
        than the `astropy.table.Table` object.

        Parameters
        ----------
        object_name : str
            name of the identifier to query.
        get_query_payload : bool, optional
            if set to `True` then returns the dictionary sent as the HTTP request.
            Defaults to `False`

        Returns
        -------
        response : `requests.Response`
            The HTTP response returned from the service

        """
        request_payload = self._request_payload_init()
        self._set_input_options(request_payload)
        self._set_output_options(request_payload)
        request_payload['objname'] = object_name
        if get_query_payload:
            return request_payload
        response = commons.send_request(Ned.OBJ_SEARCH_URL, request_payload, Ned.TIMEOUT, request_type='GET')
        return response

    @class_or_instance
    def query_region(self, coordinates, radius=1 * u.arcmin, equinox='J2000.0', get_query_payload=False,
                     verbose=False):
        """
        Used to query a region around a known identifier or given coordinates. Equivalent to
        the near position and near name queries from the Ned web interface.

        Parameters
        ----------
        coordinates : str or `astropy.coordinates` object
            The target around which to search. It may be specified as a string
            in which case it is resolved using online services or as the appropriate
            `astropy.coordinates` object. ICRS coordinates may also be entered as strings
            as specified in the `astropy.coordinates` module.
        radius : str or `astropy.units.Quantity` object, optional
            The string must be parsable by `astropy.coordinates.Angle`. The appropriate
            `Quantity` object from `astropy.units` may also be used. Defaults to 1 arcmin.
        equinox : str, optional
            The equinox may be either J2000.0 or B1950.0. Defaults to J2000.0
        get_query_payload : bool, optional
            if set to `True` then returns the dictionary sent as the HTTP request.
            Defaults to `False`.
        verbose : bool, optional.
            When set to `True` displays warnings if the returned VOTable does not
            conform to the standard. Defaults to `False`.

        Returns
        -------
        result : `astropy.table.Table`
            The result of the query as an `astropy.table.Table` object.
        """
        # for NED's object near name/ near region
        response = self.query_region_async(coordinates, radius=radius, equinox=equinox,
                                           get_query_payload=get_query_payload)
        if get_query_payload:
            return response
        result = self._parse_result(response, verbose=verbose)
        return result

    @class_or_instance
    def query_region_async(self, coordinates, radius=1 * u.arcmin, equinox='J2000.0', get_query_payload=False):
        """
        Serves the same purpose as `Ned.query_region` but returns the raw HTTP response rather
        than the `astropy.table.Table` object.

        Parameters
        ----------
        coordinates : str or `astropy.coordinates` object
            The target around which to search. It may be specified as a string
            in which case it is resolved using online services or as the appropriate
            `astropy.coordinates` object. ICRS coordinates may also be entered as strings
            as specified in the `astropy.coordinates` module.
        radius : str or `astropy.units.Quantity` object, optional
            The string must be parsable by `astropy.coordinates.Angle`. The appropriate
            `Quantity` object from `astropy.units` may also be used. Defaults to 1 arcmin.
        equinox : str, optional
            The equinox may be either J2000.0 or B1950.0. Defaults to J2000.0
        get_query_payload : bool, optional
            if set to `True` then returns the dictionary sent as the HTTP request.
            Defaults to `False`.

        Returns
        -------
        response : `requests.Response`
            The HTTP response returned from the service
        """
        request_payload = self._request_payload_init()
        self._set_input_options(request_payload)
        self._set_output_options(request_payload)
        # if its a name then query near name
        if _is_name(coordinates):
            request_payload['objname'] = coordinates
            request_payload['search_type'] = 'Near Name Search'
        else:
            try:
                c = commons.parse_coordinates(coordinates)
                if isinstance(c, coord.GalacticCoordinates):
                    request_payload['in_csys'] = 'Galactic'
                    request_payload['lon'] = c.lonangle.degree
                    request_payload['lat'] = c.latangle.degree
                # for any other, convert to ICRS and send<commit_msg>"near name" searches in NED need a radius too<commit_after># Licensed under a 3-clause BSD style license - see LICENSE.rst
from __future__ import print_function

import tempfile
import re
import warnings
from collections import namedtuple
from xml.dom.minidom import parseString
from datetime import datetime

import astropy.units as u
import astropy.coordinates as coord
import astropy.utils.data as aud
import astropy.io.votable as votable
from astropy import __version__ as ASTROPY_VERSION
from astropy.io import fits

from ..query import BaseQuery
from ..utils.class_or_instance import class_or_instance
from ..utils import commons
from . import (HUBBLE_CONSTANT,
               CORRECT_REDSHIFT,
               OUTPUT_COORDINATE_FRAME,
               OUTPUT_EQUINOX,
               SORT_OUTPUT_BY)
from . import NED_SERVER, NED_TIMEOUT

__all__ = ["Ned"]


class Ned(BaseQuery):
    # make configurable
    BASE_URL = NED_SERVER()
    OBJ_SEARCH_URL = BASE_URL + 'nph-objsearch'
    ALL_SKY_URL = BASE_URL + 'nph-allsky'
    DATA_SEARCH_URL = BASE_URL + 'nph-datasearch'
    IMG_DATA_URL = BASE_URL + 'imgdata'
    SPECTRA_URL = BASE_URL + 'NEDspectra'
    TIMEOUT = NED_TIMEOUT()
    Options = namedtuple('Options', ('display_name', 'cgi_name'))

    PHOTOMETRY_OUT = {1: Options('Data as Published and Homogenized (mJy)', 'bot'),
                      2: Options('Data as Published', 'pub'),
                      3: Options('Homogenized Units (mJy)', 'mjy')}

    @class_or_instance
    def query_object(self, object_name, get_query_payload=False, verbose=False):
        """
        Queries objects by name from the NED Service and returns the Main Source Table.

        Parameters
        ----------
        object_name : str
            name of the identifier to query.
        get_query_payload : bool, optional
            if set to `True` then returns the dictionary sent as the HTTP request.
            Defaults to `False`
        verbose : bool, optional.
            When set to `True` displays warnings if the returned VOTable does not
            conform to the standard. Defaults to `False`.

        Returns
        -------
        result : `astropy.table.Table`
            The result of the query as an `astropy.table.Table` object.

        """
        # for NED's object by name
        response = self.query_object_async(object_name, get_query_payload=get_query_payload)
        if get_query_payload:
            return response
        result = self._parse_result(response, verbose=verbose)
        return result

    @class_or_instance
    def query_object_async(self, object_name, get_query_payload=False):
        """
        Serves the same purpose as `Ned.query_object` but returns the raw HTTP response rather
        than the `astropy.table.Table` object.

        Parameters
        ----------
        object_name : str
            name of the identifier to query.
        get_query_payload : bool, optional
            if set to `True` then returns the dictionary sent as the HTTP request.
            Defaults to `False`

        Returns
        -------
        response : `requests.Response`
            The HTTP response returned from the service

        """
        request_payload = self._request_payload_init()
        self._set_input_options(request_payload)
        self._set_output_options(request_payload)
        request_payload['objname'] = object_name
        if get_query_payload:
            return request_payload
        response = commons.send_request(Ned.OBJ_SEARCH_URL, request_payload, Ned.TIMEOUT, request_type='GET')
        return response

    @class_or_instance
    def query_region(self, coordinates, radius=1 * u.arcmin, equinox='J2000.0', get_query_payload=False,
                     verbose=False):
        """
        Used to query a region around a known identifier or given coordinates. Equivalent to
        the near position and near name queries from the Ned web interface.

        Parameters
        ----------
        coordinates : str or `astropy.coordinates` object
            The target around which to search. It may be specified as a string
            in which case it is resolved using online services or as the appropriate
            `astropy.coordinates` object. ICRS coordinates may also be entered as strings
            as specified in the `astropy.coordinates` module.
        radius : str or `astropy.units.Quantity` object, optional
            The string must be parsable by `astropy.coordinates.Angle`. The appropriate
            `Quantity` object from `astropy.units` may also be used. Defaults to 1 arcmin.
        equinox : str, optional
            The equinox may be either J2000.0 or B1950.0. Defaults to J2000.0
        get_query_payload : bool, optional
            if set to `True` then returns the dictionary sent as the HTTP request.
            Defaults to `False`.
        verbose : bool, optional.
            When set to `True` displays warnings if the returned VOTable does not
            conform to the standard. Defaults to `False`.

        Returns
        -------
        result : `astropy.table.Table`
            The result of the query as an `astropy.table.Table` object.
        """
        # for NED's object near name/ near region
        response = self.query_region_async(coordinates, radius=radius, equinox=equinox,
                                           get_query_payload=get_query_payload)
        if get_query_payload:
            return response
        result = self._parse_result(response, verbose=verbose)
        return result

    @class_or_instance
    def query_region_async(self, coordinates, radius=1 * u.arcmin, equinox='J2000.0', get_query_payload=False):
        """
        Serves the same purpose as `Ned.query_region` but returns the raw HTTP response rather
        than the `astropy.table.Table` object.

        Parameters
        ----------
        coordinates : str or `astropy.coordinates` object
            The target around which to search. It may be specified as a string
            in which case it is resolved using online services or as the appropriate
            `astropy.coordinates` object. ICRS coordinates may also be entered as strings
            as specified in the `astropy.coordinates` module.
        radius : str or `astropy.units.Quantity` object, optional
            The string must be parsable by `astropy.coordinates.Angle`. The appropriate
            `Quantity` object from `astropy.units` may also be used. Defaults to 1 arcmin.
        equinox : str, optional
            The equinox may be either J2000.0 or B1950.0. Defaults to J2000.0
        get_query_payload : bool, optional
            if set to `True` then returns the dictionary sent as the HTTP request.
            Defaults to `False`.

        Returns
        -------
        response : `requests.Response`
            The HTTP response returned from the service
        """
        request_payload = self._request_payload_init()
        self._set_input_options(request_payload)
        self._set_output_options(request_payload)
        # if its a name then query near name
        if _is_name(coordinates):
            request_payload['objname'] = coordinates
            request_payload['search_type'] = 'Near Name Search'
            request_payload['radius'] = _parse_radius(radius)
        else:
            try:
                c = commons.parse_coordinates(coordinates)
                if isinstance(c, coord.GalacticCoordinates):
                    request_payload['in_csys'] = 'Galactic'
                    request_payload['lon'] = c.lonangle.degree
                    request_payload['lat'] = c.latangle.degree
                # for any other, convert to ICRS and send
{'fraction_non_alphanumeric': 0.07268349817803227, 'fraction_numerical': 0.006246746486205101, 'mean_word_length': 2.254764930114358, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5410848', 'n_tokens_mistral': 4145, 'n_tokens_neox': 3984, 'n_words': 1383}