Skip to content

Commit 6849dd9

Browse files
committed
Rewrite query functions; query the ISts
1 parent e8adc4a commit 6849dd9

File tree

3 files changed

+103
-163
lines changed

3 files changed

+103
-163
lines changed

astroquery/eso/core.py

Lines changed: 71 additions & 158 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import warnings
2121
import xml.etree.ElementTree as ET
2222
from typing import List, Optional, Tuple, Dict, Set, Union
23-
from dataclasses import dataclass
2423
from datetime import datetime, timezone, timedelta
2524

2625
import astropy.table
@@ -29,7 +28,7 @@
2928
import keyring
3029
import requests.exceptions
3130
from astropy.table import Table, Column
32-
from astropy.utils.decorators import deprecated, deprecated_renamed_argument
31+
from astropy.utils.decorators import deprecated_renamed_argument
3332
from bs4 import BeautifulSoup
3433
import pyvo
3534

@@ -67,20 +66,15 @@ def expired(self) -> bool:
6766
return time.time() > self.expiration_time - 600
6867

6968

70-
@dataclass
71-
class QueryOnField:
72-
table_name: str
73-
column_name: str
69+
class EsoNames:
70+
raw_table = "dbo.raw"
71+
phase3_table = "ivoa.ObsCore"
72+
raw_instruments_column = "instrument"
73+
phase3_collections_column = "obs_collection"
7474

75-
76-
QueryOnInstrument = QueryOnField(
77-
table_name="dbo.raw", # This should be ist.<instrument_name>
78-
column_name="instrument")
79-
80-
81-
QueryOnCollection = QueryOnField(
82-
table_name="ivoa.ObsCore",
83-
column_name="obs_collection")
75+
@staticmethod
76+
def ist_table(instrument_name):
77+
return f"ist.{instrument_name}"
8478

8579

8680
class EsoClass(QueryWithLogin):
@@ -104,10 +98,6 @@ def __init__(self, timeout=None):
10498
def timeout(self):
10599
return self._timeout
106100

