astro query:docs

- Index
- Modules

### Navigation

- next »
- « previous |
- astroquery v0.4.11 »
- Template Module

# Template Module

The template module, written by Madhura Parikh, shows how to build your own module for a new online service.

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

    # put all imports organized as shown below
    # 1. standard library imports

    # 2. third party imports
    import astropy.units as u
    import astropy.coordinates as coord
    import astropy.io.votable as votable
    from astropy.table import Table
    from astropy.io import fits

    # 3. local imports - use relative imports
    # commonly required local imports shown below as example
    # all Query classes should inherit from BaseQuery.
    from ..query import BaseQuery
    # has common functions required by most modules
    from ..utils import commons
    # prepend_docstr is a way to copy docstrings between methods
    from ..utils import prepend_docstr_nosections
    # async_to_sync generates the relevant query tools from _async methods
    from ..utils import async_to_sync
    # import configurable items declared in __init__.py
    from . import conf

    # export all the public classes and methods
    __all__ = ['Template', 'TemplateClass']

    # declare global variables and constants if any

    # Now begin your main class
    # should be decorated with the async_to_sync imported previously
    @async_to_sync
    class TemplateClass(BaseQuery):

        """
        Not all the methods below are necessary but these cover most of the common
        cases, new methods may be added if necessary, follow the guidelines at
        <http://astroquery.readthedocs.io/en/latest/api.html>
        """
        # use the Configuration Items imported from __init__.py to set the URL,
        # TIMEOUT, etc.
        URL = conf.server
        TIMEOUT = conf.timeout

        # all query methods are implemented with an "async" method that handles
        # making the actual HTTP request and returns the raw HTTP response, which
        # should be parsed by a separate _parse_result method.   The query_object
        # method is created by async_to_sync automatically.  It would look like
        # this:
        """
        def query_object(object_name, get_query_payload=False)
            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
        """

        def query_object_async(self, object_name, *, get_query_payload=False,
                               cache=True):
            """
            This method is for services that can parse object names. Otherwise
            use :meth:`astroquery.template_module.TemplateClass.query_region`.
            Put a brief description of what the class does here.

            Parameters
            ----------
            object_name : str
                name of the identifier to query.
            get_query_payload : bool, optional
                This should default to False. When set to `True` the method
                should return the HTTP request parameters as a dict.
            verbose : bool, optional
               This should default to `False`, when set to `True` it displays
               VOTable warnings.
            any_other_param : <param_type>
                similarly list other parameters the method takes

            Returns
            -------
            response : `requests.Response`
                The HTTP response returned from the service.
                All async methods should return the raw HTTP response.

            Examples
            --------
            While this section is optional you may put in some examples that
            show how to use the method. The examples are written similar to
            standard doctests in python.

            """
            # the async method should typically have the following steps:
            # 1. First construct the dictionary of the HTTP request params.
            # 2. If get_query_payload is `True` then simply return this dict.
            # 3. Else make the actual HTTP request and return the corresponding
            #    HTTP response
            # All HTTP requests are made via the `BaseQuery._request` method. This
            # use a generic HTTP request method internally, similar to
            # `requests.Session.request` of the Python Requests library, but
            # with added caching-related tools.

            # See below for an example:

            # first initialize the dictionary of HTTP request parameters
            request_payload = dict()

            # Now fill up the dictionary. Here the dictionary key should match
            # the exact parameter name as expected by the remote server. The
            # corresponding dict value should also be in the same format as
            # expected by the server. Additional parsing of the user passed
            # value may be required to get it in the right units or format.
            # All this parsing may be done in a separate private `_args_to_payload`
            # method for cleaner code.

            request_payload['object_name'] = object_name
            # similarly fill up the rest of the dict ...

            if get_query_payload:
                return request_payload
            # BaseQuery classes come with a _request method that includes a
            # built-in caching system
            response = self._request('GET', self.URL, params=request_payload,
                                     timeout=self.TIMEOUT, cache=cache)
            return response

        # For services that can query coordinates, use the query_region method.
        # The pattern is similar to the query_object method. The query_region
        # method also has a 'radius' keyword for specifying the radius around
        # the coordinates in which to search. If the region is a box, then
        # the keywords 'width' and 'height' should be used instead. The coordinates
        # may be accepted as an `astropy.coordinates` object or as a string, which
        # may be further parsed.

        # similarly we write a query_region_async method that makes the
        # actual HTTP request and returns the HTTP response

        def query_region_async(self, coordinates, radius, height, width,
                               *, get_query_payload=False, cache=True):
            """
            Queries a region around the specified coordinates.

            Parameters
            ----------
            coordinates : str or `astropy.coordinates`.
                coordinates around which to query
            radius : str or `astropy.units.Quantity`.
                the radius of the cone search
            width : str or `astropy.units.Quantity`
                the width for a box region
            height : str or `astropy.units.Quantity`
                the height for a box region
            get_query_payload : bool, optional
                Just return the dict of HTTP request parameters.
            verbose : bool, optional
                Display VOTable warnings or not.

            Returns
            -------
            response : `requests.Response`
                The HTTP response returned from the service.
                All async methods should return the raw HTTP response.
            """
            request_payload = self._args_to_payload(coordinates, radius, height,
                                                    width)
            if get_query_payload:
                return request_payload
            response = self._request('GET', self.URL, params=request_payload,
                                     timeout=self.TIMEOUT, cache=cache)
            return response

        # as we mentioned earlier use various python regular expressions, etc
        # to create the dict of HTTP request parameters by parsing the user
        # entered values. For cleaner code keep this as a separate private method:

        def _args_to_payload(self, *args, **kwargs):
            request_payload = dict()
            # code to parse input and construct the dict
            # goes here. Then return the dict to the caller
            return request_payload

        # the methods above call the private _parse_result method.
        # This should parse the raw HTTP response and return it as
        # an `astropy.table.Table`. Below is the skeleton:

        def _parse_result(self, response, *, verbose=False):
            # if verbose is False then suppress any VOTable related warnings
            if not verbose:
                commons.suppress_vo_warnings()
            # try to parse the result into an astropy.Table, else
            # return the raw result with an informative error message.
            try:
                # do something with regex to get the result into
                # astropy.Table form. return the Table.
                pass
            except ValueError:
                # catch common errors here, but never use bare excepts
                # return raw result/ handle in some way
                pass

            return Table()

        # Image queries do not use the async_to_sync approach: the "synchronous"
        # version must be defined explicitly.  The example below therefore presents
        # a complete example of how to write your own synchronous query tools if
        # you prefer to avoid the automatic approach.
        #
        # For image queries, the results should be returned as a
        # list of `astropy.fits.HDUList` objects. Typically image queries
        # have the following method family:
        # 1. get_images - this is the high level method that interacts with
        #        the user. It reads in the user input and returns the final
        #        list of fits images to the user.
        # 2. get_images_async - This is a lazier form of the get_images function,
        #        in that it returns just the list of handles to the image files
        #        instead of actually downloading them.
        # 3. extract_image_urls - This takes in the raw HTTP response and scrapes
        #        it to get the downloadable list of image URLs.
        # 4. get_image_list - this is similar to the get_images, but it simply
        #        takes in the list of URLs scrapped by extract_image_urls and
        #        returns this list rather than the actual FITS images
        # NOTE : in future support may be added to allow the user to save
        # the downloaded images to a preferred location. Here we look at the
        # skeleton code for image services

        def get_images(self, coordinates, radius, get_query_payload):
            """
            A query function that searches for image cut-outs around coordinates

            Parameters
            ----------
            coordinates : str or `astropy.coordinates`.
                coordinates around which to query
            radius : str or `astropy.units.Quantity`.
                the radius of the cone search
            get_query_payload : bool, optional
                If true than returns the dictionary of query parameters, posted to
                remote server. Defaults to `False`.

            Returns
            -------
            A list of `astropy.fits.HDUList` objects
            """
            readable_objs = self.get_images_async(coordinates, radius,
                                                  get_query_payload=get_query_payload)
            if get_query_payload:
                return readable_objs  # simply return the dict of HTTP request params
            # otherwise return the images as a list of astropy.fits.HDUList
            return [obj.get_fits() for obj in readable_objs]

        @prepend_docstr_nosections(get_images.__doc__)
        def get_images_async(self, coordinates, radius, *, get_query_payload=False):
            """
            Returns
            -------
            A list of context-managers that yield readable file-like objects
            """
            # As described earlier, this function should return just
            # the handles to the remote image files. Use the utilities
            # in commons.py for doing this:

            # first get the links to the remote image files
            image_urls = self.get_image_list(coordinates, radius,
                                             get_query_payload=get_query_payload)
            if get_query_payload:  # if true then return the HTTP request params dict
                return image_urls
            # otherwise return just the handles to the image files.
            return [commons.FileContainer(U) for U in image_urls]

        # the get_image_list method, simply returns the download
        # links for the images as a list

        @prepend_docstr_nosections(get_images.__doc__)
        def get_image_list(self, coordinates, radius, *, get_query_payload=False,
                           cache=True):
            """
            Returns
            -------
            list of image urls
            """
            # This method should implement steps as outlined below:
            # 1. Construct the actual dict of HTTP request params.
            # 2. Check if the get_query_payload is True, in which
            #    case it should just return this dict.
            # 3. Otherwise make the HTTP request and receive the
            #    HTTP response.
            # 4. Pass this response to the extract_image_urls
            #    which scrapes it to extract the image download links.
            # 5. Return the download links as a list.
            request_payload = self._args_to_payload(coordinates, radius)
            if get_query_payload:
                return request_payload
            response = self._request(method="GET", url=self.URL,
                                     data=request_payload,
                                     timeout=self.TIMEOUT, cache=cache)

            return self.extract_image_urls(response.text)

        # the extract_image_urls method takes in the HTML page as a string
        # and uses regexps, etc to scrape the image urls:

        def extract_image_urls(self, html_str):
            """
            Helper function that uses regex to extract the image urls from the
            given HTML.

            Parameters
            ----------
            html_str : str
                source from which the urls are to be extracted

            Returns
            -------
            list of image URLs
            """
            # do something with regex on the HTML
            # return the list of image URLs
            pass

    # the default tool for users to interact with is an instance of the Class
    Template = TemplateClass()

    # once your class is done, tests should be written
    # See ./tests for examples on this

    # Next you should write the docs in astroquery/docs/module_name
    # using Sphinx.