diff --git a/.github/workflows/ci_devtests.yml b/.github/workflows/ci_devtests.yml index e0f73c1310..7f0b61b132 100644 --- a/.github/workflows/ci_devtests.yml +++ b/.github/workflows/ci_devtests.yml @@ -5,11 +5,13 @@ on: push: branches: - main + - develop tags: - '*' pull_request: branches: - main + - develop schedule: # run every Monday at 5am UTC - cron: '0 5 * * 1' diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml index 9786f85fcf..278b38491e 100644 --- a/.github/workflows/ci_tests.yml +++ b/.github/workflows/ci_tests.yml @@ -5,11 +5,13 @@ on: push: branches: - main + - develop tags: - '*' pull_request: branches: - main + - develop schedule: # run every Monday at 5am UTC - cron: '0 5 * * 1' diff --git a/.github/workflows/sync_fork.yml b/.github/workflows/sync_fork.yml new file mode 100644 index 0000000000..18abb115e6 --- /dev/null +++ b/.github/workflows/sync_fork.yml @@ -0,0 +1,45 @@ +name: Sync Fork +run-name: Sync Fork +on: + schedule: + - cron: '58 23 * * *' # run every day - two minutes to midnight + workflow_dispatch: # to enable manual runs of the workflow + +jobs: + Get-Timestamp: + runs-on: ubuntu-latest + steps: + - run: date + + Sync-With-Upstream: + runs-on: ubuntu-latest + steps: + - run: echo "The job was automatically triggered by a ${{ github.event_name }} event." + - run: echo "This job is now running on a ${{ runner.os }} server hosted by GitHub" + - run: echo "Running on branch ${{ github.ref }}, repository ${{ github.repository }}." + - name: Check out repository code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - run: echo "The ${{ github.repository }} repository has been cloned to the runner." + - name: List files in the repository + run: | + ls ${{ github.workspace }} + - name: Sync repository with upstream + run: | + cd ${{ github.workspace }} + git config --global user.email "jcarmona@eso.org" + git config --global user.name "Nightly Sync" + git remote add upstream https://github.com/astropy/astroquery.git + git remote -v + git fetch upstream main + echo "--- upstream log: " + git log upstream/main --oneline -10 + echo "--- current branch log before merge: " + git log --oneline -10 + git merge upstream/main + echo "--- current branch log after merge: " + git log --oneline -10 + echo "--- push force with lease" + git push --force-with-lease + - run: echo "The job finished with status ${{ job.status }}." diff --git a/CHANGES.rst b/CHANGES.rst index a76ced54bb..675ce9feef 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -182,6 +182,7 @@ eso - Cone search using ``cone_ra`, ``cone_dec`, ``cone_radius`` arguments. [#3339] - Retrieve record count before querying the archive, via ``count_only`` argument. [#3339] - Ask query functions to print the underlying ADQL queries without issuing them. [#3339] +- Add functionality to list and query ESO catalogues. [#XXXX] gaia ^^^^ diff --git a/astroquery/eso/__init__.py b/astroquery/eso/__init__.py index 25b588981a..60296bb40b 100644 --- a/astroquery/eso/__init__.py +++ b/astroquery/eso/__init__.py @@ -9,16 +9,21 @@ class Conf(_config.ConfigNamespace): """ Configuration parameters for `astroquery.eso`. """ - + MAX_ROW_LIMIT = _config.ConfigItem( + 15000000, + 'Maximum number of rows allowed by the TAP service.') ROW_LIMIT = _config.ConfigItem( 1000, - 'Maximum number of rows returned (set to -1 for unlimited).') + 'Maximum number of rows returned (set to -1 for maximum allowed via TAP service).') username = _config.ConfigItem( "", 'Optional default username for ESO archive.') - tap_url = _config.ConfigItem( + tap_obs_url = _config.ConfigItem( "https://archive.eso.org/tap_obs", - 'URL for TAP queries.') + 'URL for TAP observation queries.') + tap_cat_url = _config.ConfigItem( + "https://archive.eso.org/tap_cat", + 'URL for TAP catalogue queries.') conf = Conf() diff --git a/astroquery/eso/core.py b/astroquery/eso/core.py index 30c473b60d..d19797ea86 100644 --- a/astroquery/eso/core.py +++ b/astroquery/eso/core.py @@ -19,6 +19,7 @@ import time import warnings import xml.etree.ElementTree as ET +from contextlib import contextmanager from typing import List, Optional, Tuple, Dict, Set, Union import astropy.utils.data @@ -32,16 +33,26 @@ from astroquery import log from . import conf -from ..exceptions import RemoteServiceError, LoginError, \ - NoResultsWarning, MaxResultsWarning +from ..exceptions import ( + RemoteServiceError, + LoginError, + NoResultsWarning, + MaxResultsWarning, +) from ..query import QueryWithLogin from ..utils import schema -from .utils import _UserParams, raise_if_coords_not_valid, _reorder_columns, \ - _raise_if_has_deprecated_keys, _build_adql_string, \ - DEFAULT_LEAD_COLS_PHASE3, DEFAULT_LEAD_COLS_RAW +from .utils import ( + _UserParams, + raise_if_coords_not_valid, + _reorder_columns, + _raise_if_has_deprecated_keys, + _build_adql_string, + DEFAULT_LEAD_COLS_PHASE3, + DEFAULT_LEAD_COLS_RAW, +) -__all__ = ['Eso', 'EsoClass'] +__all__ = ["Eso", "EsoClass"] class CalSelectorError(Exception): @@ -59,7 +70,7 @@ def __init__(self, username: str, token: str): def _get_exp_time_from_token(self) -> int: # "manual" decoding since jwt is not installed decoded_token = base64.b64decode(self.token.split(".")[1] + "==") - return int(json.loads(decoded_token)['exp']) + return int(json.loads(decoded_token)["exp"]) def _expired(self) -> bool: # we anticipate the expiration time by 10 minutes to avoid issues @@ -71,6 +82,7 @@ class _EsoNames: phase3_table = "ivoa.ObsCore" raw_instruments_column = "instrument" phase3_surveys_column = "obs_collection" + catalogue_schema = "safcat" @staticmethod def ist_table(instrument_name): @@ -87,6 +99,7 @@ def unlimited_maxrec(func): """ decorator to overwrite maxrec for specific queries """ + @functools.wraps(func) def wrapper(self, *args, **kwargs): if not isinstance(self, EsoClass): @@ -94,11 +107,12 @@ def wrapper(self, *args, **kwargs): tmpvar = self.ROW_LIMIT try: - self.ROW_LIMIT = sys.maxsize + self.ROW_LIMIT = conf.MAX_ROW_LIMIT result = func(self, *args, **kwargs) finally: self.ROW_LIMIT = tmpvar return result + return wrapper @@ -106,6 +120,7 @@ class EsoClass(QueryWithLogin): """ User facing class to query the ESO archive """ + USERNAME = conf.username CALSELECTOR_URL = "https://archive.eso.org/calselector/v1/associations" DOWNLOAD_URL = "https://dataportal.eso.org/dataPortal/file/" @@ -133,34 +148,74 @@ def ROW_LIMIT(self, value): # type check if not (value is None or isinstance(value, int)): - raise TypeError(f"ROW_LIMIT attribute must be of type int or None; found {type(value)}") + raise TypeError( + f"ROW_LIMIT attribute must be of type int or None; found {type(value)}" + ) + elif value > conf.MAX_ROW_LIMIT: + raise ValueError( + f"ROW_LIMIT cannot be higher than {conf.MAX_ROW_LIMIT}; found {value}" + ) if value is None or value < 1: - mr = sys.maxsize + mr = conf.MAX_ROW_LIMIT else: mr = value self._ROW_LIMIT = mr - def _tap_url(self) -> str: - url = conf.tap_url - return url + @contextmanager + def _temporary_row_limit(self, row_limit: Optional[int]): + if row_limit is None: + yield + return + tmpvar = self.ROW_LIMIT + try: + self.ROW_LIMIT = row_limit + yield + finally: + self.ROW_LIMIT = tmpvar + + def _tap_urls(self) -> Dict[str, str]: + return { + "tap_obs": conf.tap_obs_url, + "tap_cat": conf.tap_cat_url, + } + + def _tap_url(self, which_tap: str = "tap_obs") -> str: + tap_urls = self._tap_urls() + try: + return tap_urls[which_tap] + except KeyError as exc: + valid_keys = "', '".join(tap_urls.keys()) + raise ValueError(f"which_tap must be one of '{valid_keys}'.") from exc + + def _which_tap(self, tap_url: str = conf.tap_obs_url) -> str: + tap_urls = self._tap_urls() + normalized_tap_url = tap_url.rstrip("/") + for which_tap, known_url in tap_urls.items(): + if normalized_tap_url == known_url.rstrip("/"): + return which_tap + + valid_urls = "', '".join(tap_urls.values()) + raise ValueError(f"tap_url must be one of '{valid_urls}'.") def _authenticate(self, *, username: str, password: str) -> bool: """ Get the access token from ESO SSO provider """ self._auth_info = None - url_params = {"response_type": "id_token token", - "grant_type": "password", - "client_id": "clientid", - "client_secret": "clientSecret", - "username": username, - "password": password} + url_params = { + "response_type": "id_token token", + "grant_type": "password", + "client_id": "clientid", + "client_secret": "clientSecret", + "username": username, + "password": password, + } log.info(f"Authenticating {username} on 'www.eso.org' ...") - response = self._request('GET', self.AUTH_URL, params=url_params) + response = self._request("GET", self.AUTH_URL, params=url_params) if response.status_code == 200: - token = json.loads(response.content)['id_token'] + token = json.loads(response.content)["id_token"] self._auth_info = _AuthInfo(username=username, token=token) log.info("Authentication successful!") return True @@ -168,23 +223,31 @@ def _authenticate(self, *, username: str, password: str) -> bool: log.error("Authentication failed!") return False - def _get_auth_info(self, username: str, *, store_password: bool = False, - reenter_password: bool = False) -> Tuple[str, str]: + def _get_auth_info( + self, + username: str, + *, + store_password: bool = False, + reenter_password: bool = False, + ) -> Tuple[str, str]: """ Get the auth info (user, password) for use in another function """ if username is None: if not self.USERNAME: - raise LoginError("If you do not pass a username to login(), " - "you should configure a default one!") + raise LoginError( + "If you do not pass a username to login(), " + "you should configure a default one!" + ) else: username = self.USERNAME service_name = "astroquery:www.eso.org" # Get password from keyring or prompt password, password_from_keyring = self._get_password( - service_name, username, reenter=reenter_password) + service_name, username, reenter=reenter_password + ) # When authenticated, save password in keyring if needed if password_from_keyring is None and store_password: @@ -192,8 +255,12 @@ def _get_auth_info(self, username: str, *, store_password: bool = False, return username, password - def _login(self, username: str = None, store_password: bool = False, - reenter_password: bool = False) -> bool: + def _login( + self, + username: str = None, + store_password: bool = False, + reenter_password: bool = False, + ) -> bool: """ Login to the ESO User Portal. @@ -210,19 +277,19 @@ def _login(self, username: str = None, store_password: bool = False, on the keyring. Default is `False`. """ - username, password = self._get_auth_info(username=username, - store_password=store_password, - reenter_password=reenter_password) + username, password = self._get_auth_info( + username=username, + store_password=store_password, + reenter_password=reenter_password, + ) return self._authenticate(username=username, password=password) def _get_auth_header(self) -> Dict[str, str]: if self._auth_info and self._auth_info._expired(): - raise LoginError( - "Authentication token has expired! Please log in again." - ) + raise LoginError("Authentication token has expired! Please log in again.") if self._auth_info and not self._auth_info._expired(): - return {'Authorization': 'Bearer ' + self._auth_info.token} + return {"Authorization": "Bearer " + self._auth_info.token} else: return {} @@ -235,29 +302,42 @@ def _maybe_warn_about_table_length(self, table_rowlim_plus_one, row_limit_plus_o warnings.warn("Query returned no results", NoResultsWarning) if len(table_rowlim_plus_one) == row_limit_plus_one: - warnings.warn(f"Results truncated to {self.ROW_LIMIT}. " - "To retrieve all the records set to None the ROW_LIMIT attribute", - MaxResultsWarning) + warnings.warn( + f"Results truncated to {self.ROW_LIMIT}. " + "To retrieve all the records set to None the ROW_LIMIT attribute", + MaxResultsWarning, + ) - def _try_download_pyvo_table(self, - query_str: str, - tap: TAPService) -> Optional[Table]: + def _try_download_pyvo_table( + self, query_str: str, tap: TAPService + ) -> Optional[Table]: table_with_an_extra_row = Table() def message(query_str): - return (f"Error executing the following query:\n\n" - f"{query_str}\n\n" - "See examples here: https://archive.eso.org/tap_obs/examples\n\n" - f"For maximum query freedom use the query_tap method:\n\n" - f' >>> Eso().query_tap( "{query_str}" )\n\n') + try: + which_tap = self._which_tap(tap.baseurl) + except ValueError: + # Keep the original exception path stable for unrecognized/custom TAP URLs. + which_tap = tap.baseurl + return ( + f"Error executing the following query:\n\n" + f"{query_str}\n\n" + "See examples here: https://archive.eso.org/tap_obs/examples\n\n" + f"For maximum query freedom use the query_tap method:\n\n" + f' >>> Eso().query_tap( "{query_str}", which_tap="{which_tap}")\n\n' + ) try: row_limit_plus_one = self.ROW_LIMIT - if self.ROW_LIMIT < sys.maxsize: + if self.ROW_LIMIT < conf.MAX_ROW_LIMIT: row_limit_plus_one = self.ROW_LIMIT + 1 - table_with_an_extra_row = tap.search(query=query_str, maxrec=row_limit_plus_one).to_table() - self._maybe_warn_about_table_length(table_with_an_extra_row, row_limit_plus_one) + table_with_an_extra_row = tap.search( + query=query_str, maxrec=row_limit_plus_one + ).to_table() + self._maybe_warn_about_table_length( + table_with_an_extra_row, row_limit_plus_one + ) except DALQueryError: log.error(message(query_str)) except DALFormatError as e: @@ -265,9 +345,11 @@ def message(query_str): except Exception as e: raise type(e)(f"{e}\n" + message(query_str)) from e - return table_with_an_extra_row[:self.ROW_LIMIT] + return table_with_an_extra_row[: self.ROW_LIMIT] - def tap(self, authenticated: bool = False) -> TAPService: + def tap( + self, authenticated: bool = False, *, which_tap: str = "tap_obs" + ) -> TAPService: if authenticated and not self.authenticated(): raise LoginError( @@ -279,32 +361,36 @@ def tap(self, authenticated: bool = False) -> TAPService: ".login(username=" ) - log.debug(f"Querying from {self._tap_url()}") if authenticated: h = self._get_auth_header() self._session.headers = {**self._session.headers, **h} - tap_service = TAPService(self._tap_url(), session=self._session) + tap_service = TAPService(self._tap_url(which_tap), session=self._session) else: - tap_service = TAPService(self._tap_url()) + tap_service = TAPService(self._tap_url(which_tap)) return tap_service - def query_tap(self, - query: str, *, - authenticated: bool = False, - ) -> Table: + def query_tap( + self, + query: str, + *, + authenticated: bool = False, + which_tap: str = "tap_obs", + ) -> Table: """ Query the ESO TAP service using a free ADQL string. Parameters ---------- - query_str : str + query : str The ADQL query string to be executed. authenticated : bool, optional If ``True``, the query is run as an authenticated user. Authentication must be performed beforehand via :meth:`astroquery.eso.EsoClass.login`. Authenticated queries may be slower. Default is ``False``. + which_tap : {"tap_obs", "tap_cat"}, optional + TAP endpoint to query. Default is ``"tap_obs"``. Returns ------- @@ -317,12 +403,12 @@ def query_tap(self, eso_instance.query_tap("SELECT * FROM ivoa.ObsCore") """ table_to_return = Table() - tap_service = self.tap(authenticated) + tap_service = self.tap(authenticated, which_tap=which_tap) table_to_return = self._try_download_pyvo_table(query, tap_service) return table_to_return @unlimited_maxrec - @deprecated_renamed_argument('cache', None, since='0.4.12') + @deprecated_renamed_argument("cache", None, since="0.4.12") def list_instruments(self, cache=True) -> List[str]: """ List all the available instrument-specific queries offered by the ESO archive. @@ -334,8 +420,10 @@ def list_instruments(self, cache=True) -> List[str]: Deprecated - unused. """ _ = cache # We're aware about disregarding the argument - query_str = ("select table_name from TAP_SCHEMA.tables " - "where schema_name='ist' order by table_name") + query_str = ( + "select table_name from TAP_SCHEMA.tables " + "where schema_name='ist' order by table_name" + ) res = self.query_tap(query_str)["table_name"].data l_res = list(res) @@ -349,7 +437,7 @@ def list_instruments(self, cache=True) -> List[str]: return l_res @unlimited_maxrec - @deprecated_renamed_argument('cache', None, since='0.4.12') + @deprecated_renamed_argument("cache", None, since="0.4.12") def list_surveys(self, *, cache=True) -> List[str]: """ List all the available surveys (phase 3) in the ESO archive. @@ -368,62 +456,132 @@ def list_surveys(self, *, cache=True) -> List[str]: return res @unlimited_maxrec - def list_column(self, table_name: str) -> None: + def _columns_table(self, table_name: str, *, which_tap: str = "tap_obs") -> Table: + if which_tap == "tap_obs": + help_query = ( + "select column_name, datatype, unit, xtype " + f"from TAP_SCHEMA.columns where table_name = '{table_name}'" + ) + else: + schema = _EsoNames.catalogue_schema + help_query = ( + "select column_name, datatype, unit, ucd " + f"from TAP_SCHEMA.columns " + f"where table_name = '{table_name.removeprefix(schema + '.')}'" + ) + return self.query_tap(help_query, which_tap=which_tap) + + @unlimited_maxrec + def _list_column( + self, table_name: str, *, which_tap: str = "tap_obs" + ) -> Optional[Table]: """ - Prints the columns contained in a given table + Prints the columns contained in a given table. """ - help_query = ( - f"select column_name, datatype, xtype, unit " - # TODO: The column description renders output unmanageable - # f", description " - f"from TAP_SCHEMA.columns " - f"where table_name = '{table_name}'") - available_cols = self.query_tap(help_query) + available_cols = self._columns_table(table_name, which_tap=which_tap) count_query = f"select count(*) from {table_name}" - num_records = list(self.query_tap(count_query)[0].values())[0] + num_records = list( + self.query_tap(count_query, which_tap=which_tap)[0].values() + )[0] + + with ( + astropy.conf.set_temp("max_lines", len(available_cols) + 2), + astropy.conf.set_temp("max_width", sys.maxsize), + ): + log.info( + f"\nColumns present in the table {table_name}:\n{available_cols}\n" + f"\nNumber of records present in the table {table_name}:\n{num_records}\n" + ) + + @unlimited_maxrec + def list_catalogues( + self, all_versions: bool = False, cache: bool = True + ) -> List[str]: + """ + List available catalogue tables offered by the ESO archive. + + Parameters + ---------- + all_versions : bool, optional + If True, list all versions of each catalogue table. If False (default), + return only the latest version of each catalogue (as determined by the + TAP_CAT metadata query). + cache : bool, optional + Deprecated and unused. Retained for backwards compatibility. + + Returns + ------- + list[str] + List of catalogue table names. + """ + _ = cache # We're aware about disregarding the argument + schema = _EsoNames.catalogue_schema + + query_str = ( + f"SELECT table_name FROM TAP_SCHEMA.tables as ref " + "LEFT OUTER JOIN TAP_SCHEMA.keys AS k ON ref.table_name = k.from_table " + "LEFT OUTER JOIN TAP_SCHEMA.key_columns AS kc ON k.key_id = kc.key_id " + f"WHERE schema_name='{schema}' " + ) + + if not all_versions: + query_str += ( + "AND cat_id IN ( " + "SELECT t1.cat_id " + "FROM TAP_SCHEMA.tables t1 " + "LEFT JOIN TAP_SCHEMA.tables t2 ON (t1.title = t2.title AND t1.version < t2.version) " + "WHERE t2.title IS NULL)" + ) - with (astropy.conf.set_temp( - "max_lines", len(available_cols) + 2), - astropy.conf.set_temp( - "max_width", sys.maxsize)): - log.info(f"\nColumns present in the table {table_name}:\n{available_cols}\n" - f"\nNumber of records present in the table {table_name}:\n{num_records}\n") + res = self.query_tap(query_str, which_tap="tap_cat") + return list(res["table_name"]) def _query_on_allowed_values( self, - user_params: _UserParams + user_params: _UserParams, + which_tap="tap_obs", ) -> Union[Table, int, str, None]: if user_params.print_help: - self.list_column(user_params.table_name) - return + return self._list_column( + user_params.table_name, which_tap=user_params.which_tap + ) _raise_if_has_deprecated_keys(user_params.column_filters) - raise_if_coords_not_valid(user_params.cone_ra, user_params.cone_dec, user_params.cone_radius) + raise_if_coords_not_valid( + user_params.cone_ra, user_params.cone_dec, user_params.cone_radius + ) - query = _build_adql_string(user_params) + query_str = _build_adql_string(user_params) if user_params.get_query_payload: - return query + return query_str - ret_table = self.query_tap(query=query, authenticated=user_params.authenticated) + ret_table = self.query_tap( + query_str, which_tap=which_tap, authenticated=user_params.authenticated + ) return list(ret_table[0].values())[0] if user_params.count_only else ret_table - @deprecated_renamed_argument(('open_form', 'cache'), (None, None), - since=['0.4.12', '0.4.12']) + @deprecated_renamed_argument( + ("open_form", "cache"), (None, None), since=["0.4.12", "0.4.12"] + ) def query_surveys( - self, - surveys: Union[List[str], str] = None, *, - cone_ra: float = None, cone_dec: float = None, cone_radius: float = None, - columns: Union[List, str] = None, - column_filters: Optional[dict] = None, - top: int = None, - count_only: bool = False, - get_query_payload: bool = False, - help: bool = False, - authenticated: bool = False, - open_form: bool = False, cache: bool = False, + self, + surveys: Union[List[str], str] = None, + *, + cone_ra: float = None, + cone_dec: float = None, + cone_radius: float = None, + columns: Union[List, str] = None, + column_filters: Optional[dict] = None, + top: int = None, + count_only: bool = False, + get_query_payload: bool = False, + help: bool = False, + authenticated: bool = False, + open_form: bool = False, + cache: bool = False, ) -> Union[Table, int, str]: """ Query survey Phase 3 data contained in the ESO archive. @@ -480,40 +638,49 @@ def query_surveys( - When ``get_query_payload`` is ``True``, returns the query string that would be issued to the TAP service given the specified arguments. """ - _ = open_form, cache # make explicit that we are aware these arguments are unused + _ = ( + open_form, + cache, + ) # make explicit that we are aware these arguments are unused column_filters = column_filters if column_filters else {} - user_params = _UserParams(table_name=_EsoNames.phase3_table, - column_name=_EsoNames.phase3_surveys_column, - allowed_values=surveys, - cone_ra=cone_ra, - cone_dec=cone_dec, - cone_radius=cone_radius, - columns=columns, - column_filters=column_filters, - top=top, - count_only=count_only, - get_query_payload=get_query_payload, - print_help=help, - authenticated=authenticated, - ) - t = self._query_on_allowed_values(user_params=user_params) + user_params = _UserParams( + table_name=_EsoNames.phase3_table, + column_name=_EsoNames.phase3_surveys_column, + allowed_values=surveys, + cone_ra=cone_ra, + cone_dec=cone_dec, + cone_radius=cone_radius, + columns=columns, + column_filters=column_filters, + top=top, + count_only=count_only, + get_query_payload=get_query_payload, + print_help=help, + authenticated=authenticated, + ) + t = self._query_on_allowed_values(user_params) t = _reorder_columns(t, DEFAULT_LEAD_COLS_PHASE3) return t - @deprecated_renamed_argument(('open_form', 'cache'), (None, None), - since=['0.4.12', '0.4.12']) + @deprecated_renamed_argument( + ("open_form", "cache"), (None, None), since=["0.4.12", "0.4.12"] + ) def query_main( - self, - instruments: Union[List[str], str] = None, *, - cone_ra: float = None, cone_dec: float = None, cone_radius: float = None, - columns: Union[List, str] = None, - column_filters: Optional[dict] = None, - top: int = None, - count_only: bool = False, - get_query_payload: bool = False, - help: bool = False, - authenticated: bool = False, - open_form: bool = False, cache: bool = False, + self, + instruments: Union[List[str], str] = None, + *, + cone_ra: float = None, + cone_dec: float = None, + cone_radius: float = None, + columns: Union[List, str] = None, + column_filters: Optional[dict] = None, + top: int = None, + count_only: bool = False, + get_query_payload: bool = False, + help: bool = False, + authenticated: bool = False, + open_form: bool = False, + cache: bool = False, ) -> Union[Table, int, str]: """ Query raw data from all instruments contained in the ESO archive. @@ -570,40 +737,49 @@ def query_main( - When ``get_query_payload`` is ``True``, returns the query string that would be issued to the TAP service given the specified arguments. """ - _ = open_form, cache # make explicit that we are aware these arguments are unused + _ = ( + open_form, + cache, + ) # make explicit that we are aware these arguments are unused column_filters = column_filters if column_filters else {} - user_params = _UserParams(table_name=_EsoNames.raw_table, - column_name=_EsoNames.raw_instruments_column, - allowed_values=instruments, - cone_ra=cone_ra, - cone_dec=cone_dec, - cone_radius=cone_radius, - columns=columns, - column_filters=column_filters, - top=top, - count_only=count_only, - get_query_payload=get_query_payload, - print_help=help, - authenticated=authenticated, - ) + user_params = _UserParams( + table_name=_EsoNames.raw_table, + column_name=_EsoNames.raw_instruments_column, + allowed_values=instruments, + cone_ra=cone_ra, + cone_dec=cone_dec, + cone_radius=cone_radius, + columns=columns, + column_filters=column_filters, + top=top, + count_only=count_only, + get_query_payload=get_query_payload, + print_help=help, + authenticated=authenticated, + ) t = self._query_on_allowed_values(user_params) t = _reorder_columns(t, DEFAULT_LEAD_COLS_RAW) return t - @deprecated_renamed_argument(('open_form', 'cache'), (None, None), - since=['0.4.12', '0.4.12']) + @deprecated_renamed_argument( + ("open_form", "cache"), (None, None), since=["0.4.12", "0.4.12"] + ) def query_instrument( - self, - instrument: str, *, - cone_ra: float = None, cone_dec: float = None, cone_radius: float = None, - columns: Union[List, str] = None, - column_filters: Optional[dict] = None, - top: int = None, - count_only: bool = False, - get_query_payload: bool = False, - help: bool = False, - authenticated: bool = False, - open_form: bool = False, cache: bool = False, + self, + instrument: str, + *, + cone_ra: float = None, + cone_dec: float = None, + cone_radius: float = None, + columns: Union[List, str] = None, + column_filters: Optional[dict] = None, + top: int = None, + count_only: bool = False, + get_query_payload: bool = False, + help: bool = False, + authenticated: bool = False, + open_form: bool = False, + cache: bool = False, ) -> Union[Table, int, str]: """ Query instrument-specific raw data contained in the ESO archive. @@ -658,21 +834,26 @@ def query_instrument( - When ``get_query_payload`` is ``True``, returns the query string that would be issued to the TAP service given the specified arguments. """ - _ = open_form, cache # make explicit that we are aware these arguments are unused + _ = ( + open_form, + cache, + ) # make explicit that we are aware these arguments are unused column_filters = column_filters if column_filters else {} - user_params = _UserParams(table_name=_EsoNames.ist_table(instrument), - column_name=None, - allowed_values=None, - cone_ra=cone_ra, - cone_dec=cone_dec, - cone_radius=cone_radius, - columns=columns, - column_filters=column_filters, - top=top, - count_only=count_only, - get_query_payload=get_query_payload, - print_help=help, - authenticated=authenticated) + user_params = _UserParams( + table_name=_EsoNames.ist_table(instrument), + column_name=None, + allowed_values=None, + cone_ra=cone_ra, + cone_dec=cone_dec, + cone_radius=cone_radius, + columns=columns, + column_filters=column_filters, + top=top, + count_only=count_only, + get_query_payload=get_query_payload, + print_help=help, + authenticated=authenticated, + ) t = self._query_on_allowed_values(user_params) t = _reorder_columns(t, DEFAULT_LEAD_COLS_RAW) return t @@ -702,23 +883,22 @@ def get_headers(self, product_ids, *, cache=True): A table where: columns are header keywords, rows are product_ids. """ - _schema_product_ids = schema.Schema( - schema.Or(Column, [schema.Schema(str)])) + _schema_product_ids = schema.Schema(schema.Or(Column, [schema.Schema(str)])) _schema_product_ids.validate(product_ids) # Get all headers result = [] for dp_id in product_ids: response = self._request( - "GET", f"https://archive.eso.org/hdr?DpId={dp_id}", - cache=cache) - root = BeautifulSoup(response.content, 'html5lib') - hdr = root.select('pre')[0].text - header = {'DP.ID': dp_id} - for key_value in hdr.split('\n'): + "GET", f"https://archive.eso.org/hdr?DpId={dp_id}", cache=cache + ) + root = BeautifulSoup(response.content, "html5lib") + hdr = root.select("pre")[0].text + header = {"DP.ID": dp_id} + for key_value in hdr.split("\n"): if "=" in key_value: - key, value = key_value.split('=', 1) + key, value = key_value.split("=", 1) key = key.strip() - value = value.split('/', 1)[0].strip() + value = value.split("/", 1)[0].strip() if key[0:7] != "COMMENT": # drop comments if value == "T": # Convert boolean T to True value = True @@ -745,7 +925,7 @@ def get_headers(self, product_ids, *, cache=True): column_types.append(type(header[key])) # Add all missing elements for item in result: - for (column, column_type) in zip(columns, column_types): + for column, column_type in zip(columns, column_types): if column not in item: item[column] = column_type() # Return as Table @@ -757,12 +937,12 @@ def _get_filename_from_response(response: requests.Response) -> str: filename = re.findall(r"filename=(\S+)", content_disposition) if not filename: raise RemoteServiceError(f"Unable to find filename for {response.url}") - return os.path.basename(filename[0].replace('"', '')) + return os.path.basename(filename[0].replace('"', "")) @staticmethod def _find_cached_file(filename: str) -> bool: files_to_check = [filename] - if filename.endswith(('fits.Z', 'fits.gz')): + if filename.endswith(("fits.Z", "fits.gz")): files_to_check.append(filename.rsplit(".", 1)[0]) for file in files_to_check: if os.path.exists(file): @@ -770,8 +950,9 @@ def _find_cached_file(filename: str) -> bool: return True return False - def _download_eso_file(self, file_link: str, destination: str, - overwrite: bool) -> Tuple[str, bool]: + def _download_eso_file( + self, file_link: str, destination: str, overwrite: bool + ) -> Tuple[str, bool]: block_size = astropy.utils.data.conf.download_block_size headers = self._get_auth_header() with self._session.get(file_link, stream=True, headers=headers) as response: @@ -784,14 +965,15 @@ def _download_eso_file(self, file_link: str, destination: str, os.remove(part_filename) download_required = overwrite or not self._find_cached_file(filename) if download_required: - with open(part_filename, 'wb') as fd: + with open(part_filename, "wb") as fd: for chunk in response.iter_content(chunk_size=block_size): fd.write(chunk) os.rename(part_filename, filename) return filename, download_required - def _download_eso_files(self, file_ids: List[str], destination: Optional[str], - overwrite: bool) -> List[str]: + def _download_eso_files( + self, file_ids: List[str], destination: Optional[str], overwrite: bool + ) -> List[str]: destination = destination or self.cache_location destination = os.path.abspath(destination) os.makedirs(destination, exist_ok=True) @@ -802,7 +984,9 @@ def _download_eso_files(self, file_ids: List[str], destination: Optional[str], file_link = self.DOWNLOAD_URL + file_id log.info(f"Downloading file {i}/{nfiles} {file_link} to {destination}") try: - filename, downloaded = self._download_eso_file(file_link, destination, overwrite) + filename, downloaded = self._download_eso_file( + file_link, destination, overwrite + ) downloaded_files.append(filename) if downloaded: log.info(f"Successfully downloaded dataset {file_id} to {filename}") @@ -822,7 +1006,7 @@ def _unzip_file(self, filename: str) -> str: Note: ``system_tools.gunzip`` does not work with .Z files """ uncompressed_filename = None - if filename.endswith(('fits.Z', 'fits.gz')): + if filename.endswith(("fits.Z", "fits.gz")): uncompressed_filename = filename.rsplit(".", 1)[0] if not os.path.exists(uncompressed_filename): log.info(f"Uncompressing file {filename}") @@ -837,14 +1021,15 @@ def _unzip_files(self, files: List[str]) -> List[str]: if shutil.which(self.GUNZIP): files = [self._unzip_file(file) for file in files] else: - warnings.warn("Unable to unzip files " - "(gunzip is not available on this system)") + warnings.warn( + "Unable to unzip files (gunzip is not available on this system)" + ) return files @staticmethod def _get_unique_files_from_association_tree(xml: str) -> Set[str]: tree = ET.fromstring(xml) - return {element.attrib['name'] for element in tree.iter('file')} + return {element.attrib["name"] for element in tree.iter("file")} def _save_xml(self, payload: bytes, filename: str, destination: str): destination = destination or self.cache_location @@ -855,8 +1040,14 @@ def _save_xml(self, payload: bytes, filename: str, destination: str): with open(filename, "wb") as fd: fd.write(payload) - def get_associated_files(self, datasets: List[str], *, mode: str = "raw", - savexml: bool = False, destination: str = None) -> List[str]: + def get_associated_files( + self, + datasets: List[str], + *, + mode: str = "raw", + savexml: bool = False, + destination: str = None, + ) -> List[str]: """ Invoke Calselector service to find calibration files associated to the provided datasets. @@ -882,33 +1073,45 @@ def get_associated_files(self, datasets: List[str], *, mode: str = "raw", response = self._session.post(self.CALSELECTOR_URL, data=post_data) response.raise_for_status() associated_files = set() - content_type = response.headers['Content-Type'] + content_type = response.headers["Content-Type"] # Calselector can return one or more XML association trees depending on the input. # For a single dataset it returns one XML and content-type = 'application/xml' - if 'application/xml' in content_type: + if "application/xml" in content_type: filename = self._get_filename_from_response(response) xml = response.content associated_files.update(self._get_unique_files_from_association_tree(xml)) if savexml: self._save_xml(xml, filename, destination) # For multiple datasets it returns a multipart message - elif 'multipart/form-data' in content_type: + elif "multipart/form-data" in content_type: msg = email.message_from_string( - f'Content-Type: {content_type}\r\n' + response.content.decode()) + f"Content-Type: {content_type}\r\n" + response.content.decode() + ) for part in msg.get_payload(): filename = part.get_filename() xml = part.get_payload(decode=True) - associated_files.update(self._get_unique_files_from_association_tree(xml)) + associated_files.update( + self._get_unique_files_from_association_tree(xml) + ) if savexml: self._save_xml(xml, filename, destination) else: - raise CalSelectorError(f"Unexpected content-type '{content_type}' for {response.url}") + raise CalSelectorError( + f"Unexpected content-type '{content_type}' for {response.url}" + ) # remove input datasets from calselector results return list(associated_files.difference(set(datasets))) - def retrieve_data(self, datasets, *, continuation=False, destination=None, - with_calib=None, unzip=True): + def retrieve_data( + self, + datasets, + *, + continuation=False, + destination=None, + with_calib=None, + unzip=True, + ): """ Retrieve a list of datasets form the ESO archive. @@ -950,9 +1153,10 @@ def retrieve_data(self, datasets, *, continuation=False, destination=None, if isinstance(datasets, Column): datasets = list(datasets) - if with_calib and with_calib not in ('raw', 'processed'): - raise ValueError("Invalid value for 'with_calib'. " - "It must be 'raw' or 'processed'") + if with_calib and with_calib not in ("raw", "processed"): + raise ValueError( + "Invalid value for 'with_calib'. It must be 'raw' or 'processed'" + ) associated_files = [] if with_calib: @@ -963,7 +1167,8 @@ def retrieve_data(self, datasets, *, continuation=False, destination=None, sorted_datasets = sorted(datasets) for i in range(0, len(sorted_datasets), batch_size): associated_files += self.get_associated_files( - sorted_datasets[i:i + batch_size], mode=with_calib) + sorted_datasets[i:i + batch_size], mode=with_calib + ) associated_files = list(set(associated_files)) log.info(f"Found {len(associated_files)} associated files") except Exception as ex: @@ -977,19 +1182,23 @@ def retrieve_data(self, datasets, *, continuation=False, destination=None, log.info("Done!") return files[0] if files and len(files) == 1 and return_string else files - @deprecated_renamed_argument(('open_form', 'cache'), (None, None), - since=['0.4.12', '0.4.12']) - def query_apex_quicklooks(self, - project_id: Union[List[str], str] = None, *, - columns: Union[List, str] = None, - column_filters: Optional[dict] = None, - top: int = None, - count_only: bool = False, - get_query_payload: bool = False, - help: bool = False, - authenticated: bool = False, - open_form: bool = False, cache: bool = False, - ) -> Union[Table, int, str]: + @deprecated_renamed_argument( + ("open_form", "cache"), (None, None), since=["0.4.12", "0.4.12"] + ) + def query_apex_quicklooks( + self, + project_id: Union[List[str], str] = None, + *, + columns: Union[List, str] = None, + column_filters: Optional[dict] = None, + top: int = None, + count_only: bool = False, + get_query_payload: bool = False, + help: bool = False, + authenticated: bool = False, + open_form: bool = False, + cache: bool = False, + ) -> Union[Table, int, str]: """ APEX data are distributed with quicklook products identified with a different name than other ESO products. This query tool searches by @@ -1037,20 +1246,132 @@ def query_apex_quicklooks(self, - When ``get_query_payload`` is ``True``, returns the query string that would be issued to the TAP service given the specified arguments. """ - _ = open_form, cache # make explicit that we are aware these arguments are unused + _ = ( + open_form, + cache, + ) # make explicit that we are aware these arguments are unused column_filters = column_filters if column_filters else {} - user_params = _UserParams(table_name=_EsoNames.apex_quicklooks_table, - column_name=_EsoNames.apex_quicklooks_pid_column, - allowed_values=project_id, - cone_ra=None, cone_dec=None, cone_radius=None, - columns=columns, - column_filters=column_filters, - top=top, - count_only=count_only, - get_query_payload=get_query_payload, - print_help=help, - authenticated=authenticated) + user_params = _UserParams( + table_name=_EsoNames.apex_quicklooks_table, + column_name=_EsoNames.apex_quicklooks_pid_column, + allowed_values=project_id, + cone_ra=None, + cone_dec=None, + cone_radius=None, + columns=columns, + column_filters=column_filters, + top=top, + count_only=count_only, + get_query_payload=get_query_payload, + print_help=help, + authenticated=authenticated, + ) return self._query_on_allowed_values(user_params) + def query_catalogue( + self, + catalogue: str, + *, + cone_ra: float = None, + cone_dec: float = None, + cone_radius: float = None, + columns: Union[List, str] = None, + column_filters: Optional[dict] = None, + top: int = None, + count_only: bool = False, + get_query_payload: bool = False, + help: bool = False, + authenticated: bool = False, + open_form: bool = False, + cache: bool = False, + ROW_LIMIT: Optional[int] = None, + ) -> Union[Table, int, str]: + """ + Query catalogue data contained in the ESO archive. + + Parameters + ---------- + catalogue : str + Name of the catalogue to query. Should be ONLY ONE of the names + returned by :meth:`~astroquery.eso.EsoClass.list_catalogues`. + cone_ra : float, optional + Not yet implemented. + Cone Search Center - Right Ascension in degrees. + cone_dec : float, optional + Not yet implemented. + Cone Search Center - Declination in degrees. + cone_radius : float, optional + Not yet implemented. + Cone Search Radius in degrees. + columns : str or list of str, optional + Name of the columns the query should return. If specified as a string, + it should be a comma-separated list of column names. + top : int, optional + When set to ``N``, returns only the top ``N`` records. + count_only : bool, optional + If ``True``, returns only an ``int``: the count of the records + the query would return when set to ``False``. Default is ``False``. + get_query_payload : bool, optional + If ``True``, returns only a ``str``: the query string that + would be issued to the TAP service. Default is ``False``. + help : bool, optional + If ``True``, prints all the parameters accepted in ``column_filters`` + and ``columns``. Default is ``False``. + authenticated : bool, optional + If ``True``, runs the query as an authenticated user. + Authentication must be done beforehand via + :meth:`~astroquery.eso.EsoClass.login`. Note that authenticated queries + are slower. Default is ``False``. + column_filters : dict or None, optional + Constraints applied to the query in ADQL syntax, + e.g., ``{"mag": "< 20"}``. + Default is ``None``. + open_form : bool, optional + **Deprecated** - unused. + cache : bool, optional + **Deprecated** - unused. + ROW_LIMIT : int, optional + Overrides the configured (eso.ROW_LIMIT) row limit for this query only. + + Returns + ------- + astropy.table.Table, str, int, or None + - By default, returns an :class:`~astropy.table.Table` containing records + based on the specified columns and constraints. Returns ``None`` if no results. + - When ``count_only`` is ``True``, returns an ``int`` representing the + record count for the specified filters. + - When ``get_query_payload`` is ``True``, returns the query string that + would be issued to the TAP service given the specified arguments. + """ + _ = ( + open_form, + cache, + ) # make explicit that we are aware these arguments are unused + column_filters = column_filters if column_filters else {} + + schema = _EsoNames.catalogue_schema + table_name = f"{schema}.{catalogue}" + + with self._temporary_row_limit(ROW_LIMIT): + which_tap = "tap_cat" + user_params = _UserParams( + table_name=table_name, + column_name=None, + allowed_values=None, + cone_ra=None, + cone_dec=None, + cone_radius=None, + columns=columns, + column_filters=column_filters, + top=top, + count_only=count_only, + get_query_payload=get_query_payload, + print_help=help, + authenticated=authenticated, + which_tap=which_tap, + ) + + return self._query_on_allowed_values(user_params, which_tap=which_tap) + Eso = EsoClass() diff --git a/astroquery/eso/tests/data/kids_dr4_sample.csv b/astroquery/eso/tests/data/kids_dr4_sample.csv new file mode 100644 index 0000000000..644cbb9e2c --- /dev/null +++ b/astroquery/eso/tests/data/kids_dr4_sample.csv @@ -0,0 +1,6 @@ +Level,ALPHA_J2000,A_IMAGE,A_WORLD,Agaper,Agaper_0p7,Agaper_1p0,BPZ_FILT,BPZ_FLAGFILT,BPZ_NONDETFILT,B_IMAGE,B_WORLD,BackGr,Bgaper,Bgaper_0p7,Bgaper_1p0,CHI_SQUARED_BPZ,CLASS_STAR,COLOUR_GAAP_H_Ks,COLOUR_GAAP_J_H,COLOUR_GAAP_Y_J,COLOUR_GAAP_Z_Y,COLOUR_GAAP_g_r,COLOUR_GAAP_i_Z,COLOUR_GAAP_r_i,COLOUR_GAAP_u_g,CXX_WORLD,CXY_WORLD,CYY_WORLD,DECJ2000,DELTA_J2000,ERRA_IMAGE,ERRA_WORLD,ERRB_IMAGE,ERRB_WORLD,ERRCXX_WORLD,ERRCXY_WORLD,ERRCYY_WORLD,ERRTHETA_J2000,ERRTHETA_WORLD,ERRX2_WORLD,ERRXY_WORLD,ERRY2_WORLD,EXTINCTION_H,EXTINCTION_J,EXTINCTION_Ks,EXTINCTION_Y,EXTINCTION_Z,EXTINCTION_g,EXTINCTION_i,EXTINCTION_r,EXTINCTION_u,FIELD_POS,FLAG_GAAP_0p7_H,FLAG_GAAP_0p7_J,FLAG_GAAP_0p7_Ks,FLAG_GAAP_0p7_Y,FLAG_GAAP_0p7_Z,FLAG_GAAP_0p7_g,FLAG_GAAP_0p7_i,FLAG_GAAP_0p7_r,FLAG_GAAP_0p7_u,FLAG_GAAP_1p0_H,FLAG_GAAP_1p0_J,FLAG_GAAP_1p0_Ks,FLAG_GAAP_1p0_Y,FLAG_GAAP_1p0_Z,FLAG_GAAP_1p0_g,FLAG_GAAP_1p0_i,FLAG_GAAP_1p0_r,FLAG_GAAP_1p0_u,FLAG_GAAP_H,FLAG_GAAP_J,FLAG_GAAP_Ks,FLAG_GAAP_Y,FLAG_GAAP_Z,FLAG_GAAP_g,FLAG_GAAP_i,FLAG_GAAP_r,FLAG_GAAP_u,FLUXERR_APER_10,FLUXERR_APER_100,FLUXERR_APER_14,FLUXERR_APER_20,FLUXERR_APER_30,FLUXERR_APER_4,FLUXERR_APER_40,FLUXERR_APER_6,FLUXERR_APER_60,FLUXERR_APER_8,FLUXERR_AUTO,FLUXERR_GAAP_0p7_H,FLUXERR_GAAP_0p7_J,FLUXERR_GAAP_0p7_Ks,FLUXERR_GAAP_0p7_Y,FLUXERR_GAAP_0p7_Z,FLUXERR_GAAP_0p7_g,FLUXERR_GAAP_0p7_i,FLUXERR_GAAP_0p7_r,FLUXERR_GAAP_0p7_u,FLUXERR_GAAP_1p0_H,FLUXERR_GAAP_1p0_J,FLUXERR_GAAP_1p0_Ks,FLUXERR_GAAP_1p0_Y,FLUXERR_GAAP_1p0_Z,FLUXERR_GAAP_1p0_g,FLUXERR_GAAP_1p0_i,FLUXERR_GAAP_1p0_r,FLUXERR_GAAP_1p0_u,FLUXERR_GAAP_H,FLUXERR_GAAP_J,FLUXERR_GAAP_Ks,FLUXERR_GAAP_Y,FLUXERR_GAAP_Z,FLUXERR_GAAP_g,FLUXERR_GAAP_i,FLUXERR_GAAP_r,FLUXERR_GAAP_u,FLUXERR_ISO,FLUXERR_ISOCOR,FLUX_APER_10,FLUX_APER_100,FLUX_APER_14,FLUX_APER_20,FLUX_APER_30,FLUX_APER_4,FLUX_APER_40,FLUX_APER_6,FLUX_APER_60,FLUX_APER_8,FLUX_AUTO,FLUX_GAAP_0p7_H,FLUX_GAAP_0p7_J,FLUX_GAAP_0p7_Ks,FLUX_GAAP_0p7_Y,FLUX_GAAP_0p7_Z,FLUX_GAAP_0p7_g,FLUX_GAAP_0p7_i,FLUX_GAAP_0p7_r,FLUX_GAAP_0p7_u,FLUX_GAAP_1p0_H,FLUX_GAAP_1p0_J,FLUX_GAAP_1p0_Ks,FLUX_GAAP_1p0_Y,FLUX_GAAP_1p0_Z,FLUX_GAAP_1p0_g,FLUX_GAAP_1p0_i,FLUX_GAAP_1p0_r,FLUX_GAAP_1p0_u,FLUX_GAAP_H,FLUX_GAAP_J,FLUX_GAAP_Ks,FLUX_GAAP_Y,FLUX_GAAP_Z,FLUX_GAAP_g,FLUX_GAAP_i,FLUX_GAAP_r,FLUX_GAAP_u,FLUX_ISO,FLUX_ISOCOR,FLUX_RADIUS,FWHM_IMAGE,FWHM_WORLD,Flag,HTM,ID,IMAFLAGS_ISO,ISO0,ISO1,ISO2,ISO3,ISO4,ISO5,ISO6,ISO7,ISOAREA_WORLD,KIDS_TILE,KRON_RADIUS,MAGERR_APER_10,MAGERR_APER_100,MAGERR_APER_14,MAGERR_APER_20,MAGERR_APER_4,MAGERR_APER_40,MAGERR_APER_6,MAGERR_APER_60,MAGERR_APER_8,MAGERR_AUTO,MAGERR_GAAP_0p7_H,MAGERR_GAAP_0p7_J,MAGERR_GAAP_0p7_Ks,MAGERR_GAAP_0p7_Y,MAGERR_GAAP_0p7_Z,MAGERR_GAAP_0p7_g,MAGERR_GAAP_0p7_i,MAGERR_GAAP_0p7_r,MAGERR_GAAP_0p7_u,MAGERR_GAAP_1p0_H,MAGERR_GAAP_1p0_J,MAGERR_GAAP_1p0_Ks,MAGERR_GAAP_1p0_Y,MAGERR_GAAP_1p0_Z,MAGERR_GAAP_1p0_g,MAGERR_GAAP_1p0_i,MAGERR_GAAP_1p0_r,MAGERR_GAAP_1p0_u,MAGERR_GAAP_H,MAGERR_GAAP_J,MAGERR_GAAP_Ks,MAGERR_GAAP_Y,MAGERR_GAAP_Z,MAGERR_GAAP_g,MAGERR_GAAP_i,MAGERR_GAAP_r,MAGERR_GAAP_u,MAGERR_ISO,MAGERR_ISOCOR,MAGGERR_APER_30,MAG_APER_10,MAG_APER_100,MAG_APER_14,MAG_APER_20,MAG_APER_30,MAG_APER_4,MAG_APER_40,MAG_APER_6,MAG_APER_60,MAG_APER_8,MAG_AUTO,MAG_GAAP_0p7_H,MAG_GAAP_0p7_J,MAG_GAAP_0p7_Ks,MAG_GAAP_0p7_Y,MAG_GAAP_0p7_Z,MAG_GAAP_0p7_g,MAG_GAAP_0p7_i,MAG_GAAP_0p7_r,MAG_GAAP_0p7_u,MAG_GAAP_1p0_H,MAG_GAAP_1p0_J,MAG_GAAP_1p0_Ks,MAG_GAAP_1p0_Y,MAG_GAAP_1p0_Z,MAG_GAAP_1p0_g,MAG_GAAP_1p0_i,MAG_GAAP_1p0_r,MAG_GAAP_1p0_u,MAG_GAAP_H,MAG_GAAP_J,MAG_GAAP_Ks,MAG_GAAP_Y,MAG_GAAP_Z,MAG_GAAP_g,MAG_GAAP_i,MAG_GAAP_r,MAG_GAAP_u,MAG_ISO,MAG_ISOCOR,MAG_LIM_H,MAG_LIM_J,MAG_LIM_Ks,MAG_LIM_Y,MAG_LIM_Z,MAG_LIM_g,MAG_LIM_i,MAG_LIM_r,MAG_LIM_u,MASK,MU_MAX,MU_THRESHOLD,M_0,MaxVal,NBPZ_FILT,NBPZ_FLAGFILT,NBPZ_NONDETFILT,NIMAFLAGS_ISO,ODDS,PAgaap,RAJ2000,SG2DPHOT,SG_FLAG,SID,SLID,S_ELLIPTICITY,S_ELONGATION,SeqNr,THELI_NAME,THETA_J2000,THETA_WORLD,T_B,T_ML,X2_WORLD,XMAX_IMAGE,XMIN_IMAGE,XY_WORLD,X_WORLD,Xpos,Y2_WORLD,YMAX_IMAGE,YMIN_IMAGE,Y_WORLD,Ypos,Z_B,Z_B_MAX,Z_B_MIN,Z_ML +0.03316526114940643,5.079035,1.023542,6.084905908210203e-05,0.7300000190734863,0.7300000190734863,1.0199999809265137,511,0,0,0.7522829999999999,4.469737905310467e-05,-0.0017154590459540486,0.7200000286102295,0.7200000286102295,1.0099999904632568,0.729,0.464847594499588,0.2999153137207031,0.49968910217285156,0.14684677124023438,0.406768798828125,1.3296089172363281,0.9521522521972656,0.38743019104003906,-0.6200618743896484,0.0036126889754086733,-0.000762108713388443,0.002087776083499193,-28.686515,-28.686515,0.15672509372234344,9.317543117504101e-06,0.11101970076560974,6.595674221898662e-06,8.399833313887939e-05,-2.136586954293307e-05,4.6321190893650055e-05,14.778429985046387,75.22157287597656,4.632118993930234e-11,1.0683040389813936e-11,8.39983291256452e-11,0.007836037315428257,0.012345454655587673,0.005248666275292635,0.01899869367480278,0.022029614076018333,0.057601768523454666,0.02961180917918682,0.03984864056110382,0.07392487674951553,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1980980932712555,1.9727469682693481,0.2766576111316681,0.39451149106025696,0.5913798809051514,0.08062147349119186,0.7879332900047302,0.11983469873666763,1.1810959577560425,0.15883159637451172,0.2735537886619568,196.6279754638672,124.66181182861328,238.99668884277344,158.6905059814453,69.5469970703125,2.6999999458432455e-11,1.7100000582193076e-10,4.109999840462564e-11,6.479999870023789e-11,251.62139892578125,156.7567138671875,308.53338623046875,190.8169403076172,85.86070251464844,3.0600001699188084e-11,2.0700000047391143e-10,4.609999881832749e-11,7.229999932079068e-11,196.6279754638672,124.66181182861328,238.99668884277344,158.6905059814453,69.5469970703125,2.6999999458432455e-11,1.7100000582193076e-10,4.109999840462564e-11,6.479999870023789e-11,0.0746077224612236,0.1772087961435318,1.596519947052002,2.49216890335083,2.030400037765503,2.7329230308532715,4.337295055389404,0.5427271127700806,4.349409103393555,0.908402681350708,3.3192410469055176,1.28159499168396,1.8628959655761719,2737.440185546875,1720.6212158203125,3617.1357421875,1493.7296142578125,1024.1282958984375,7.939399832013194e-11,4.504099870850098e-10,3.074500098954047e-10,1.2166000151747625e-10,3256.905029296875,2114.560302734375,4415.322265625,1885.77685546875,1198.38671875,9.303999931598028e-11,3.9882999680607156e-10,3.5764000094751225e-10,9.228499908697785e-11,2737.440185546875,1720.6212158203125,3617.1357421875,1493.7296142578125,1024.1282958984375,7.939399832013194e-11,4.504099870850098e-10,3.074500098954047e-10,1.2166000151747625e-10,0.49366798996925354,1.1097660064697266,3.0711519718170166,4.069960117340088,0.00024193650460802019,2,1405256194,KiDSDR4 J002018.968-284111.45,0,8,7,7,6,5,4,4,3,2.826913991782476e-08,KIDS_5.6_-28.2,7.95773983001709,0.13475219905376434,0.8596541881561279,0.14797580242156982,0.15676969289779663,0.16132399439811707,0.19673840701580048,0.14326299726963043,0.3864349126815796,0.1345909982919693,0.15947189927101135,0.07798749953508377,0.0786634013056755,0.07173839956521988,0.11534599959850311,0.0737306997179985,0.3692328929901123,0.41220420598983765,0.14514149725437164,0.5782977342605591,0.08388160169124603,0.08048789948225021,0.07586889714002609,0.10986299812793732,0.07778959721326828,0.3570886552333832,0.5635167360305786,0.13995201885700226,0.8506119847297668,0.07798749953508377,0.0786634013056755,0.07173839956521988,0.11534599959850311,0.0737306997179985,0.3692328929901123,0.41220420598983765,0.14514149725437164,0.5782977342605591,0.16412639617919922,0.17341390252113342,0.1480734944343567,24.15205955505371,23.668560028076172,23.891050338745117,23.568429946899414,23.06694984436035,25.323549270629883,23.063919067382812,24.764299392700195,23.35740089416504,24.3906192779541,23.984529495239258,21.406600952148438,21.91080093383789,21.10409927368164,22.064300537109375,22.47410011291504,25.178863525390625,23.433834075927734,23.831501007080078,24.575124740600586,21.218000411987305,21.686899185180664,20.88759994506836,21.81130027770996,22.303499221801758,25.00748062133789,23.570972442626953,23.669971466064453,24.882030487060547,21.398765563964844,21.898454666137695,21.09885025024414,22.04530143737793,22.452070236206055,25.121261596679688,23.40422248840332,23.79165267944336,24.50119972229004,25.426410675048828,24.546920776367188,24.265886306762695,24.760665893554688,24.054019927978516,24.49862289428711,25.394304275512695,26.34992218017578,24.485366821289062,26.016332626342773,25.259056091308594,0,24.143320083618164,25.12795066833496,23.523,0.07370539754629135,9,0,0,0,0.61812,-76.69999694824219,5.079035,0,1.0,4343,60513621,0.2650201916694641,1.3605819940567017,4344,KIDS_5p6_m28p2,13.277409553527832,76.72258758544922,1.6360000000000001,1.6360000000000001,2.0877759521198413e-09,18819,18817,3.8105821276168683e-10,5.079035,18817.859375,3.6126890368137765e-09,2168,2165,-28.686515,2166.279052734375,0.7899999999999999,0.97,0.6699999999999999,0.7799999999999999 +0.0331641286611557,5.127818,2.087884,0.00012409189366735518,0.8299999833106995,0.8299999833106995,1.100000023841858,511,0,0,1.929386,0.00011468859884189442,0.0009604087099432945,0.8100000023841858,0.8100000023841858,1.0800000429153442,3.303,0.017473550513386726,0.4565296173095703,0.1604766845703125,0.12378120422363281,0.1814556121826172,0.7199001312255859,0.5032062530517578,0.6213703155517578,0.6133289337158203,0.01324538979679346,-0.0008897571824491024,0.01530689001083374,-28.686661,-28.686661,0.08034873753786087,4.775493835040834e-06,0.07493723183870316,4.454465852177236e-06,1.9969149434473366e-05,-1.1997229876214988e-06,2.2678470486425795e-05,78.05769348144531,11.942299842834473,2.267847021286684e-11,5.998674864129971e-13,1.9969149597787172e-11,0.008384065702557564,0.013208858668804169,0.005615742411464453,0.020327404141426086,0.02357029914855957,0.061630260199308395,0.031682759523391724,0.04263553023338318,0.07909496128559113,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2021384984254837,1.967947006225586,0.27962151169776917,0.39648279547691345,0.5924813747406006,0.08512426912784576,0.7888457775115967,0.12468740344047546,1.1816530227661133,0.16327069699764252,0.40961921215057373,251.87571716308594,167.1168975830078,208.3955841064453,143.0128631591797,52.4952278137207,2.730000080164441e-11,1.340000055360946e-10,4.210000056903418e-11,6.539999791721485e-11,309.8416748046875,204.4779510498047,258.7093811035156,170.1577606201172,63.23879623413086,3.13000007856612e-11,1.5999999936067155e-10,4.7899999938705307e-11,7.429999671071386e-11,251.87571716308594,167.1168975830078,208.3955841064453,143.0128631591797,52.4952278137207,2.730000080164441e-11,1.340000055360946e-10,4.210000056903418e-11,6.539999791721485e-11,0.18546420335769653,0.29874908924102783,5.327457904815674,5.995962142944336,6.273825168609619,6.970154762268066,7.856791973114014,1.679190993309021,7.93869686126709,3.189857006072998,6.079957008361816,4.419428825378418,7.018610000610352,4051.90087890625,3479.613037109375,6185.0205078125,3084.215087890625,2601.79443359375,4.301299871833919e-10,1.7293999565737295e-09,9.510400245105188e-10,2.114200065017613e-10,4348.30419921875,3868.227783203125,6566.3017578125,3274.38037109375,2917.63671875,4.848499934873018e-10,1.8596999495912314e-09,9.914600251903494e-10,2.552000000211052e-10,4051.90087890625,3479.613037109375,6185.0205078125,3084.215087890625,2601.79443359375,4.301299871833919e-10,1.7293999565737295e-09,9.510400245105188e-10,2.114200065017613e-10,5.152454853057861,6.596183776855469,3.2383029460906982,7.050258159637451,0.00041909870924428105,0,1940157430,KiDSDR4 J002030.676-284111.97,0,59,57,50,42,30,24,15,5,2.0848490578373458e-07,KIDS_5.6_-28.2,5.154382228851318,0.041205838322639465,0.35643818974494934,0.04840252920985222,0.0617748498916626,0.05505327880382538,0.10791269689798355,0.042450349777936935,0.21106639504432678,0.040121011435985565,0.06338100135326385,0.06749189645051956,0.0521451011300087,0.036582399159669876,0.0503447987139225,0.021906400099396706,0.06891079246997833,0.08412666618824005,0.04806263744831085,0.33585819602012634,0.07736489921808243,0.05739299952983856,0.04277750104665756,0.05642180144786835,0.02353299967944622,0.07009083777666092,0.09341172873973846,0.05245472490787506,0.31610578298568726,0.06749189645051956,0.0521451011300087,0.036582399159669876,0.0503447987139225,0.021906400099396706,0.06891079246997833,0.08412666618824005,0.04806263744831085,0.33585819602012634,0.039090901613235474,0.04918624088168144,0.08189535140991211,22.843700408935547,22.715349197387695,22.666170120239258,22.551889419555664,22.421890258789062,24.09724998474121,22.410629272460938,23.400569915771484,22.70025062561035,23.04659080505371,22.544370651245117,20.980899810791016,21.14620018005371,20.5216007232666,21.277099609375,21.46179962158203,23.344335556030273,21.97311782836914,22.605440139770508,23.975130081176758,20.904199600219727,21.031200408935547,20.45669937133789,21.212200164794922,21.337400436401367,23.215137481689453,21.899335861206055,22.562896728515625,23.77765655517578,20.972515106201172,21.132991790771484,20.5159854888916,21.256772994995117,21.438228607177734,23.282705307006836,21.941434860229492,22.56280517578125,23.896034240722656,22.879959106445312,22.611770629882812,23.997034072875977,24.44244956970215,24.202777862548828,24.611562728881836,25.69969940185547,26.33792495727539,24.750093460083008,25.990232467651367,25.24905014038086,12292,23.234149932861328,25.12795066833496,21.844,0.17028109729290009,9,0,0,0,0.95672,-11.699999809265137,5.127818,0,1.0,4349,60513621,0.07591354846954346,1.0821499824523926,4350,KIDS_5p6_m28p2,78.32723999023438,11.672760009765625,2.818,2.818,1.530688997775087e-08,18102,18093,4.44882991557094e-10,5.127818,18097.859375,1.3245379903992216e-08,2171,2162,-28.686661,2167.06591796875,0.8300000000000001,0.92,0.7899999999999999,0.8300000000000001 +0.03320556879043579,5.171088,2.6607149999999997,0.0001581599935889244,0.8999999761581421,0.8999999761581421,1.149999976158142,511,0,0,2.431581,0.00014451940660364926,-0.0012118120212107897,0.8700000047683716,0.8700000047683716,1.1299999952316284,4.211,0.023555999621748924,0.26761817932128906,0.28167724609375,0.21369171142578125,0.12752342224121094,0.5717144012451172,0.3171119689941406,0.5846939086914062,0.40755653381347656,0.02248905971646309,0.004024359863251448,0.02341138944029808,-28.68675,-28.68675,0.06320922076702118,3.757583954211441e-06,0.0549326092004776,3.264565066274372e-06,1.1484959941299167e-05,2.953092916868627e-06,1.3291860341269057e-05,-60.73038101196289,-29.269620895385742,1.3291859800312888e-11,-1.4765609524999834e-12,1.1484959684671114e-11,0.008726082742214203,0.01374769676476717,0.005844829138368368,0.021156635135412216,0.02453181892633438,0.06414438784122467,0.03297523036599159,0.04437479004263878,0.08232153952121735,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.20699100196361542,1.980178952217102,0.2839707136154175,0.4002367854118347,0.5956223011016846,0.08929155021905899,0.792570173740387,0.12924690544605255,1.1906169652938843,0.16821430623531342,0.4653717875480652,266.2980041503906,146.86647033691406,284.1306457519531,170.8724822998047,77.06451416015625,2.7900000018621363e-11,1.4100000333971963e-10,4.289999952500345e-11,6.510000177817332e-11,325.5726623535156,176.05889892578125,346.78216552734375,201.66734313964844,91.30030822753906,3.199999987213431e-11,1.660000054082289e-10,4.879999876417074e-11,7.420000031066465e-11,266.2980041503906,146.86647033691406,284.1306457519531,170.8724822998047,77.06451416015625,2.7900000018621363e-11,1.4100000333971963e-10,4.289999952500345e-11,6.510000177817332e-11,0.2510314881801605,0.35853201150894165,10.1139497756958,9.025279998779297,12.638589859008789,14.521349906921387,15.874529838562012,3.0002949237823486,16.144920349121094,5.660746097564697,17.23090934753418,8.114038467407227,15.060689926147461,7332.3759765625,5630.73046875,9407.111328125,4593.22998046875,4071.43408203125,9.458900329661901e-10,3.211299892669217e-09,1.8258999867626358e-09,5.615800047209518e-10,7973.56201171875,6089.32763671875,9826.095703125,4967.423828125,4375.4306640625,1.038599983793631e-09,3.5336999992807705e-09,1.9852999244562852e-09,6.130200236320604e-10,7332.3759765625,5630.73046875,9407.111328125,4593.22998046875,4071.43408203125,9.458900329661901e-10,3.211299892669217e-09,1.8258999867626358e-09,5.615800047209518e-10,12.042059898376465,14.088139533996582,3.7381560802459717,7.203877925872803,0.00042823050171136856,0,1641070272,KiDSDR4 J002041.061-284112.29,0,109,104,87,64,49,35,20,11,3.851669987398054e-07,KIDS_5.6_-28.2,4.601593971252441,0.022225959226489067,0.2382722944021225,0.024400850757956505,0.029932279139757156,0.03232036158442497,0.053312819451093674,0.02479569986462593,0.07504016906023026,0.022514160722494125,0.03355715051293373,0.03943189978599548,0.02831929922103882,0.032793398946523666,0.04039039835333824,0.02055089920759201,0.03202490508556366,0.04767191410064697,0.025509655475616455,0.12586171925067902,0.04433229938149452,0.03139159828424454,0.03831779956817627,0.04407870024442673,0.022655600681900978,0.03345229849219322,0.051003821194171906,0.026688121259212494,0.13141760230064392,0.03943189978599548,0.02831929922103882,0.032793398946523666,0.04039039835333824,0.02055089920759201,0.03202490508556366,0.04767191410064697,0.025509655475616455,0.12586171925067902,0.022638989612460136,0.027637850493192673,0.04074741154909134,22.1476993560791,22.271350860595703,21.905750274658203,21.754980087280273,21.65825080871582,23.467090606689453,21.639909744262695,22.777809143066406,21.569229125976562,22.38690948486328,21.715389251708984,20.33690071105957,20.623600006103516,20.0664005279541,20.84469985961914,20.97559928894043,22.488731384277344,21.30115509033203,21.897247314453125,22.914464950561523,20.245899200439453,20.53860092163086,20.018999099731445,20.759700775146484,20.89739990234375,22.38803482055664,21.202369689941406,21.80902099609375,22.826169967651367,20.328174591064453,20.609851837158203,20.060556411743164,20.823543548583984,20.951066970825195,22.42458724975586,21.268178939819336,21.852872848510742,22.832143783569336,21.958250045776367,21.787870407104492,23.936580657958984,24.582693099975586,23.8662052154541,24.418319702148438,25.28286361694336,26.31432342529297,24.694807052612305,25.96979331970215,25.254039764404297,16,22.62466049194336,25.12795066833496,21.049,0.2985140085220337,9,0,0,0,0.99565,38.5,5.171088,0,1.0,4358,60513621,0.08611738681793213,1.0942319631576538,4359,KIDS_5p6_m28p2,-51.45418167114258,-38.54581832885742,3.364,3.364,2.3411390159822076e-08,17466,17453,-2.012199962209138e-09,5.171088,17459.23046875,2.2489059503527642e-08,2174,2163,-28.68675,2168.2099609375,0.8600000000000001,0.89,0.7899999999999999,0.8600000000000001 +0.025127040222287178,5.912251,201.661499,0.011986199766397476,2.0,2.0,2.0,510,0,1,102.667236,0.006104231812059879,0.20623379945755005,2.0,2.0,2.0,222.029,0.0003681149100884795,-0.9134559631347656,0.07864570617675781,-0.4123420715332031,0.9540748596191406,0.3177051544189453,0.9476261138916016,0.001316070556640625,,38.00328826904297,17.704729080200195,142.92750549316406,-28.648329,-28.648329,0.0652417466044426,3.877772087435005e-06,0.030923010781407356,1.8386889450994204e-06,3.465592044449295e-06,1.981326022360008e-06,1.4952300261938944e-05,-85.1066665649414,-4.893333911895752,1.4952299814963155e-11,-9.906730383951734e-13,3.4655919627091247e-12,0.006526535842567682,0.010282372124493122,0.004371547605842352,0.015823770314455032,0.01834818534553051,0.04797577112913132,0.02466329000890255,0.03318941965699196,0.061571091413497925,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.23805120587348938,2.215264081954956,0.35368359088897705,0.525692880153656,0.8124848008155823,0.08366984128952026,1.0661189556121826,0.1278619021177292,1.4753819704055786,0.18171200156211853,17.696800231933594,855.2486572265625,400.5097961425781,950.0929565429688,484.01983642578125,235.7167205810547,3.769999937230928e-11,2.2299999347108468e-10,6.559999765620717e-11,,855.2486572265625,400.5097961425781,950.0929565429688,484.01983642578125,235.7167205810547,3.769999937230928e-11,2.2299999347108468e-10,6.559999765620717e-11,,855.2486572265625,400.5097961425781,950.0929565429688,484.01983642578125,235.7167205810547,3.769999937230928e-11,2.2299999347108468e-10,6.559999765620717e-11,,11.132800102233887,12.957690238952637,15.784859657287598,1704.470947265625,32.00090026855469,66.90850830078125,152.60589599609375,2.4939560890197754,275.4986877441406,5.55715799331665,624.2496948242188,9.973380088806152,66054.453125,23248.056640625,21549.865234375,10043.4482421875,31343.283203125,12986.73828125,3.6842000561421173e-09,5.742299968858333e-09,5.602499797419114e-09,,23248.056640625,21549.865234375,10043.4482421875,31343.283203125,12986.73828125,3.6842000561421173e-09,5.742299968858333e-09,5.602499797419114e-09,,23248.056640625,21549.865234375,10043.4482421875,31343.283203125,12986.73828125,3.6842000561421173e-09,5.742299968858333e-09,5.602499797419114e-09,,44497.80859375,47288.671875,221.34500122070312,863.8519287109375,0.051351189613342285,145,1800316701,KiDSDR4 J002338.940-283853.98,1,-31269,2976,12006,-21012,-30571,8706,657,34,0.0010474099544808269,KIDS_5.6_-28.2,3.6439590454101562,0.016377950087189674,0.0014114510267972946,0.012002799659967422,0.008532585576176643,0.03643425926566124,0.004202578216791153,0.02498723939061165,0.002566705923527479,0.019786600023508072,0.00029095279751345515,0.039942000061273575,0.020178699865937233,0.10270900279283524,0.0167664997279644,0.01970669999718666,0.0111102145165205,0.042164143174886703,0.012712948024272919,,0.039942000061273575,0.020178699865937233,0.10270900279283524,0.0167664997279644,0.01970669999718666,0.0111102145165205,0.042164143174886703,0.012712948024272919,,0.039942000061273575,0.020178699865937233,0.10270900279283524,0.0167664997279644,0.01970669999718666,0.0111102145165205,0.042164143174886703,0.012712948024272919,,0.0002717036986723542,0.0002975777897518128,0.00578194297850132,21.664400100708008,16.581029891967773,20.897090911865234,20.09630012512207,19.20107078552246,23.66777992248535,18.55970001220703,22.797870635986328,17.671600341796875,22.16288948059082,12.61023998260498,19.083999633789062,19.166400909423828,19.99530029296875,18.759599685668945,19.71619987487793,21.012474060058594,20.670141220092773,20.679983139038086,,19.083999633789062,19.166400909423828,19.99530029296875,18.759599685668945,19.71619987487793,21.013296127319336,20.675228118896484,20.68263053894043,,19.077472686767578,19.156118392944336,19.990928649902344,18.743776321411133,19.697851181030273,20.96449851989746,20.645477294921875,20.646793365478516,,13.03915023803711,12.97311019897461,22.669769287109375,23.493467330932617,22.555583953857422,23.287841796875,24.06902313232422,25.98748016357422,24.197093963623047,25.508678436279297,24.940444946289062,14356,20.47719955444336,25.12795066833496,12.547,2.1574931144714355,8,0,1,822,1.0,4.800000190734863,5.912251,0,1.0,4359,60513621,0.4908931851387024,1.9642239809036255,4360,KIDS_5p6_m28p2,-85.21106719970703,-4.788931846618652,1.0,1.0,0.00014292749983724207,7492,5552,-8.852452083374374e-06,5.912251,6519.47998046875,3.800329068326391e-05,3196,2168,-28.648329,2823.85302734375,0.01,0.04,0.01,0.01 +0.042013488709926605,6.206854,3.289606,0.00019556870392989367,0.9900000095367432,0.9900000095367432,1.2200000286102295,511,0,0,2.669323,0.0001586083963047713,0.00567405391484499,0.8999999761581421,0.8999999761581421,1.149999976158142,1.1,0.013172520324587822,-0.266632080078125,0.405914306640625,0.09042930603027344,-0.15038299560546875,0.5065250396728516,0.16477203369140625,0.12359428405761719,0.813262939453125,0.027990849688649178,-0.010782940313220024,0.03541288897395134,-28.686387,-28.686387,0.07346581667661667,4.36771097156452e-06,0.05782262980937958,3.4355250591033837e-06,1.3084840247756802e-05,-5.543181032408029e-06,1.779488957254216e-05,65.17716979980469,24.822830200195312,1.7794890561084742e-11,2.771618004548948e-12,1.3084839635413292e-11,0.007971487008035183,0.012558851391077042,0.005339391995221376,0.01932709477841854,0.022410405799746513,0.05859743058681488,0.03012366034090519,0.04053743928670883,0.07520270347595215,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2625320851802826,2.757617950439453,0.36180469393730164,0.5104584097862244,0.7598472237586975,0.11131899803876877,1.010071039199829,0.16186439990997314,1.5659099817276,0.2128363996744156,0.9226744771003723,377.9237060546875,172.92108154296875,490.3476867675781,239.10488891601562,113.69266510009766,3.529999903495451e-11,1.4699999550948917e-10,5.740000141862822e-11,7.070000140885213e-11,449.18890380859375,202.87725830078125,569.6578979492188,271.0382385253906,127.95698547363281,4.009999970966405e-11,1.7100000582193076e-10,6.530000151716564e-11,7.999999968033578e-11,377.9237060546875,172.92108154296875,490.3476867675781,239.10488891601562,113.69266510009766,3.529999903495451e-11,1.4699999550948917e-10,5.740000141862822e-11,7.070000140885213e-11,0.34884360432624817,0.5749511122703552,9.5691499710083,60.65951919555664,13.21718978881836,16.888919830322266,21.595380783081055,2.4568400382995605,26.476560592651367,4.867195129394531,36.438621520996094,7.279531002044678,24.22311019897461,3070.866943359375,2104.077880859375,2408.064208984375,1923.9056396484375,2203.45068359375,9.594499639220544e-10,2.0010999524089357e-09,1.7414000241799954e-09,3.9258998829616587e-10,3382.674072265625,2345.5068359375,2576.024169921875,2025.1239013671875,2325.28173828125,1.0473999445537174e-09,2.1263999450127358e-09,1.92710003510399e-09,4.266300090982611e-10,3070.866943359375,2104.077880859375,2408.064208984375,1923.9056396484375,2203.45068359375,9.594499639220544e-10,2.0010999524089357e-09,1.7414000241799954e-09,3.9258998829616587e-10,13.420519828796387,17.619949340820312,6.339869022369385,10.838139533996582,0.00064426742028445,0,-1276785327,KiDSDR4 J002449.644-284110.99,0,136,128,112,89,63,38,20,8,4.805752951142495e-07,KIDS_5.6_-28.2,6.1619791984558105,0.029794689267873764,0.04937019944190979,0.029727939516305923,0.03282376006245613,0.04920646920800209,0.04143049940466881,0.036116231232881546,0.046669669449329376,0.0317520909011364,0.041366469115018845,0.13361899554729462,0.08922989666461945,0.22108599543571472,0.13493600487709045,0.056021299213171005,0.039946310222148895,0.07975773513317108,0.03578801825642586,0.19552600383758545,0.14417600631713867,0.09391199797391891,0.2400979995727539,0.14531299471855164,0.059746500104665756,0.04156770929694176,0.08731231093406677,0.03679029271006584,0.20359301567077637,0.13361899554729462,0.08922989666461945,0.22108599543571472,0.13493600487709045,0.056021299213171005,0.039946310222148895,0.07975773513317108,0.03578801825642586,0.19552600383758545,0.028228729963302612,0.035436928272247314,0.03821159154176712,22.207820892333984,20.202749252319336,21.857149124145508,21.590999603271484,21.324100494384766,23.684059143066406,21.10284996032715,22.94179916381836,20.756099700927734,22.50473976135254,21.199420928955078,21.28179931640625,21.69230079650879,21.545799255371094,21.789499282836914,21.642200469970703,22.473278045654297,21.81468391418457,21.948692321777344,23.303146362304688,21.176799774169922,21.574399948120117,21.47260093688965,21.73390007019043,21.583799362182617,22.378873825073242,21.753829956054688,21.841323852539062,23.219728469848633,21.273828506469727,21.67974281311035,21.54046058654785,21.770172119140625,21.619789123535156,22.41468048095703,21.784561157226562,21.90815544128418,23.227943420410156,21.840579986572266,21.54499053955078,23.556489944458008,24.405380249023438,23.273738861083984,24.05352783203125,24.860668182373047,26.058897018432617,24.64956283569336,25.653657913208008,25.164445877075195,0,22.76590919494629,25.12795066833496,21.001,0.2620980143547058,9,0,0,0,0.84319,-27.700000762939453,6.206854,0,1.0,4363,60513621,0.18855850398540497,1.2323750257492065,4364,KIDS_5p6_m28p2,62.26993942260742,27.730060577392578,5.455,5.455,3.541288862152214e-08,2182,2166,5.391522783781966e-09,6.206854,2172.93798828125,2.7990850526293798e-08,2175,2162,-28.686387,2168.39208984375,0.27,0.35,0.23,0.27 diff --git a/astroquery/eso/tests/data/query_list_catalogues.csv b/astroquery/eso/tests/data/query_list_catalogues.csv new file mode 100644 index 0000000000..369a806eba --- /dev/null +++ b/astroquery/eso/tests/data/query_list_catalogues.csv @@ -0,0 +1,129 @@ +'AMBRE_V1', + 'atlas_er3_ugriz_catMetaData_fits_V2', + 'ATLASGAL_V1', + 'COSMOS2015_Laigle_v1_1b_latestV7_fits_V1', + 'EREBOS_cat_fits_V1', + 'EREBOS_RV_cat_fits_V1', + 'GES_iDR4_PIII2016_Catalogue_v3_fits_V2', + 'GOODS_FORS2_V1', + 'GOODS_ISAAC_V1', + 'GOODS_VIMOS_SPEC_V1', + 'HUGS_GOODSS_K_V1', + 'HUGS_UDS_K_V1', + 'HUGS_UDS_Y_V1', + 'KiDS_DR3_0_ugri_src_fits_V2', + 'KiDS_DR3_1_ugri_shear_fits_V1', + 'legac_DR1_fits_V1', + 'legac_DR2_fits_V2', + 'PESSTO_TRAN_CAT_fits_V2', + 'PESSTO_MPHOT_fits_V2', + 'UltraVISTA_V3', + 'VANDELS_META_SPECTRO_fits_V1', + 'VHS_CAT_V2', + 'video_er3_zyjhks_CDFS_catMetaData_fits_V2', + 'video_er3_zyjhks_ES1_catMetaData_fits_V2', + 'video_er3_zyjhks_XMM_catMetaData_fits_V3', + 'viking_er4_zyjj_1j_2hks_catMetaData_fits_V3', + 'VIPERS_SPECTRO_PDR2_ESO_fits_V1', + 'vmc_er4_ksjy_catMetaData_fits_V3', + 'vmc_er4_j_mPhotMetaData_fits_V3', + 'vmc_er4_ks_mPhotMetaData_fits_V3', + 'vmc_er4_y_mPhotMetaData_fits_V3', + 'vmc_er4_yjks_cepheidCatMetaData_fits_V3', + 'vmc_er4_yjks_eclBinCatMetaData_fits_V2', + 'vmc_er4_yjks_psfCatMetaData_fits_V2', + 'vmc_er4_yjks_rrLyrCatMetaData_fits_V1', + 'vphas_er3_ugr_1r_2ihavphas_catMetaData_fits_V3', + 'VVV_CAT_V2', + 'VVV_MPHOT_Ks_V2', + 'VVV_VAR_V2', + 'XQ_100_summary_fits_V1', + 'ZCOSMOS_V2', + 'VANDELS_META_SPECTRO_fits_V2', + 'gcav_rxcj2129_YJKs_cat_fits_V1', + 'gcav_rxcj1515_YJKs_cat_fits_V1', + 'KiDS_DR4_0_ugriZYJHKs_cat_fits_V3', + 'UVISTA_5band_cat_dr4_rc_v2_fits_V3', + 'atlas_er4_ugriz_catMetaData_fits_V3', + 'VVV_VIRAC_PM_V1', + 'NGTS_SOURCE_CATALOGUE_fits_V1', + 'NGTS_LC_CATALOGUE_fits_V1', + 'MW_BULGE_PSFPHOT_V1', + 'VANDELS_spec_redshift_V3', + 'VEXAS_AllWISE_V1', + 'VEXAS_SMW_V1', + 'VEXAS_21_V1', + 'VEXAS_PS1W_V1', + 'VEXAS_XRAY_V1', + 'VEXAS_SPEC_V1', + 'VEXAS_DESW_V1', + 'viking_er5_zyjj_1j_2hks_catMetaData_fits_V4', + 'VHS_CAT_V3', + 'KiDS_DR4_1_ugriZYJHKs_cat_fits', + 'vmc_dr5_sourceCat_yjks_V4', + 'vmc_dr5_var_yjKs_V1', + 'vmc_dr5_mPhotY_V4', + 'vmc_dr5_mPhotJ_V4', + 'vmc_dr5_mPhotKs_V4', + 'vmc_dr5_psf_yjks_V3', + 'NGTS_SOURCE_CAT_V2', + 'NGTS_LC_V2', + 'VVV_bandMergedSourceCat_V3', + 'FDS_SourceCatalogue_V1', + 'VANDELS_SPECTRO_V4', + 'VEXAS_DESW_V2', + 'VEXAS_SMW_V2', + 'VEXAS_PSW_V2', + 'VEXAS_SPEC_GOOD_V2', + 'PESSTO_TRAN_CAT_V3', + 'GNS_catalogue_V1', + 'AMBRE_UVES_V1', + 'AMBRE_HARPS_V1', + 'PESSTO_MPHOT_V3', + 'legac_V3', + 'GES_2021_VRAD', + 'VIDEO_CAT_DR5', + 'GES_DR5', + 'COSMOS2020_CLASSIC_V2', + 'COSMOS2020_FARMER_V1', + 'vmc_dr6_yjks_varCat_V2', + 'vmc_dr6_yjks_psf_V4', + 'vmc_dr6_ksjy_V5', + 'vmc_dr6_mPhotJ_V5', + 'vmc_dr6_mPhotKs_V5', + 'vmc_dr6_mPhotY_V5', + 'COSMOS2020_FARMER_V2', + 'AMUSED_MAIN_SOURCE_CAT_V1', + 'UVISTA_5band_cat_dr5_rc_v1_fits_V4', + 'GES_DR5_1_V1', + 'HARPS_RVCAT_V1', + 'INSPIRE_V1', + 'UVISTA_5band_cat_dr6_rc_v1_fits_V5', + 'VVVX_VIRAC_V2_SOURCES', + 'VVVX_VIRAC_V2_REJECTED_SOURCES', + 'VVVX_VIRAC_V2_OBS', + 'VVVX_VIRAC_V2_LC', + 'VVVX_VIRAC_V2_LC', + 'VVVX_VIRAC_V2_REJECTED_LC', + 'VVVX_VIRAC_V2_REJECTED_LC', + 'KiDS_DR5_0_ugriZYJHKs_cat_fits', + 'PHANGS_DR1_NebCat', + 'atlas_er5_ugriz', + 'vmc_dr7_ksjy_V6', + 'vmc_dr7_mPhotJ_V6', + 'vmc_dr7_mPhotKs_V6', + 'vmc_dr7_mPhotY_V6', + 'vmc_dr7_yjks_rrLy_V2', + 'vmc_dr7_yjks_agbVar_V1', + 'vmc_dr7_yjks_lpvVar_V1', + 'vmc_dr7_yjks_eclBinVar_V3', + 'vmc_dr7_yjks_chephVar_V4', + 'vmc_dr7_yjks_ysoVar_V1', + 'vmc_dr7_yjks_qsos_V1', + 'vmc_dr7_yjks_extYKs_V1', + 'vmc_dr7_yjks_MlClass_V1', + 'vmc_dr7_yjks_extJKs_V1', + 'vmc_dr7_yjks_pm_V1', + 'vmc_dr7_yjks_psfSrc_V5', + 'vmc_dr7_yjks_back_V1', + 'vmc_dr7_yjks_varCat_V3' \ No newline at end of file diff --git a/astroquery/eso/tests/data/query_list_catalogues_all_versions.csv b/astroquery/eso/tests/data/query_list_catalogues_all_versions.csv new file mode 100644 index 0000000000..fb0c7f8fe0 --- /dev/null +++ b/astroquery/eso/tests/data/query_list_catalogues_all_versions.csv @@ -0,0 +1,130 @@ +,table_name +0,AMBRE_V1 +1,atlas_er3_ugriz_catMetaData_fits_V2 +2,ATLASGAL_V1 +3,COSMOS2015_Laigle_v1_1b_latestV7_fits_V1 +4,EREBOS_cat_fits_V1 +5,EREBOS_RV_cat_fits_V1 +6,GES_iDR4_PIII2016_Catalogue_v3_fits_V2 +7,GOODS_FORS2_V1 +8,GOODS_ISAAC_V1 +9,GOODS_VIMOS_SPEC_V1 +10,HUGS_GOODSS_K_V1 +11,HUGS_UDS_K_V1 +12,HUGS_UDS_Y_V1 +13,KiDS_DR3_0_ugri_src_fits_V2 +14,KiDS_DR3_1_ugri_shear_fits_V1 +15,legac_DR1_fits_V1 +16,legac_DR2_fits_V2 +17,PESSTO_TRAN_CAT_fits_V2 +18,PESSTO_MPHOT_fits_V2 +19,UltraVISTA_V3 +20,VANDELS_META_SPECTRO_fits_V1 +21,VHS_CAT_V2 +22,video_er3_zyjhks_CDFS_catMetaData_fits_V2 +23,video_er3_zyjhks_ES1_catMetaData_fits_V2 +24,video_er3_zyjhks_XMM_catMetaData_fits_V3 +25,viking_er4_zyjj_1j_2hks_catMetaData_fits_V3 +26,VIPERS_SPECTRO_PDR2_ESO_fits_V1 +27,vmc_er4_ksjy_catMetaData_fits_V3 +28,vmc_er4_j_mPhotMetaData_fits_V3 +29,vmc_er4_ks_mPhotMetaData_fits_V3 +30,vmc_er4_y_mPhotMetaData_fits_V3 +31,vmc_er4_yjks_cepheidCatMetaData_fits_V3 +32,vmc_er4_yjks_eclBinCatMetaData_fits_V2 +33,vmc_er4_yjks_psfCatMetaData_fits_V2 +34,vmc_er4_yjks_rrLyrCatMetaData_fits_V1 +35,vphas_er3_ugr_1r_2ihavphas_catMetaData_fits_V3 +36,VVV_CAT_V2 +37,VVV_MPHOT_Ks_V2 +38,VVV_VAR_V2 +39,XQ_100_summary_fits_V1 +40,ZCOSMOS_V2 +41,VANDELS_META_SPECTRO_fits_V2 +42,gcav_rxcj2129_YJKs_cat_fits_V1 +43,gcav_rxcj1515_YJKs_cat_fits_V1 +44,KiDS_DR4_0_ugriZYJHKs_cat_fits_V3 +45,UVISTA_5band_cat_dr4_rc_v2_fits_V3 +46,atlas_er4_ugriz_catMetaData_fits_V3 +47,VVV_VIRAC_PM_V1 +48,NGTS_SOURCE_CATALOGUE_fits_V1 +49,NGTS_LC_CATALOGUE_fits_V1 +50,MW_BULGE_PSFPHOT_V1 +51,VANDELS_spec_redshift_V3 +52,VEXAS_AllWISE_V1 +53,VEXAS_SMW_V1 +54,VEXAS_21_V1 +55,VEXAS_PS1W_V1 +56,VEXAS_XRAY_V1 +57,VEXAS_SPEC_V1 +58,VEXAS_DESW_V1 +59,viking_er5_zyjj_1j_2hks_catMetaData_fits_V4 +60,VHS_CAT_V3 +61,KiDS_DR4_1_ugriZYJHKs_cat_fits +62,vmc_dr5_sourceCat_yjks_V4 +63,vmc_dr5_var_yjKs_V1 +64,vmc_dr5_mPhotY_V4 +65,vmc_dr5_mPhotJ_V4 +66,vmc_dr5_mPhotKs_V4 +67,vmc_dr5_psf_yjks_V3 +68,NGTS_SOURCE_CAT_V2 +69,NGTS_LC_V2 +70,VVV_bandMergedSourceCat_V3 +71,FDS_SourceCatalogue_V1 +72,VANDELS_SPECTRO_V4 +73,VEXAS_DESW_V2 +74,VEXAS_SMW_V2 +75,VEXAS_PSW_V2 +76,VEXAS_SPEC_GOOD_V2 +77,PESSTO_TRAN_CAT_V3 +78,GNS_catalogue_V1 +79,AMBRE_UVES_V1 +80,AMBRE_HARPS_V1 +81,PESSTO_MPHOT_V3 +82,legac_V3 +83,GES_2021_VRAD +84,VIDEO_CAT_DR5 +85,GES_DR5 +86,COSMOS2020_CLASSIC_V2 +87,COSMOS2020_FARMER_V1 +88,vmc_dr6_yjks_varCat_V2 +89,vmc_dr6_yjks_psf_V4 +90,vmc_dr6_ksjy_V5 +91,vmc_dr6_mPhotJ_V5 +92,vmc_dr6_mPhotKs_V5 +93,vmc_dr6_mPhotY_V5 +94,COSMOS2020_FARMER_V2 +95,AMUSED_MAIN_SOURCE_CAT_V1 +96,UVISTA_5band_cat_dr5_rc_v1_fits_V4 +97,GES_DR5_1_V1 +98,HARPS_RVCAT_V1 +99,INSPIRE_V1 +100,UVISTA_5band_cat_dr6_rc_v1_fits_V5 +101,VVVX_VIRAC_V2_SOURCES +102,VVVX_VIRAC_V2_REJECTED_SOURCES +103,VVVX_VIRAC_V2_OBS +104,VVVX_VIRAC_V2_LC +105,VVVX_VIRAC_V2_LC +106,VVVX_VIRAC_V2_REJECTED_LC +107,VVVX_VIRAC_V2_REJECTED_LC +108,KiDS_DR5_0_ugriZYJHKs_cat_fits +109,PHANGS_DR1_NebCat +110,atlas_er5_ugriz +111,vmc_dr7_ksjy_V6 +112,vmc_dr7_mPhotJ_V6 +113,vmc_dr7_mPhotKs_V6 +114,vmc_dr7_mPhotY_V6 +115,vmc_dr7_yjks_rrLy_V2 +116,vmc_dr7_yjks_agbVar_V1 +117,vmc_dr7_yjks_lpvVar_V1 +118,vmc_dr7_yjks_eclBinVar_V3 +119,vmc_dr7_yjks_chephVar_V4 +120,vmc_dr7_yjks_ysoVar_V1 +121,vmc_dr7_yjks_qsos_V1 +122,vmc_dr7_yjks_extYKs_V1 +123,vmc_dr7_yjks_MlClass_V1 +124,vmc_dr7_yjks_extJKs_V1 +125,vmc_dr7_yjks_pm_V1 +126,vmc_dr7_yjks_psfSrc_V5 +127,vmc_dr7_yjks_back_V1 +128,vmc_dr7_yjks_varCat_V3 diff --git a/astroquery/eso/tests/data/query_list_catalogues_latest_versions.csv b/astroquery/eso/tests/data/query_list_catalogues_latest_versions.csv new file mode 100644 index 0000000000..a754df1b3e --- /dev/null +++ b/astroquery/eso/tests/data/query_list_catalogues_latest_versions.csv @@ -0,0 +1,87 @@ +,table_name +0,AMBRE_V1 +1,ATLASGAL_V1 +2,COSMOS2015_Laigle_v1_1b_latestV7_fits_V1 +3,EREBOS_cat_fits_V1 +4,EREBOS_RV_cat_fits_V1 +5,GOODS_FORS2_V1 +6,GOODS_ISAAC_V1 +7,GOODS_VIMOS_SPEC_V1 +8,HUGS_GOODSS_K_V1 +9,HUGS_UDS_K_V1 +10,HUGS_UDS_Y_V1 +11,KiDS_DR3_0_ugri_src_fits_V2 +12,KiDS_DR3_1_ugri_shear_fits_V1 +13,video_er3_zyjhks_CDFS_catMetaData_fits_V2 +14,video_er3_zyjhks_ES1_catMetaData_fits_V2 +15,video_er3_zyjhks_XMM_catMetaData_fits_V3 +16,VIPERS_SPECTRO_PDR2_ESO_fits_V1 +17,vphas_er3_ugr_1r_2ihavphas_catMetaData_fits_V3 +18,VVV_MPHOT_Ks_V2 +19,VVV_VAR_V2 +20,XQ_100_summary_fits_V1 +21,ZCOSMOS_V2 +22,gcav_rxcj2129_YJKs_cat_fits_V1 +23,gcav_rxcj1515_YJKs_cat_fits_V1 +24,VVV_VIRAC_PM_V1 +25,MW_BULGE_PSFPHOT_V1 +26,VANDELS_spec_redshift_V3 +27,VEXAS_AllWISE_V1 +28,VEXAS_21_V1 +29,VEXAS_XRAY_V1 +30,VEXAS_SPEC_V1 +31,viking_er5_zyjj_1j_2hks_catMetaData_fits_V4 +32,VHS_CAT_V3 +33,KiDS_DR4_1_ugriZYJHKs_cat_fits +34,NGTS_SOURCE_CAT_V2 +35,NGTS_LC_V2 +36,VVV_bandMergedSourceCat_V3 +37,FDS_SourceCatalogue_V1 +38,VANDELS_SPECTRO_V4 +39,VEXAS_DESW_V2 +40,VEXAS_SMW_V2 +41,VEXAS_PSW_V2 +42,VEXAS_SPEC_GOOD_V2 +43,PESSTO_TRAN_CAT_V3 +44,GNS_catalogue_V1 +45,AMBRE_UVES_V1 +46,AMBRE_HARPS_V1 +47,PESSTO_MPHOT_V3 +48,legac_V3 +49,GES_2021_VRAD +50,VIDEO_CAT_DR5 +51,COSMOS2020_CLASSIC_V2 +52,COSMOS2020_FARMER_V2 +53,AMUSED_MAIN_SOURCE_CAT_V1 +54,GES_DR5_1_V1 +55,HARPS_RVCAT_V1 +56,INSPIRE_V1 +57,UVISTA_5band_cat_dr6_rc_v1_fits_V5 +58,VVVX_VIRAC_V2_SOURCES +59,VVVX_VIRAC_V2_REJECTED_SOURCES +60,VVVX_VIRAC_V2_OBS +61,VVVX_VIRAC_V2_LC +62,VVVX_VIRAC_V2_LC +63,VVVX_VIRAC_V2_REJECTED_LC +64,VVVX_VIRAC_V2_REJECTED_LC +65,KiDS_DR5_0_ugriZYJHKs_cat_fits +66,PHANGS_DR1_NebCat +67,atlas_er5_ugriz +68,vmc_dr7_ksjy_V6 +69,vmc_dr7_mPhotJ_V6 +70,vmc_dr7_mPhotKs_V6 +71,vmc_dr7_mPhotY_V6 +72,vmc_dr7_yjks_rrLy_V2 +73,vmc_dr7_yjks_agbVar_V1 +74,vmc_dr7_yjks_lpvVar_V1 +75,vmc_dr7_yjks_eclBinVar_V3 +76,vmc_dr7_yjks_chephVar_V4 +77,vmc_dr7_yjks_ysoVar_V1 +78,vmc_dr7_yjks_qsos_V1 +79,vmc_dr7_yjks_extYKs_V1 +80,vmc_dr7_yjks_MlClass_V1 +81,vmc_dr7_yjks_extJKs_V1 +82,vmc_dr7_yjks_pm_V1 +83,vmc_dr7_yjks_psfSrc_V5 +84,vmc_dr7_yjks_back_V1 +85,vmc_dr7_yjks_varCat_V3 diff --git a/astroquery/eso/tests/test_eso.py b/astroquery/eso/tests/test_eso.py index 758623e7a6..a9b7bb5e9e 100644 --- a/astroquery/eso/tests/test_eso.py +++ b/astroquery/eso/tests/test_eso.py @@ -257,12 +257,29 @@ def test_calselector_multipart(monkeypatch, tmp_path): assert datasets[0] not in result and datasets[1] not in result -def test_tap_url(): +def test_tap_obs_url(): prod_url = "https://archive.eso.org/tap_obs" eso_instance = Eso() assert eso_instance._tap_url() == prod_url +@pytest.mark.parametrize("tap_url, expected", [ + ("https://archive.eso.org/tap_obs", "tap_obs"), + ("https://archive.eso.org/tap_obs/", "tap_obs"), + ("https://archive.eso.org/tap_cat", "tap_cat"), + ("https://archive.eso.org/tap_cat/", "tap_cat"), +]) +def test_which_tap(tap_url, expected): + eso_instance = Eso() + assert eso_instance._which_tap(tap_url) == expected + + +def test_which_tap_invalid_url(): + eso_instance = Eso() + with pytest.raises(ValueError, match="tap_url must be one of"): + eso_instance._which_tap("https://archive.eso.org/not-a-tap") + + @pytest.mark.parametrize("input_val, expected", [ # Numeric values (1, "= 1"), diff --git a/astroquery/eso/tests/test_eso_catalogues.py b/astroquery/eso/tests/test_eso_catalogues.py new file mode 100644 index 0000000000..4589d38a3a --- /dev/null +++ b/astroquery/eso/tests/test_eso_catalogues.py @@ -0,0 +1,298 @@ +# Licensed under a 3-clause BSD style license - see LICENSE.rst +""" +=========================== +ESO Astroquery Module tests +=========================== + +European Southern Observatory (ESO) + +""" + +import os + +import astropy.io.ascii +from astropy.table import Table + +from ...eso import Eso + +DATA_DIR = os.path.join(os.path.dirname(__file__), "data") +EXPECTED_MAXREC = 1000 +MONKEYPATCH_TABLE_LENGTH = 50 + + +def data_path(filename): + return os.path.join(DATA_DIR, filename) + + +DATA_FILES = { + "ADQL": { + "SELECT table_name FROM TAP_SCHEMA.tables as ref " + "LEFT OUTER JOIN TAP_SCHEMA.keys AS k ON ref.table_name = k.from_table " + "LEFT OUTER JOIN TAP_SCHEMA.key_columns AS kc ON k.key_id = kc.key_id " + "WHERE schema_name='safcat'" + "AND cat_id IN ( " + "SELECT t1.cat_id " + "FROM TAP_SCHEMA.tables t1 " + "LEFT JOIN TAP_SCHEMA.tables t2 ON (t1.title = t2.title AND t1.version < t2.version) " + "WHERE t2.title IS NULL)": "query_list_catalogues_latest_versions.csv", + "SELECT table_name FROM TAP_SCHEMA.tables as ref " + "LEFT OUTER JOIN TAP_SCHEMA.keys AS k ON ref.table_name = k.from_table " + "LEFT OUTER JOIN TAP_SCHEMA.key_columns AS kc ON k.key_id = kc.key_id " + "WHERE schema_name='safcat'": "query_list_catalogues_all_versions.csv", + "SELECT * FROM KiDS_DR4_1_ugriZYJHKs_cat_fits": "kids_dr4_sample.csv", + } +} + +catalogue_list = [ + "AMBRE_V1", + "ATLASGAL_V1", + "COSMOS2015_Laigle_v1_1b_latestV7_fits_V1", + "EREBOS_cat_fits_V1", + "EREBOS_RV_cat_fits_V1", + "GOODS_FORS2_V1", + "GOODS_ISAAC_V1", + "GOODS_VIMOS_SPEC_V1", + "HUGS_GOODSS_K_V1", + "HUGS_UDS_K_V1", + "HUGS_UDS_Y_V1", + "KiDS_DR3_0_ugri_src_fits_V2", + "KiDS_DR3_1_ugri_shear_fits_V1", + "video_er3_zyjhks_CDFS_catMetaData_fits_V2", + "video_er3_zyjhks_ES1_catMetaData_fits_V2", + "video_er3_zyjhks_XMM_catMetaData_fits_V3", + "VIPERS_SPECTRO_PDR2_ESO_fits_V1", + "vphas_er3_ugr_1r_2ihavphas_catMetaData_fits_V3", + "VVV_MPHOT_Ks_V2", + "VVV_VAR_V2", + "XQ_100_summary_fits_V1", + "ZCOSMOS_V2", + "gcav_rxcj2129_YJKs_cat_fits_V1", + "gcav_rxcj1515_YJKs_cat_fits_V1", + "VVV_VIRAC_PM_V1", + "MW_BULGE_PSFPHOT_V1", + "VANDELS_spec_redshift_V3", + "VEXAS_AllWISE_V1", + "VEXAS_21_V1", + "VEXAS_XRAY_V1", + "VEXAS_SPEC_V1", + "viking_er5_zyjj_1j_2hks_catMetaData_fits_V4", + "VHS_CAT_V3", + "KiDS_DR4_1_ugriZYJHKs_cat_fits", + "NGTS_SOURCE_CAT_V2", + "NGTS_LC_V2", + "VVV_bandMergedSourceCat_V3", + "FDS_SourceCatalogue_V1", + "VANDELS_SPECTRO_V4", + "VEXAS_DESW_V2", + "VEXAS_SMW_V2", + "VEXAS_PSW_V2", + "VEXAS_SPEC_GOOD_V2", + "PESSTO_TRAN_CAT_V3", + "GNS_catalogue_V1", + "AMBRE_UVES_V1", + "AMBRE_HARPS_V1", + "PESSTO_MPHOT_V3", + "legac_V3", + "GES_2021_VRAD", + "VIDEO_CAT_DR5", + "COSMOS2020_CLASSIC_V2", + "COSMOS2020_FARMER_V2", + "AMUSED_MAIN_SOURCE_CAT_V1", + "GES_DR5_1_V1", + "HARPS_RVCAT_V1", + "INSPIRE_V1", + "UVISTA_5band_cat_dr6_rc_v1_fits_V5", + "VVVX_VIRAC_V2_SOURCES", + "VVVX_VIRAC_V2_REJECTED_SOURCES", + "VVVX_VIRAC_V2_OBS", + "VVVX_VIRAC_V2_LC", + "VVVX_VIRAC_V2_LC", + "VVVX_VIRAC_V2_REJECTED_LC", + "VVVX_VIRAC_V2_REJECTED_LC", + "KiDS_DR5_0_ugriZYJHKs_cat_fits", + "PHANGS_DR1_NebCat", + "atlas_er5_ugriz", + "vmc_dr7_ksjy_V6", + "vmc_dr7_mPhotJ_V6", + "vmc_dr7_mPhotKs_V6", + "vmc_dr7_mPhotY_V6", + "vmc_dr7_yjks_rrLy_V2", + "vmc_dr7_yjks_agbVar_V1", + "vmc_dr7_yjks_lpvVar_V1", + "vmc_dr7_yjks_eclBinVar_V3", + "vmc_dr7_yjks_chephVar_V4", + "vmc_dr7_yjks_ysoVar_V1", + "vmc_dr7_yjks_qsos_V1", + "vmc_dr7_yjks_extYKs_V1", + "vmc_dr7_yjks_MlClass_V1", + "vmc_dr7_yjks_extJKs_V1", + "vmc_dr7_yjks_pm_V1", + "vmc_dr7_yjks_psfSrc_V5", + "vmc_dr7_yjks_back_V1", + "vmc_dr7_yjks_varCat_V3", +] + +catalogue_list_all = [ + "AMBRE_V1", + "atlas_er3_ugriz_catMetaData_fits_V2", + "ATLASGAL_V1", + "COSMOS2015_Laigle_v1_1b_latestV7_fits_V1", + "EREBOS_cat_fits_V1", + "EREBOS_RV_cat_fits_V1", + "GES_iDR4_PIII2016_Catalogue_v3_fits_V2", + "GOODS_FORS2_V1", + "GOODS_ISAAC_V1", + "GOODS_VIMOS_SPEC_V1", + "HUGS_GOODSS_K_V1", + "HUGS_UDS_K_V1", + "HUGS_UDS_Y_V1", + "KiDS_DR3_0_ugri_src_fits_V2", + "KiDS_DR3_1_ugri_shear_fits_V1", + "legac_DR1_fits_V1", + "legac_DR2_fits_V2", + "PESSTO_TRAN_CAT_fits_V2", + "PESSTO_MPHOT_fits_V2", + "UltraVISTA_V3", + "VANDELS_META_SPECTRO_fits_V1", + "VHS_CAT_V2", + "video_er3_zyjhks_CDFS_catMetaData_fits_V2", + "video_er3_zyjhks_ES1_catMetaData_fits_V2", + "video_er3_zyjhks_XMM_catMetaData_fits_V3", + "viking_er4_zyjj_1j_2hks_catMetaData_fits_V3", + "VIPERS_SPECTRO_PDR2_ESO_fits_V1", + "vmc_er4_ksjy_catMetaData_fits_V3", + "vmc_er4_j_mPhotMetaData_fits_V3", + "vmc_er4_ks_mPhotMetaData_fits_V3", + "vmc_er4_y_mPhotMetaData_fits_V3", + "vmc_er4_yjks_cepheidCatMetaData_fits_V3", + "vmc_er4_yjks_eclBinCatMetaData_fits_V2", + "vmc_er4_yjks_psfCatMetaData_fits_V2", + "vmc_er4_yjks_rrLyrCatMetaData_fits_V1", + "vphas_er3_ugr_1r_2ihavphas_catMetaData_fits_V3", + "VVV_CAT_V2", + "VVV_MPHOT_Ks_V2", + "VVV_VAR_V2", + "XQ_100_summary_fits_V1", + "ZCOSMOS_V2", + "VANDELS_META_SPECTRO_fits_V2", + "gcav_rxcj2129_YJKs_cat_fits_V1", + "gcav_rxcj1515_YJKs_cat_fits_V1", + "KiDS_DR4_0_ugriZYJHKs_cat_fits_V3", + "UVISTA_5band_cat_dr4_rc_v2_fits_V3", + "atlas_er4_ugriz_catMetaData_fits_V3", + "VVV_VIRAC_PM_V1", + "NGTS_SOURCE_CATALOGUE_fits_V1", + "NGTS_LC_CATALOGUE_fits_V1", + "MW_BULGE_PSFPHOT_V1", + "VANDELS_spec_redshift_V3", + "VEXAS_AllWISE_V1", + "VEXAS_SMW_V1", + "VEXAS_21_V1", + "VEXAS_PS1W_V1", + "VEXAS_XRAY_V1", + "VEXAS_SPEC_V1", + "VEXAS_DESW_V1", + "viking_er5_zyjj_1j_2hks_catMetaData_fits_V4", + "VHS_CAT_V3", + "KiDS_DR4_1_ugriZYJHKs_cat_fits", + "vmc_dr5_sourceCat_yjks_V4", + "vmc_dr5_var_yjKs_V1", + "vmc_dr5_mPhotY_V4", + "vmc_dr5_mPhotJ_V4", + "vmc_dr5_mPhotKs_V4", + "vmc_dr5_psf_yjks_V3", + "NGTS_SOURCE_CAT_V2", + "NGTS_LC_V2", + "VVV_bandMergedSourceCat_V3", + "FDS_SourceCatalogue_V1", + "VANDELS_SPECTRO_V4", + "VEXAS_DESW_V2", + "VEXAS_SMW_V2", + "VEXAS_PSW_V2", + "VEXAS_SPEC_GOOD_V2", + "PESSTO_TRAN_CAT_V3", + "GNS_catalogue_V1", + "AMBRE_UVES_V1", + "AMBRE_HARPS_V1", + "PESSTO_MPHOT_V3", + "legac_V3", + "GES_2021_VRAD", + "VIDEO_CAT_DR5", + "GES_DR5", + "COSMOS2020_CLASSIC_V2", + "COSMOS2020_FARMER_V1", + "vmc_dr6_yjks_varCat_V2", + "vmc_dr6_yjks_psf_V4", + "vmc_dr6_ksjy_V5", + "vmc_dr6_mPhotJ_V5", + "vmc_dr6_mPhotKs_V5", + "vmc_dr6_mPhotY_V5", + "COSMOS2020_FARMER_V2", + "AMUSED_MAIN_SOURCE_CAT_V1", + "UVISTA_5band_cat_dr5_rc_v1_fits_V4", + "GES_DR5_1_V1", + "HARPS_RVCAT_V1", + "INSPIRE_V1", + "UVISTA_5band_cat_dr6_rc_v1_fits_V5", + "VVVX_VIRAC_V2_SOURCES", + "VVVX_VIRAC_V2_REJECTED_SOURCES", + "VVVX_VIRAC_V2_OBS", + "VVVX_VIRAC_V2_LC", + "VVVX_VIRAC_V2_LC", + "VVVX_VIRAC_V2_REJECTED_LC", + "VVVX_VIRAC_V2_REJECTED_LC", + "KiDS_DR5_0_ugriZYJHKs_cat_fits", + "PHANGS_DR1_NebCat", + "atlas_er5_ugriz", + "vmc_dr7_ksjy_V6", + "vmc_dr7_mPhotJ_V6", + "vmc_dr7_mPhotKs_V6", + "vmc_dr7_mPhotY_V6", + "vmc_dr7_yjks_rrLy_V2", + "vmc_dr7_yjks_agbVar_V1", + "vmc_dr7_yjks_lpvVar_V1", + "vmc_dr7_yjks_eclBinVar_V3", + "vmc_dr7_yjks_chephVar_V4", + "vmc_dr7_yjks_ysoVar_V1", + "vmc_dr7_yjks_qsos_V1", + "vmc_dr7_yjks_extYKs_V1", + "vmc_dr7_yjks_MlClass_V1", + "vmc_dr7_yjks_extJKs_V1", + "vmc_dr7_yjks_pm_V1", + "vmc_dr7_yjks_psfSrc_V5", + "vmc_dr7_yjks_back_V1", + "vmc_dr7_yjks_varCat_V3", +] + + +def monkey_tap(query, **kwargs): + _ = kwargs + table_file = data_path(DATA_FILES["ADQL"][query]) + table = astropy.io.ascii.read( + table_file, format="csv", header_start=0, data_start=1 + ) + return table + + +def test_list_catalogues_latest_versions(monkeypatch): + eso = Eso() + monkeypatch.setattr(eso, "query_tap", monkey_tap) + saved_list = eso.list_catalogues(all_versions=False) + assert isinstance(saved_list, list) + assert set(catalogue_list) <= set(saved_list) + + +def test_list_catalogues_all_versions(monkeypatch): + eso = Eso() + monkeypatch.setattr(eso, "query_tap", monkey_tap) + saved_list = eso.list_catalogues(all_versions=True) + assert isinstance(saved_list, list) + assert len(saved_list) >= len(catalogue_list_all) + + +def test_query_catalogues(monkeypatch): + eso = Eso() + monkeypatch.setattr(eso, "query_tap", monkey_tap) + result = eso.query_catalogue("KiDS_DR4_1_ugriZYJHKs_cat_fits", ROW_LIMIT=5) + assert isinstance(result, Table) + assert len(result) <= 5 diff --git a/astroquery/eso/tests/test_eso_catalogues_remote.py b/astroquery/eso/tests/test_eso_catalogues_remote.py new file mode 100644 index 0000000000..619c14a0e1 --- /dev/null +++ b/astroquery/eso/tests/test_eso_catalogues_remote.py @@ -0,0 +1,50 @@ +# Licensed under a 3-clause BSD style license - see LICENSE.rst +""" +=========================== +ESO Astroquery Module tests +=========================== + +European Southern Observatory (ESO) + +""" + +import pytest + +from astropy.table import Table +from astroquery.eso import Eso + +from .test_eso_catalogues import catalogue_list, catalogue_list_all + + +@pytest.mark.remote_data +class TestEso: + @pytest.mark.filterwarnings("ignore::pyvo.dal.exceptions.DALOverflowWarning") + def test_list_catalogues(self): + eso = Eso() + t = eso.list_catalogues(all_versions=False) + t_all = eso.list_catalogues(all_versions=True) + lt = len(t) + lt_all = len(t_all) + + assert isinstance(t, list), f"Expected type {type(list)}; Obtained {type(t)}" + assert lt > 0, "Expected non-empty list of catalogues" + assert set(t) <= set(catalogue_list), "Expected different list of catalogues" + assert set(t_all) <= set(catalogue_list_all), "Expected different list of catalogues" + assert ( + lt_all >= lt + ), "Expected all_versions=True to return equal or more catalogues than all_versions=False" + + @pytest.mark.filterwarnings("ignore::pyvo.dal.exceptions.DALOverflowWarning") + @pytest.mark.parametrize("catalogue", catalogue_list) + def test_query_catalogue(self, catalogue): + eso = Eso() + t = eso.query_catalogue(catalogue, ROW_LIMIT=5) + + assert isinstance(t, Table), f"Expected type {type(Table)}; Obtained {type(t)}" + assert len(t) <= 5, f"Expected max 5 records; Obtained {len(t)}" + assert len(t) > 0, "Expected non-empty table" + + @pytest.mark.parametrize("catalogue", catalogue_list) + def test_query_catalogue_help(self, catalogue): + eso = Eso() + eso.query_catalogue(catalogue, help=True) diff --git a/astroquery/eso/tests/test_eso_remote.py b/astroquery/eso/tests/test_eso_remote.py index 532229fa29..10455bed78 100644 --- a/astroquery/eso/tests/test_eso_remote.py +++ b/astroquery/eso/tests/test_eso_remote.py @@ -15,41 +15,67 @@ from astroquery.exceptions import NoResultsWarning, MaxResultsWarning from astroquery.eso import Eso -instrument_list = ['alpaca', 'fors1', 'fors2', 'sphere', 'vimos', 'omegacam', - 'hawki', 'isaac', 'naco', 'visir', 'vircam', - 'apex', - 'giraffe', 'uves', 'xshooter', 'muse', 'crires', - 'kmos', 'sinfoni', 'amber', 'midi', 'pionier', - 'gravity', 'espresso', 'wlgsu', 'matisse', 'eris', - 'fiat', - 'efosc', 'harps', 'nirps', 'sofi' - ] - -SGRA_SURVEYS = ['195.B-0283', - 'ALMA', - 'ATLASGAL', - 'CRIRESplus', - 'ERIS-SPIFFIER', - 'GIRAFFE', - 'HARPS', - 'HAWKI', - 'KMOS', - 'MW-BULGE-PSFPHOT', - 'SEDIGISM', - 'VPHASplus', - 'VVV', - 'VVVX', - 'XSHOOTER' - ] +instrument_list = [ + "alpaca", + "fors1", + "fors2", + "sphere", + "vimos", + "omegacam", + "hawki", + "isaac", + "naco", + "visir", + "vircam", + "apex", + "giraffe", + "uves", + "xshooter", + "muse", + "crires", + "kmos", + "sinfoni", + "amber", + "midi", + "pionier", + "gravity", + "espresso", + "wlgsu", + "matisse", + "eris", + "fiat", + "efosc", + "harps", + "nirps", + "sofi", +] + +SGRA_SURVEYS = [ + "195.B-0283", + "ALMA", + "ATLASGAL", + "CRIRESplus", + "ERIS-SPIFFIER", + "GIRAFFE", + "HARPS", + "HAWKI", + "KMOS", + "MW-BULGE-PSFPHOT", + "SEDIGISM", + "VPHASplus", + "VVV", + "VVVX", + "XSHOOTER", +] ONE_RECORD_SURVEYS = [ - '081.C-0827', - '108.2289', - '1100.A-0528', - '60.A-9493', - 'APEX-SciOps', - 'HARPS', - 'LESS', + "081.C-0827", + "108.2289", + "1100.A-0528", + "60.A-9493", + "APEX-SciOps", + "HARPS", + "LESS", ] @@ -64,7 +90,9 @@ def test_query_tap_service(self): lt = len(t) assert isinstance(t, Table), f"Expected type {type(Table)}; Obtained {type(t)}" assert len(t) > 0, "Table length is zero" - assert len(t) == eso.ROW_LIMIT, f"Table length is {lt}, expected {eso.ROW_LIMIT}" + assert len(t) == eso.ROW_LIMIT, ( + f"Table length is {lt}, expected {eso.ROW_LIMIT}" + ) @pytest.mark.filterwarnings("ignore::pyvo.dal.exceptions.DALOverflowWarning") def test_row_limit(self): @@ -73,12 +101,12 @@ def test_row_limit(self): # since in this case the results are truncated, a warning is issued with pytest.warns(MaxResultsWarning): - table = eso.query_instrument('UVES') + table = eso.query_instrument("UVES") n = len(table) assert n == eso.ROW_LIMIT, f"Expected {eso.ROW_LIMIT}; Obtained {n}" with pytest.warns(MaxResultsWarning): - table = eso.query_surveys('VVV') + table = eso.query_surveys("VVV") n = len(table) assert n == eso.ROW_LIMIT, f"Expected {eso.ROW_LIMIT}; Obtained {n}" @@ -94,11 +122,11 @@ def test_top(self): eso.ROW_LIMIT = None # in this case the results are NOT truncated, no warnings should be issued - table = eso.query_instrument('UVES', top=top) + table = eso.query_instrument("UVES", top=top) n = len(table) assert n == top, f"Expected {top}; Obtained {n}" - table = eso.query_surveys('VVV', top=top) + table = eso.query_surveys("VVV", top=top) n = len(table) assert n == top, f"Expected {top}; Obtained {n}" @@ -110,23 +138,17 @@ def test_apex_retrieval(self): eso = Eso() tblb = eso.query_apex_quicklooks( - column_filters={ - "project_id": 'E-095.F-9802A-2015' - } - ) - tbla = eso.query_apex_quicklooks( - column_filters={ - "prog_id": '095.F-9802(A)' - } + column_filters={"project_id": "E-095.F-9802A-2015"} ) + tbla = eso.query_apex_quicklooks(column_filters={"prog_id": "095.F-9802(A)"}) assert len(tbla) == 5 - assert set(tbla['release_date']) == { - '2015-07-17T03:06:23.280Z', - '2015-07-18T12:07:32.713Z', - '2015-09-18T11:31:15.867Z', - '2015-09-15T11:06:55.663Z', - '2015-09-18T11:46:19.970Z' + assert set(tbla["release_date"]) == { + "2015-07-17T03:06:23.280Z", + "2015-07-18T12:07:32.713Z", + "2015-09-18T11:31:15.867Z", + "2015-09-15T11:06:55.663Z", + "2015-09-18T11:46:19.970Z", } assert all(tbla.values_equal(tblb)) @@ -141,20 +163,24 @@ def test_sgrastar(self): # result_i = eso.query_instrument('midi', target='Sgr A*') # Equivalent, does not depend on SESAME: with pytest.warns(MaxResultsWarning): - result_i = eso.query_instrument('midi', cone_ra=266.41681662, - cone_dec=-29.00782497, cone_radius=1.0) + result_i = eso.query_instrument( + "midi", cone_ra=266.41681662, cone_dec=-29.00782497, cone_radius=1.0 + ) surveys = eso.list_surveys() assert len(surveys) > 0 with pytest.warns(MaxResultsWarning): - result_s = eso.query_surveys(surveys='VVV', cone_ra=266.41681662, - cone_dec=-29.00782497, - cone_radius=1.0) + result_s = eso.query_surveys( + surveys="VVV", + cone_ra=266.41681662, + cone_dec=-29.00782497, + cone_radius=1.0, + ) - assert 'midi' in instruments + assert "midi" in instruments assert result_i is not None - assert 'VVV' in surveys + assert "VVV" in surveys assert result_s is not None # From obs.raw, we have "object" (when query_instruments) @@ -166,8 +192,8 @@ def test_sgrastar(self): # target_name: The target name as assigned by the Principal Investigator; # ref. Ref. OBJECT keyword in ESO SDP standard. # For spectroscopic public surveys, the value shall be set to the survey source identifier. - assert 'target_name' in result_s.colnames - assert 'b319' in result_s['target_name'] + assert "target_name" in result_s.colnames + assert "b319" in result_s["target_name"] @pytest.mark.filterwarnings("ignore::pyvo.dal.exceptions.DALOverflowWarning") def test_multisurvey(self, tmp_path): @@ -176,15 +202,17 @@ def test_multisurvey(self, tmp_path): eso.cache_location = tmp_path eso.ROW_LIMIT = 1000 - test_surveys = ['VVV', 'XSHOOTER'] + test_surveys = ["VVV", "XSHOOTER"] with pytest.warns(MaxResultsWarning): - result_s = eso.query_surveys(surveys=test_surveys, - cone_ra=266.41681662, - cone_dec=-29.00782497, - cone_radius=1.0) + result_s = eso.query_surveys( + surveys=test_surveys, + cone_ra=266.41681662, + cone_dec=-29.00782497, + cone_radius=1.0, + ) assert result_s is not None - assert 'target_name' in result_s.colnames + assert "target_name" in result_s.colnames counts = Counter(result_s["obs_collection"].data) for tc in test_surveys: @@ -199,8 +227,12 @@ def test_empty_return(self): # Avoid SESAME with pytest.warns(NoResultsWarning): - result_s = eso.query_surveys(surveys=surveys[0], cone_ra=202.469575, - cone_dec=47.195258, cone_radius=1.0) + result_s = eso.query_surveys( + surveys=surveys[0], + cone_ra=202.469575, + cone_dec=47.195258, + cone_radius=1.0, + ) assert len(result_s) == 0 @@ -208,75 +240,81 @@ def test_empty_return(self): def test_sgrastar_column_filters(self): eso = Eso() - result1 = eso.query_surveys("sphere, vegas", - columns=("obs_collection, calib_level, " - "multi_ob, filter, s_pixel_scale, instrument_name"), - column_filters={ - 'calib_level': "= 3", - 'multi_ob': "like '%M%'"} - ) - - result2 = eso.query_surveys("sphere, vegas", - columns=("obs_collection, calib_level, " - "multi_ob, filter, s_pixel_scale, instrument_name"), - column_filters={ - 'calib_level': 3, - 'multi_ob': 'M' - } - ) + result1 = eso.query_surveys( + "sphere, vegas", + columns=( + "obs_collection, calib_level, " + "multi_ob, filter, s_pixel_scale, instrument_name" + ), + column_filters={"calib_level": "= 3", "multi_ob": "like '%M%'"}, + ) + + result2 = eso.query_surveys( + "sphere, vegas", + columns=( + "obs_collection, calib_level, " + "multi_ob, filter, s_pixel_scale, instrument_name" + ), + column_filters={"calib_level": 3, "multi_ob": "M"}, + ) assert all(result1.values_equal(result2)) def test_list_instruments(self): # If this test fails, we may simply need to update it inst = set(Eso.list_instruments()) - assert set(inst) == set(instrument_list), \ + assert set(inst) == set(instrument_list), ( f"Expected result {instrument_list}; Obtained: {inst}" + ) def test_retrieve_data(self): eso = Eso() - file_id = 'AMBER.2006-03-14T07:40:19.830' + file_id = "AMBER.2006-03-14T07:40:19.830" result = eso.retrieve_data(file_id) assert isinstance(result, str) assert file_id in result - @pytest.mark.skipif('not Eso.USERNAME') + @pytest.mark.skipif("not Eso.USERNAME") def test_retrieve_data_authenticated(self): eso = Eso() eso.login() - file_id = 'AMBER.2006-03-14T07:40:19.830' + file_id = "AMBER.2006-03-14T07:40:19.830" result = eso.retrieve_data(file_id) assert isinstance(result, str) assert file_id in result def test_retrieve_data_list(self): eso = Eso() - datasets = ['MIDI.2014-07-25T02:03:11.561', 'AMBER.2006-03-14T07:40:19.830'] + datasets = ["MIDI.2014-07-25T02:03:11.561", "AMBER.2006-03-14T07:40:19.830"] result = eso.retrieve_data(datasets) assert isinstance(result, list) assert len(result) == 2 - @pytest.mark.parametrize('instrument', instrument_list) + @pytest.mark.parametrize("instrument", instrument_list) def test_help(self, instrument): eso = Eso() eso.query_instrument(instrument, help=True) @pytest.mark.filterwarnings("ignore::pyvo.dal.exceptions.DALOverflowWarning") - @pytest.mark.parametrize('instrument', instrument_list) + @pytest.mark.parametrize("instrument", instrument_list) def test_each_instrument_sgrastar(self, instrument): eso = Eso() eso.ROW_LIMIT = 1 # Either we have maxrec results or none at all try: with pytest.warns(MaxResultsWarning): - result = eso.query_instrument(instrument, - cone_ra=266.41681662, - cone_dec=-29.00782497, - cone_radius=1.0) + result = eso.query_instrument( + instrument, + cone_ra=266.41681662, + cone_dec=-29.00782497, + cone_radius=1.0, + ) except NoResultsWarning: # we don't care if there are no results pass else: assert isinstance(result, Table) - assert len(result) > 0, f"query_instrument({instrument}) returned no records" + assert len(result) > 0, ( + f"query_instrument({instrument}) returned no records" + ) @pytest.mark.filterwarnings("ignore::pyvo.dal.exceptions.DALOverflowWarning") def test_each_survey_sgrastar(self, tmp_path): @@ -291,19 +329,28 @@ def test_each_survey_sgrastar(self, tmp_path): with pytest.warns(MaxResultsWarning): result_s = eso.query_surveys( surveys=survey, - cone_ra=266.41681662, cone_dec=-29.00782497, cone_radius=0.1775) + cone_ra=266.41681662, + cone_dec=-29.00782497, + cone_radius=0.1775, + ) else: # No warnings expected result_s = eso.query_surveys( surveys=survey, - cone_ra=266.41681662, cone_dec=-29.00782497, cone_radius=0.1775) + cone_ra=266.41681662, + cone_dec=-29.00782497, + cone_radius=0.1775, + ) assert isinstance(result_s, Table) assert len(result_s) > 0 else: # survey does not contain SGRA with pytest.warns(NoResultsWarning): - result_s = eso.query_surveys(surveys=survey, cone_ra=266.41681662, - cone_dec=-29.00782497, - cone_radius=0.1775) + result_s = eso.query_surveys( + surveys=survey, + cone_ra=266.41681662, + cone_dec=-29.00782497, + cone_radius=0.1775, + ) assert isinstance(result_s, Table) assert isinstance(result_s, Table) assert len(result_s) == 0, f"Failed for survey {survey}" @@ -315,8 +362,9 @@ def test_each_survey_sgrastar(self, tmp_path): else: # Do not expect warnings generic_result = eso.query_surveys(surveys=survey) assert isinstance(generic_result, Table) - assert len(generic_result) > 0, \ + assert len(generic_result) > 0, ( f"query_surveys({survey}) returned no records" + ) @pytest.mark.filterwarnings("ignore::pyvo.dal.exceptions.DALOverflowWarning") def test_mixed_case_instrument(self, tmp_path): @@ -325,10 +373,12 @@ def test_mixed_case_instrument(self, tmp_path): eso.ROW_LIMIT = 5 with pytest.warns(MaxResultsWarning): - result1 = eso.query_instrument('midi', cone_ra=266.41681662, - cone_dec=-29.00782497, cone_radius=1.0) - result2 = eso.query_instrument('MiDi', cone_ra=266.41681662, - cone_dec=-29.00782497, cone_radius=1.0) + result1 = eso.query_instrument( + "midi", cone_ra=266.41681662, cone_dec=-29.00782497, cone_radius=1.0 + ) + result2 = eso.query_instrument( + "MiDi", cone_ra=266.41681662, cone_dec=-29.00782497, cone_radius=1.0 + ) assert all(result1.values_equal(result2)) @pytest.mark.filterwarnings("ignore::pyvo.dal.exceptions.DALOverflowWarning") @@ -338,11 +388,9 @@ def test_main_sgrastar(self): with pytest.warns(MaxResultsWarning): result = eso.query_main( - column_filters={ - 'target': "SGR A", - 'object': "SGR A"} + column_filters={"target": "SGR A", "object": "SGR A"} ) assert len(result) == 5 - assert 'SGR A' in result['object'] - assert 'SGR A' in result['target'] + assert "SGR A" in result["object"] + assert "SGR A" in result["target"] diff --git a/astroquery/eso/utils.py b/astroquery/eso/utils.py index e4f910e279..a445377615 100644 --- a/astroquery/eso/utils.py +++ b/astroquery/eso/utils.py @@ -29,6 +29,7 @@ class _UserParams: get_query_payload: bool = False print_help: bool = False authenticated: bool = False + which_tap: str = "tap_obs" def _split_str_as_list_of_str(column_str: str): diff --git a/setup.cfg b/setup.cfg index d51f8c8b1a..351e654fbf 100644 --- a/setup.cfg +++ b/setup.cfg @@ -37,7 +37,9 @@ show-response = 1 [tool:pytest] minversion = 7.4 norecursedirs = build docs/_build astroquery/irsa astroquery/nasa_exoplanet_archive astroquery/ned astroquery/ibe astroquery/irsa_dust astroquery/cds astroquery/sha astroquery/dace -testpaths = astroquery docs +testpaths = + docs/eso + astroquery/eso doctest_plus = enabled astropy_header = true text_file_format = rst diff --git a/tox.ini b/tox.ini index 53a67b9341..1f7fcceef4 100644 --- a/tox.ini +++ b/tox.ini @@ -66,12 +66,12 @@ commands = devdeps: pip install -U --pre --no-deps --extra-index-url https://pypi.anaconda.org/scientific-python-nightly-wheels/simple numpy python -m pip freeze - !cov: pytest --pyargs astroquery {toxinidir}/docs {env:PYTEST_ARGS} {posargs} - cov: pytest --pyargs astroquery {toxinidir}/docs --cov astroquery --cov-config={toxinidir}/setup.cfg {env:PYTEST_ARGS} {posargs} + !cov: pytest --pyargs astroquery.eso {toxinidir}/docs/eso {env:PYTEST_ARGS} {posargs} + cov: pytest --pyargs astroquery.eso {toxinidir}/docs/eso --cov astroquery.eso --cov-config={toxinidir}/setup.cfg {env:PYTEST_ARGS} {posargs} # For remote tests, we re-run the failures to filter out at least some of the flaky ones. # We use a second pytest run with --last-failed as opposed to --rerun in order to rerun the # failed ones at the end rather than right away. - online: pytest --pyargs astroquery {toxinidir}/docs {env:PYTEST_ARGS_2} {posargs} + online: pytest --pyargs astroquery.eso {toxinidir}/docs/eso {env:PYTEST_ARGS_2} {posargs} cov: coverage xml -o {toxinidir}/coverage.xml pip_pre =