text: # Licensed under a 3-clause BSD style license - see LICENSE.rst
  from __future__ import print_function
  
  import warnings
  import functools
  import numpy as np
  from astropy.table import Table
  from astropy.utils.exceptions import AstropyDeprecationWarning
  
  from ..query import BaseQuery
  from ..utils import commons, async_to_sync, prepend_docstr_nosections
  
  from . import conf
  
  __all__ = ['Ogle', 'OgleClass']
  
  __doctest_skip__ = ['OgleClass.*']
  
  
  def _validate_params(func):
      @functools.wraps(func)
      def wrapper(*args, **kwargs):
          algorithm = kwargs.get('algorithm')
          quality = kwargs.get('quality')
          coord_sys = kwargs.get('coord_sys')
          # if unspecified, the defaults (which are OK) will be used
          if algorithm is not None and algorithm not in Ogle.algorithms:
              raise ValueError("'algorithm` must be one of \
                               {!s}".format(Ogle.algorithms))
          if quality is not None and quality not in Ogle.quality_codes:
              raise ValueError("'quality' must be one of \
                               {!s}".format(Ogle.quality_codes))
          if coord_sys is not None and coord_sys not in Ogle.coord_systems:
              raise ValueError("'coord_sys' must be one of \
                      {!s}".format(Ogle.coord_systems))
          return func(*args, **kwargs)
      return wrapper
  
  
  class CoordParseError(ValueError):
  
      def __init__(self, message='Could not parse `coord` argument.', **kwargs):
          super(ValueError, self).__init__(message, **kwargs)
  
  
  @async_to_sync
  class OgleClass(BaseQuery):
  
      DATA_URL = conf.server
      TIMEOUT = conf.timeout
  
      algorithms = ['NG', 'NN']
      quality_codes = ['GOOD', 'ALL']
      coord_systems = ['RD', 'LB']
      result_dtypes = ['f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'i8',
                       'a2', 'f8']
  
      @_validate_params
      def _args_to_payload(self, coord=None, algorithm='NG', quality='GOOD',
                           coord_sys='RD'):
          """
          Query the OGLE-III interstellar extinction calculator.
  
          Parameters
          ----------
          coord : list-like
              Pointings to evaluate interstellar extinction. Three forms of
              coordinates may be passed::
  
                  * single astropy coordinate instance
                  * list-like object (1 x N) of astropy coordinate instances
                  * list-like object (2 x N) of RA/Decs or Glon/Glat as strings
                  or  floats. (May not be supported in future versions.)
  
          algorithm : string
              Algorithm to interpolate data for desired coordinate.
              Valid options::
  
                  * 'NG': nearest grid point
                  * 'NN': natural neighbor interpolation
  
          quality : string
              Quality factor for data. Valid options::
  
                  * 'All': all points
                  * 'GOOD': QF=0 as described in Nataf et al. (2012).
  
          coord_sys : string
              Coordinate system if using lists of RA/Decs in ``coord``.
              Valid options::
  
                  * 'RD': equatorial coordinates
                  * 'LB': Galactic coordinates.
  
          Returns
          -------
          table : `~astropy.table.Table`
  
          Raises
          ------
          CoordParseError
              Exception raised for malformed coordinate input
  
          Examples
          --------
          Using astropy coordinates:
  
          >>> from astropy.coordinates import SkyCoord
          >>> from astropy import units as u
          >>> co = SkyCoord(0.0, 3.0, unit=(u.degree, u.degree),
          ...               frame='galactic')
          >>> from astroquery.ogle import Ogle
          >>> t = Ogle.query_region(coord=co)
          >>> t.pprint()
          RA/LON   Dec/Lat    A_I  E(V-I) S_E(V-I) R_JKVI   mu    S_mu
          --------- ---------- ----- ------ -------- ------ ------ ----- ...
          17.568157 -27.342475 3.126  2.597    0.126 0.3337 14.581 0.212
          """
          # Determine the coord object type and generate list of coordinates
          lon, lat = self._parse_coords(coord, coord_sys)
          # Generate payload
          query_header = '# {0} {1} {2}\n'.format(coord_sys, algorithm, quality)
          sources = '\n'.join(['{0} {1}'.format(lo, la) for lo, la in
                               zip(lon, lat)])
          file_data = query_header + sources
          files = {'file1': file_data}
          return files
  
      @prepend_docstr_nosections(_args_to_payload.__doc__)
      def query_region_async(self, *args, **kwargs):
          """
          Returns
          -------
          response : `requests.Response`
              The HTTP response returned from the service.
          """
          files = self._args_to_payload(*args, **kwargs)
          # Make request
          params = {'dnfile': 'submit'}
          response = self._request("POST", url=self.DATA_URL, data=params,
                                   timeout=self.TIMEOUT, files=files)
  
          response.raise_for_status()
          return response
  
      def _parse_result(self, response, verbose=False):
          # Parse table, ignore last two (blank) lines
          raw_data = response.text.split('\n')[:-2]
          # Select first row and skip first character ('#') to find column
          # headers
          header = raw_data[0][1:].split()
          data = self._parse_raw(raw_data)
          t = Table(data, names=header, dtype=self.result_dtypes)
          return t
  
      def _parse_coords(self, coord, coord_sys):
          """
          Parse single astropy.coordinates instance, list of astropy.coordinate
          instances, or 2xN list of coordinate values.
  
          Parameters
          ----------
          coord : list-like
          coord_sys : string
  
          Returns
          -------
          lon : list
              Longitude coordinate values
          lat : list
              Latitude coordinate values
          """
          if not isinstance(coord, list):
              # single astropy coordinate
              try:
                  ra, dec = commons.coord_to_radec(coord)
                  lon = [ra]
                  lat = [dec]
                  return lon, lat
              except ValueError:
                  raise CoordParseError()
          elif isinstance(coord, list):
              shape = np.shape(coord)
              # list of astropy coordinates
              if len(shape) == 1:
                  try:
                      radec = [commons.coord_to_radec(co) for co in coord]
                      lon, lat = list(zip(*radec))
                      return lon, lat
                  except ValueError:
                      raise CoordParseError()
              # list-like of values
              elif (len(shape) == 2) & (shape[0] == 2):
                  warnings.warn('Non-Astropy coordinates may not be supported '
                                'in a future version.', AstropyDeprecationWarning)
                  return coord
              else:
                  raise CoordParseError()
          else:
              raise CoordParseError()
  
      def _parse_raw(self, raw_data):
          """
          Parse the raw strings returned from the query request and return a list
          of lists for each column in string format.
  
          Parameters
          ----------
          raw_data : list
              Raw data from the request formatted to as list of strings for each
              line
  
          Returns
          -------
          data : list
              List of lists for each column as strings
          """
          # Requests returns unicode encoding, return to ascii
          data = [line.split() for line in raw_data[1:]]
          # Transpose while keeping as list of lists
          data = list(map(list, zip(*data)))
          return data
  
  
  Ogle = OgleClass()
  