107-
# The logging module needs strings
108-
# written in %s style. This wrappers
109-
# are used for that purpose.
110-
# [W1203 - logging-fstring-interpolation]
111101
@staticmethod
112102
def log_info(message):
113103
"Wrapper for logging function"
@@ -321,8 +311,8 @@ def list_collections(self, *, cache=True) -> List[str]:
321311
"""
322312
if self._collections is None:
323313
self._collections = []
324-
c = QueryOnCollection.column_name
325-
t = QueryOnCollection.table_name
314+
t = EsoNames.phase3_table
315+
c = EsoNames.phase3_collections_column
326316
query_str = f"select distinct {c} from {t}"
327317
res = self.query_tap_service(query_str, cache=cache)[c].data
328318

@@ -343,30 +333,29 @@ def print_table_help(self, table_name: str) -> None:
343333
self.log_info(f"\nColumns present in the table {table_name}:\n{available_cols}\n")
344334
astropy.conf.max_lines = n_
345335

346-
def _query_instrument_or_collection(self,
347-
query_on: QueryOnField,
348-
collections: Union[List[str], str], *,
349-
ra: float = None, dec: float = None, radius: float = None,
350-
column_filters: Dict = None,
351-
columns: Union[List, str] = None,
352-
print_help=False, cache=True,
353-
**kwargs) -> astropy.table.Table:
336+
def _query_on_allowed_values(self,
337+
table_name: str,
338+
column_name: str,
339+
allowed_values: Union[List[str], str] = None, *,
340+
ra: float = None, dec: float = None, radius: float = None,
341+
columns: Union[List, str] = None,
342+
print_help=False, cache=True,
343+
**kwargs) -> astropy.table.Table:
354344
"""
355345
Query instrument- or collection-specific data contained in the ESO archive.
356346
- instrument-specific data is raw
357347
- collection-specific data is processed
358348
"""
359-
column_filters = column_filters or {}
360349
columns = columns or []
361-
filters = {**dict(kwargs), **column_filters}
350+
filters = {**dict(kwargs)}
362351

363352
if print_help:
364-
self.print_table_help(query_on.table_name)
353+
self.print_table_help(table_name)
365354
return
366355

367-
if (('box' in filters.keys())
368-
or ('coord1' in filters.keys())
369-
or ('coord2' in filters.keys())):
356+
if (('box' in filters)
357+
or ('coord1' in filters)
358+
or ('coord2' in filters)):
370359
message = 'box, coord1 and coord2 are deprecated; use ra, dec and radius instead'
371360
raise ValueError(message)
372361

@@ -375,125 +364,65 @@ def _query_instrument_or_collection(self,
375364
message += f"Values provided: ra = {ra}, dec = {dec}, radius = {radius}"
376365
raise ValueError(message)
377366

378-
if isinstance(collections, str):
379-
collections = _split_str_as_list_of_str(collections)
367+
where_collections_strlist = []
368+
if allowed_values:
369+
if isinstance(allowed_values, str):
370+
allowed_values = _split_str_as_list_of_str(allowed_values)
380371

381-
collections = list(map(lambda x: f"'{x.strip()}'", collections))
382-
where_collections_str = f"{query_on.column_name} in (" + ", ".join(collections) + ")"
372+
allowed_values = list(map(lambda x: f"'{x.strip()}'", allowed_values))
373+
where_collections_strlist = [f"{column_name} in (" + ", ".join(allowed_values) + ")"]
383374

384375
where_constraints_strlist = [f"{k} = {adql_sanitize_val(v)}" for k, v in filters.items()]
385-
where_constraints = [where_collections_str] + where_constraints_strlist
386-
query = py2adql(table=query_on.table_name, columns=columns,
376+
where_constraints = where_collections_strlist + where_constraints_strlist
377+
query = py2adql(table=table_name, columns=columns,
387378
ra=ra, dec=dec, radius=radius,
388379
where_constraints=where_constraints,
389380
top=self.ROW_LIMIT)
390381

391382
return self.query_tap_service(query_str=query, cache=cache)
392383

393-
@deprecated_renamed_argument(('open_form', 'help'), (None, 'print_help'),
394-
since=['0.4.8', '0.4.8'])
395-
def query_instrument(self, instrument: Union[List, str] = None, *,
396-
ra: float = None, dec: float = None, radius: float = None,
397-
column_filters: Dict = None, columns: Union[List, str] = None,
398-
open_form=False, print_help=False, cache=True,
399-
**kwargs) -> astropy.table.Table:
400-
_ = open_form
401-
return self._query_instrument_or_collection(query_on=QueryOnInstrument,
402-
collections=instrument,
403-
ra=ra, dec=dec, radius=radius,
404-
column_filters=column_filters,
405-
columns=columns,
406-
print_help=print_help,
407-
cache=cache,
408-
**kwargs)
409-
410-
@deprecated_renamed_argument(('open_form', 'help'), (None, 'print_help'),
411-
since=['0.4.8', '0.4.8'])
412-
def query_collections(self, collections: Union[List, str] = None, *,
384+
def query_collections(self,
385+
collections: Union[List[str], str], *,
413386
ra: float = None, dec: float = None, radius: float = None,
414-
column_filters: Dict = None, columns: Union[List, str] = None,
415-
open_form=False, print_help=False, cache=True,
387+
columns: Union[List, str] = None,
388+
print_help=False, cache=True,
416389
**kwargs) -> astropy.table.Table:
417-
column_filters = column_filters or {}
418-
columns = columns or []
419-
_ = open_form
420-
return self._query_instrument_or_collection(query_on=QueryOnCollection,
421-
collections=collections,
422-
ra=ra, dec=dec, radius=radius,
423-
column_filters=column_filters,
424-
columns=columns,
425-
print_help=print_help,
426-
cache=cache,
427-
**kwargs)
428-
429-
@deprecated_renamed_argument(old_name='help', new_name='print_help', since='0.4.8')
430-
def query_raw(self, *,
431-
ra: float = None, dec: float = None, radius: float = None,
432-
column_filters=None, columns=None,
433-
print_help=False, cache=True, **kwargs):
434-
"""
435-
Query raw data contained in the ESO archive.
436-
437-
Returns
438-
-------
439-
table : `~astropy.table.Table`, the number of rows
440-
capped by the ROW_LIMIT configuration item.
441-
"""
442-
column_filters = column_filters or {}
443-
columns = columns or []
444-
filters = {**dict(kwargs), **column_filters}
445-
table_name = "dbo.raw"
446-
447-
if print_help:
448-
self.print_table_help(table_name=table_name)
449-
return
450-
451-
where_constraints_strlist = [f"{k} = {adql_sanitize_val(v)}" for k, v in filters.items()]
452-
where_constraints = where_constraints_strlist
453-
454-
455-
query = py2adql(table=table_name,
456-
columns=columns,
457-
ra=ra, dec=dec, radius=radius,
458-
where_constraints=where_constraints,
459-
top=self.ROW_LIMIT)
460-
461-
return self.query_tap_service(query_str=query, cache=cache)
462-
463-
@deprecated_renamed_argument(old_name='help', new_name='print_help', since='0.4.8')
464-
def query_prods(self, *,
390+
return self._query_on_allowed_values(table_name=EsoNames.phase3_table,
391+
column_name=EsoNames.phase3_collections_column,
392+
allowed_values=collections,
393+
ra=ra, dec=dec, radius=radius,
394+
columns=columns,
395+
print_help=print_help, cache=cache,
396+
**kwargs)
397+
398+
def query_main(self,
399+
instruments: Union[List[str], str] = None, *,
465400
ra: float = None, dec: float = None, radius: float = None,
466-
column_filters=None, columns=None,
467-
print_help=False, cache=True, **kwargs):
468-
"""
469-
Query processed data contained in the ESO archive.
470-
471-
Returns
472-
-------
473-
table : `~astropy.table.Table`, the number of rows
474-
capped by the ROW_LIMIT configuration item.
475-
"""
476-
column_filters = column_filters or {}
477-
columns = columns or []
478-
filters = {**dict(kwargs), **column_filters}
479-
480-
where_constraints_strlist = [f"{k} = {adql_sanitize_val(v)}" for k, v in filters.items()]
481-
where_constraints = where_constraints_strlist
482-
483-
if print_help:
484-
help_query = \
485-
"select column_name, datatype from TAP_SCHEMA.columns where table_name = 'ivoa.ObsCore'"
486-
h = self.query_tap_service(help_query, cache=cache)
487-
self.log_info(f"Columns present in the table: {h}")
488-
return
489-
490-
query = py2adql(table="ivoa.ObsCore",
491-
columns=columns,
492-
ra=ra, dec=dec, radius=radius,
493-
where_constraints=where_constraints,
494-
top=self.ROW_LIMIT)
495-
496-
return self.query_tap_service(query_str=query, cache=cache)
401+
columns: Union[List, str] = None,
402+
print_help=False, cache=True,
403+
**kwargs) -> astropy.table.Table:
404+
return self._query_on_allowed_values(table_name=EsoNames.raw_table,
405+
column_name=EsoNames.raw_instruments_column,
406+
allowed_values=instruments,
407+
ra=ra, dec=dec, radius=radius,
408+
columns=columns,
409+
print_help=print_help, cache=cache,
410+
**kwargs)
411+
412+
# ex query_instrument
413+
def query_instrument(self,
414+
instrument: str, *,
415+
ra: float = None, dec: float = None, radius: float = None,
416+
columns: Union[List, str] = None,
417+
print_help=False, cache=True,
418+
**kwargs) -> astropy.table.Table:
419+
return self._query_on_allowed_values(table_name=EsoNames.ist_table(instrument),
420+
column_name=None,
421+
allowed_values=None,
422+
ra=ra, dec=dec, radius=radius,
423+
columns=columns,
424+
print_help=print_help, cache=cache,
425+
**kwargs)
497426

498427
def get_headers(self, product_ids, *, cache=True):
499428
"""
@@ -821,21 +750,5 @@ def query_apex_quicklooks(self, *, project_id=None, print_help=False,
821750
else:
822751
raise NotImplementedError
823752

824-
@deprecated(since="v0.4.8", message=("The ESO list_surveys function is deprecated,"
825-
"Use the list_collections function instead."))
826-
def list_surveys(self, *args, **kwargs):
827-
if "surveys" in kwargs:
828-
kwargs["collections"] = kwargs["surveys"]
829-
del kwargs["surveys"]
830-
return self.list_collections(*args, **kwargs)
831-
832-
@deprecated(since="v0.4.8", message=("The ESO query_surveys function is deprecated,"
833-
"Use the query_collections function instead."))
834-
def query_surveys(self, *args, **kwargs):
835-
if "surveys" in kwargs:
836-
kwargs["collections"] = kwargs["surveys"]
837-
del kwargs["surveys"]
838-
return self.query_collections(*args, **kwargs)
839-
840753

841754
Eso = EsoClass()

astroquery/eso/tests/test_eso.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ def test_main_SgrAstar(monkeypatch):
110110
# monkeypatch instructions from https://pytest.org/latest/monkeypatch.html
111111
eso = Eso()
112112
monkeypatch.setattr(eso, 'query_tap_service', monkey_tap)
113-
result = eso.query_raw(target='SGR A', object='SGR A')
113+
result = eso.query_main(target='SGR A', object='SGR A')
114114
# test all results are there and the expected target is present
115115
assert len(result) == 23
116116
assert 'SGR A' in result['object']

astroquery/eso/tests/test_eso_remote.py

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
from astroquery.eso import Eso
1818

1919
instrument_list = ['fors1', 'fors2', 'sphere', 'vimos', 'omegacam',
20-
'hawki', 'isaac', 'naco', 'visir', 'vircam', 'apex',
20+
'hawki', 'isaac', 'naco', 'visir', 'vircam',
21+
# TODO 'apex', uncomment when ready in the ISTs
2122
'giraffe', 'uves', 'xshooter', 'muse', 'crires',
2223
'kmos', 'sinfoni', 'amber', 'midi', 'pionier',
2324
'gravity', 'espresso', 'wlgsu', 'matisse', 'eris',
@@ -123,12 +124,14 @@ def test_empty_return(self):
123124

124125
def test_SgrAstar_remotevslocal(self, tmp_path):
125126
eso = Eso()
127+
# TODO originally it was 'gravity', but it is not yet ready in the TAP ISTs
128+
instrument = 'uves'
126129
# Remote version
127-
result1 = eso.query_instrument('gravity', ra=266.41681662,
130+
result1 = eso.query_instrument(instrument, ra=266.41681662,
128131
dec=-29.00782497, radius=1.0, cache=False)
129132
# Local version
130133
eso.cache_location = tmp_path
131-
result2 = eso.query_instrument('gravity', ra=266.41681662,
134+
result2 = eso.query_instrument(instrument, ra=266.41681662,
132135
dec=-29.00782497, radius=1.0, cache=True)
133136
assert all(result1.values_equal(result2))
134137

@@ -137,6 +140,13 @@ def test_list_instruments(self):
137140

138141
inst = set(Eso.list_instruments(cache=False))
139142

143+
# TODO ############ restore when they are fixed in TAP #
144+
try:
145+
inst.remove('apex')
146+
except ValueError:
147+
pass
148+
# #################################################### #
149+
140150
# we only care about the sets matching
141151
assert set(inst) == set(instrument_list), \
142152
f"Expected result {instrument_list}; Obtained: {inst}"
@@ -187,6 +197,23 @@ def test_each_instrument_SgrAstar(self, tmp_path):
187197

188198
instruments = eso.list_instruments(cache=False)
189199

200+
# TODO: restore all of these instruments when they are fixed in the TAP ists ##################################
201+
try:
202+
instruments.remove('apex') # ValueError: 1:0: not well-formed (invalid token)
203+
# # pyvo.dal.exceptions.DALServiceError:
204+
# 500 Server Error: for url: http://dfidev5.hq.eso.org:8123/tap_obs/sync
205+
instruments.remove('fiat') # pyvo.dal.exceptions.DALQueryError:
206+
# Error converting data type varchar to numeric.
207+
instruments.remove('espresso') # pyvo.dal.exceptions.DALQueryError: Invalid column name 'obs_container_id'
208+
instruments.remove('gravity') # pyvo.dal.exceptions.DALQueryError: Invalid column name 'obs_container_id'
209+
instruments.remove('matisse') # pyvo.dal.exceptions.DALQueryError: Invalid column name 'obs_container_id'
210+
instruments.remove('omegacam') # pyvo.dal.exceptions.DALQueryError: Invalid column name 'obs_container_id'
211+
instruments.remove('pionier') # pyvo.dal.exceptions.DALQueryError: Invalid column name 'obs_container_id'
212+
instruments.remove('vircam') # pyvo.dal.exceptions.DALQueryError: Invalid column name 'obs_container_id'
213+
except ValueError:
214+
pass
215+
# #################################################### #
216+
190217
for instrument in instruments:
191218
try:
192219
result = eso.query_instrument(instrument,
@@ -242,7 +269,7 @@ def test_main_SgrAstar(self):
242269
eso.ROW_LIMIT = 5
243270

244271
# the failure should occur here
245-
result = eso.query_raw(target='SGR A', object='SGR A')
272+
result = eso.query_main(target='SGR A', object='SGR A')
246273

247274
# test that max_results = 5
248275
assert len(result) == 5

0 commit comments

Comments
 (0)