astro query:docs

- Index
- Modules

### Navigation

- astroquery v0.4.11 »
- Module code »
- astroquery.ipac.irsa »
- astroquery.ipac.irsa.ibe »

# Source code for astroquery.ipac.irsa.ibe.core

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

    API from

     https://irsa.ipac.caltech.edu/ibe/
    """

    import os
    import webbrowser
    from bs4 import BeautifulSoup

    import astropy.coordinates as coord
    from astropy.table import Table

    from astroquery.exceptions import InvalidQueryError
    from astroquery.query import BaseQuery
    from astroquery.utils import commons
    from astroquery.ipac.irsa.ibe import conf

    __all__ = ['Ibe', 'IbeClass']

    class IbeClass(BaseQuery):
        URL = conf.server
        MISSION = conf.mission
        DATASET = conf.dataset
        TABLE = conf.table
        TIMEOUT = conf.timeout

        def query_region(self, *, coordinate=None, where=None, mission=None,
                         dataset=None, table=None, columns=None, width=None,
                         height=None, intersect='OVERLAPS', most_centered=False):
            """
            For certain missions, this function can be used to search for image and
            catalog files based on a point, a box (bounded by great circles) and/or
            an SQL-like ``where`` clause.

            If ``coordinates`` is specified, then the optional ``width`` and
            ``height`` arguments control the width and height of the search
            box. If neither ``width`` nor ``height`` are provided, then the
            search area is a point. If only one of ``width`` or ``height`` are
            specified, then the search area is a square with that side length
            centered at the coordinate.

            Parameters
            ----------
            coordinate : str, `astropy.coordinates` object
                Gives the position of the center of the box if performing a box
                search. If it is a string, then it must be a valid argument to
                `~astropy.coordinates.SkyCoord`. Required if ``where`` is absent.
            where : str
                SQL-like query string. Required if ``coordinates`` is absent.
            mission : str
                The mission to be used (if not the default mission).
            dataset : str
                The dataset to be used (if not the default dataset).
            table : str
                The table to be queried (if not the default table).
            columns : str, list
                A space-separated string or a list of strings of the names of the
                columns to return.
            width : str or `~astropy.units.Quantity` object
                Width of the search box if ``coordinates`` is present.

                The string must be parsable by `~astropy.coordinates.Angle`. The
                appropriate `~astropy.units.Quantity` object from `astropy.units`
                may also be used.
            height : str, `~astropy.units.Quantity` object
                Height of the search box if ``coordinates`` is present.

                The string must be parsable by `~astropy.coordinates.Angle`. The
                appropriate `~astropy.units.Quantity` object from `astropy.units`
                may also be used.
            intersect : ``'COVERS'``, ``'ENCLOSED'``, ``'CENTER'``, ``'OVERLAPS'``
                Spatial relationship between search box and image footprint.

                ``'COVERS'``: X must completely contain S. Equivalent to
                ``'CENTER'`` and ``'OVERLAPS'`` if S is a point.

                ``'ENCLOSED'``: S must completely contain X. If S is a point, the
                query will always return an empty image table.

                ``'CENTER'``: X must contain the center of S. If S is a point, this
                is equivalent to ``'COVERS'`` and ``'OVERLAPS'``.

                ``'OVERLAPS'``: The intersection of S and X is non-empty. If S is a
                point, this is equivalent to ``'CENTER'`` and ``'COVERS'``.
            most_centered : bool
                If True, then only the most centered image is returned.

            Returns
            -------
            table : `~astropy.table.Table`
                A table containing the results of the query
            """
            response = self.query_region_async(
                coordinate=coordinate, where=where, mission=mission,
                dataset=dataset, table=table, columns=columns, width=width,
                height=height, intersect=intersect, most_centered=most_centered)

            # Raise exception, if request failed
            response.raise_for_status()

            return Table.read(response.text, format='ipac', guess=False)

        def query_region_sia(self, *, coordinate=None, mission=None,
                             dataset=None, table=None, width=None,
                             height=None, intersect='OVERLAPS',
                             most_centered=False):
            """
            Query using simple image access protocol.  See ``query_region`` for
            details.  The returned table will include a list of URLs.
            """
            response = self.query_region_async(
                coordinate=coordinate, mission=mission,
                dataset=dataset, table=table, width=width,
                height=height, intersect=intersect, most_centered=most_centered,
                action='sia')

            # Raise exception, if request failed
            response.raise_for_status()

            return commons.parse_votable(
                response.text).get_first_table().to_table()

        def query_region_async(self, *, coordinate=None, where=None, mission=None, dataset=None,
                               table=None, columns=None, width=None, height=None,
                               action='search', intersect='OVERLAPS', most_centered=False):
            """
            For certain missions, this function can be used to search for image and
            catalog files based on a point, a box (bounded by great circles) and/or
            an SQL-like ``where`` clause.

            If ``coordinates`` is specified, then the optional ``width`` and
            ``height`` arguments control the width and height of the search
            box. If neither ``width`` nor ``height`` are provided, then the
            search area is a point. If only one of ``width`` or ``height`` are
            specified, then the search area is a square with that side length
            centered at the coordinate.

            Parameters
            ----------
            coordinate : str, `astropy.coordinates` object
                Gives the position of the center of the box if performing a box
                search. If it is a string, then it must be a valid argument to
                `~astropy.coordinates.SkyCoord`. Required if ``where`` is absent.
            where : str
                SQL-like query string. Required if ``coordinates`` is absent.
            mission : str
                The mission to be used (if not the default mission).
            dataset : str
                The dataset to be used (if not the default dataset).
            table : str
                The table to be queried (if not the default table).
            columns : str, list
                A space-separated string or a list of strings of the names of the
                columns to return.
            width : str or `~astropy.units.Quantity` object
                Width of the search box if ``coordinates`` is present.

                The string must be parsable by `~astropy.coordinates.Angle`. The
                appropriate `~astropy.units.Quantity` object from `astropy.units`
                may also be used.
            height : str, `~astropy.units.Quantity` object
                Height of the search box if ``coordinates`` is present.

                The string must be parsable by `~astropy.coordinates.Angle`. The
                appropriate `~astropy.units.Quantity` object from `astropy.units`
                may also be used.
            intersect : ``'COVERS'``, ``'ENCLOSED'``, ``'CENTER'``, ``'OVERLAPS'``
                Spatial relationship between search box and image footprint.

                ``'COVERS'``: X must completely contain S. Equivalent to
                ``'CENTER'`` and ``'OVERLAPS'`` if S is a point.

                ``'ENCLOSED'``: S must completely contain X. If S is a point, the
                query will always return an empty image table.

                ``'CENTER'``: X must contain the center of S. If S is a point, this
                is equivalent to ``'COVERS'`` and ``'OVERLAPS'``.

                ``'OVERLAPS'``: The intersection of S and X is non-empty. If S is a
                point, this is equivalent to ``'CENTER'`` and ``'COVERS'``.
            most_centered : bool
                If True, then only the most centered image is returned.
            action : ``'search'``, ``'data'``, or ``'sia'``
                The action to perform at the server.  The default is ``'search'``,
                which returns a table of the available data.  ``'data'`` requires
                advanced path construction that is not yet supported. ``'sia'``
                provides access to the 'simple image access' IVOA protocol

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

            if coordinate is None and where is None:
                raise InvalidQueryError(
                    'At least one of `coordinate` or `where` is required')

            intersect = intersect.upper()
            if intersect not in ('COVERS', 'ENCLOSED', 'CENTER', 'OVERLAPS'):
                raise InvalidQueryError(
                    "Invalid value for `intersects` "
                    + "(must be 'COVERS', 'ENCLOSED', 'CENTER', or 'OVERLAPS')")

            if action not in ('sia', 'data', 'search'):
                raise InvalidQueryError("Valid actions are: sia, data, search.")
            if action == 'data':
                raise NotImplementedError(
                    "The action='data' option is a placeholder for future "
                    + "functionality.")

            args = {
                'INTERSECT': intersect
            }

            # Note: in IBE, if 'mcen' argument is present, it is true.
            # If absent, it is false.
            if most_centered:
                args['mcen'] = '1'

            if coordinate is not None:
                c = commons.parse_coordinates(coordinate).transform_to(coord.ICRS)
                args['POS'] = '{0},{1}'.format(c.ra.deg, c.dec.deg)
                if width and height:
                    args['SIZE'] = '{0},{1}'.format(
                        coord.Angle(width).value,
                        coord.Angle(height).value)
                elif width or height:
                    args['SIZE'] = str(coord.Angle(width or height).value)

            if where:
                args['where'] = where

            if columns:
                if isinstance(columns, str):
                    columns = columns.split()
                args['columns'] = ','.join(columns)

            url = "{URL}{action}/{mission}/{dataset}/{table}".format(
                URL=self.URL,
                action=action,
                mission=mission or self.MISSION,
                dataset=dataset or self.DATASET,
                table=table or self.TABLE)

            return self._request('GET', url, args, timeout=self.TIMEOUT)

        def list_missions(self, *, cache=True):
            """
            Return a list of the available missions

            Parameters
            ----------
            cache : bool
                Defaults to True. If set overrides global caching behavior.
                See :ref:`caching documentation <astroquery_cache>`.
            """
            if hasattr(self, '_missions') and cache:
                # extra level caching to avoid redoing the BeautifulSoup parsing
                # unnecessarily
                missions = self._missions
            else:
                url = self.URL + "search/"
                response = self._request('GET', url, timeout=self.TIMEOUT,
                                         cache=cache)

                root = BeautifulSoup(response.text, 'html5lib')
                links = root.find_all('a')

                missions = [os.path.basename(a.attrs['href'].rstrip('/')) for a in links]
                self._missions = missions

            return missions

        def list_datasets(self, *, mission=None, cache=True):
            """
            For a given mission, list the available datasets

            Parameters
            ----------
            mission : str
                A mission name.  Must be one of the valid missions from
                `~astroquery.ipac.irsa.ibe.IbeClass.list_missions`.  Defaults to the
                configured Mission
            cache : bool
                Defaults to True. If set overrides global caching behavior.
                See :ref:`caching documentation <astroquery_cache>`.

            Returns
            -------
            datasets : list
                A list of dataset names
            """
            if mission is None:
                mission = self.MISSION
            if mission not in self.list_missions():
                raise ValueError("Invalid mission specified: {0}."
                                 "Must be one of: {1}"
                                 .format(mission, self.list_missions()))

            url = "{URL}search/{mission}/".format(URL=self.URL, mission=mission)
            response = self._request('GET', url, timeout=self.TIMEOUT,
                                     cache=cache)

            root = BeautifulSoup(response.text, 'html5lib')
            links = root.find_all('a')
            datasets = [a.text for a in links
                        if a.attrs['href'].count('/') >= 4  # shown as '..'; ignore
                        ]

            return datasets

        def list_tables(self, *, mission=None, dataset=None, cache=True):
            """
            For a given mission and dataset (see
            `~astroquery.ipac.irsa.ibe.IbeClass.list_missions`,
            `~astroquery.ipac.irsa.ibe.IbeClass.list_datasets`),
            returns the list of valid table names to query.

            Parameters
            ----------
            mission : str
                A mission name.  Must be one of the valid missions from
                `~astroquery.ipac.irsa.ibe.IbeClass.list_missions`.  Defaults to the
                configured Mission
            dataset : str
                A dataset name.  Must be one of the valid dataset from
                ``list_datsets(mission)``.  Defaults to the configured Dataset
            cache : bool
                Defaults to True. If set overrides global caching behavior.
                See :ref:`caching documentation <astroquery_cache>`.

            Returns
            -------
            tables : list
                A list of table names
            """
            if mission is None:
                mission = self.MISSION
            if dataset is None:
                dataset = self.DATASET

            if mission not in self.list_missions():
                raise ValueError("Invalid mission specified: {0}."
                                 "Must be one of: {1}"
                                 .format(mission, self.list_missions()))

            if dataset not in self.list_datasets(mission=mission, cache=cache):
                raise ValueError("Invalid dataset {0} specified for mission {1}."
                                 "Must be one of: {2}"
                                 .format(dataset, mission,
                                         self.list_datasets(mission=mission, cache=True)))

            url = "{URL}search/{mission}/{dataset}/".format(URL=self.URL,
                                                            mission=mission,
                                                            dataset=dataset)
            response = self._request('GET', url, timeout=self.TIMEOUT,
                                     cache=cache)

            root = BeautifulSoup(response.text, 'html5lib')
            return [tr.find('td').string for tr in root.find_all('tr')[1:]]

        # Unfortunately, the URL construction for each data set is different, and
        # they're not obviously accessible via API
        # def get_data(self, **kwargs):
        #    return self.query_region_async(retrieve_data=True, **kwargs)

        def show_docs(self, *, mission=None, dataset=None, table=None):
            """
            Open the documentation for a given table in a web browser.

            Parameters
            ----------
            mission : str
                The mission to be used (if not the default mission).
            dataset : str
                The dataset to be used (if not the default dataset).
            table : str
                The table to be queried (if not the default table).
            """

            url = "{URL}docs/{mission}/{dataset}/{table}".format(
                URL=self.URL,
                mission=mission or self.MISSION,
                dataset=dataset or self.DATASET,
                table=table or self.TABLE)

            return webbrowser.open(url)

        def get_columns(self, *, mission=None, dataset=None, table=None):
            """
            Get the schema for a given table.

            Parameters
            ----------
            mission : str
                The mission to be used (if not the default mission).
            dataset : str
                The dataset to be used (if not the default dataset).
            table : str
                The table to be queried (if not the default table).

            Returns
            -------
            table : `~astropy.table.Table`
                A table containing a description of the columns
            """

            url = "{URL}search/{mission}/{dataset}/{table}".format(
                URL=self.URL,
                mission=mission or self.MISSION,
                dataset=dataset or self.DATASET,
                table=table or self.TABLE)

            response = self._request(
                'GET', url, {'FORMAT': 'METADATA'}, timeout=self.TIMEOUT)

            # Raise exception, if request failed
            response.raise_for_status()

            return Table.read(response.text, format='ipac', guess=False)

    Ibe = IbeClass()