Skip to content

Commit 2417b16

Browse files
jespinosaar“Javier
authored andcommitted
download_product with type and HAP observations
1 parent 98e9537 commit 2417b16

File tree

3 files changed

+198
-23
lines changed

3 files changed

+198
-23
lines changed

astroquery/esa/hubble/core.py

Lines changed: 169 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class ESAHubbleClass(BaseQuery):
4343
TIMEOUT = conf.TIMEOUT
4444
calibration_levels = {0: "AUXILIARY", 1: "RAW", 2: "CALIBRATED",
4545
3: "PRODUCT"}
46+
product_types = ["PRODUCT", "SCIENCE_PRODUCT", "POSTCARD"]
4647
copying_string = "Copying file to {0}..."
4748

4849
def __init__(self, tap_handler=None):
@@ -54,10 +55,11 @@ def __init__(self, tap_handler=None):
5455
else:
5556
self._tap = tap_handler
5657

57-
def download_product(self, observation_id, calibration_level="RAW",
58-
filename=None, verbose=False):
58+
def download_product(self, observation_id, calibration_level=None,
59+
product_type=None, filename=None, verbose=False):
5960
"""
60-
Download products from EHST
61+
Download products from EHST based on their observation ID and the
62+
calibration level or the product type.
6163
6264
Parameters
6365
----------
@@ -66,10 +68,13 @@ def download_product(self, observation_id, calibration_level="RAW",
6668
The identifier of the observation we want to retrieve, regardless
6769
of whether it is simple or composite.
6870
calibration_level : string
69-
calibration level, optional, default 'RAW'
71+
calibration level, optional
7072
The identifier of the data reduction/processing applied to the
7173
data. By default, the most scientifically relevant level will be
7274
chosen. RAW, CALIBRATED, PRODUCT or AUXILIARY
75+
product_type : string
76+
type of product retrieval, optional
77+
PRODUCT, SCIENCE_PRODUCT or POSTCARD
7378
filename : string
7479
file name to be used to store the artifact, optional, default
7580
None
@@ -83,22 +88,47 @@ def download_product(self, observation_id, calibration_level="RAW",
8388
None. It downloads the observation indicated
8489
"""
8590

86-
params = {"OBSERVATION_ID": observation_id,
87-
"CALIBRATION_LEVEL": calibration_level}
91+
params = {"OBSERVATION_ID": observation_id}
92+
url = self.data_url + "?OBSERVATION_ID=" + observation_id
8893

8994
if filename is None:
9095
filename = observation_id + ".tar"
9196

97+
if calibration_level:
98+
params["CALIBRATION_LEVEL"] = calibration_level
99+
url += "&CALIBRATION_LEVEL=" + calibration_level
100+
101+
if product_type:
102+
self.__validate_product_type(product_type)
103+
params["RETRIEVAL_TYPE"] = product_type
104+
filename = self._get_product_filename(product_type, filename)
105+
url += "&RETRIEVAL_TYPE=" + params["RETRIEVAL_TYPE"]
106+
92107
response = self._request('GET', self.data_url, save=True, cache=True,
93108
params=params)
94109

95110
if verbose:
96-
log.info(self.data_url + "?OBSERVATION_ID=" + observation_id +
97-
"&CALIBRATION_LEVEL=" + calibration_level)
111+
log.info(url)
98112
log.info(self.copying_string.format(filename))
99113

100114
shutil.move(response, filename)
101115

116+
def __validate_product_type(self, product_type):
117+
if(product_type not in self.product_types):
118+
raise ValueError("This product_type is not allowed")
119+
120+
def _get_product_filename(self, product_type, filename):
121+
if(product_type == "PRODUCT"):
122+
return filename
123+
elif(product_type == "SCIENCE_PRODUCT"):
124+
log.info("This is a SCIENCE_PRODUCT, the filename will be "
125+
"renamed to " + filename + ".fits.gz")
126+
return filename + ".fits.gz"
127+
else:
128+
log.info("This is a POSTCARD, the filename will be "
129+
"renamed to " + filename + ".jpg")
130+
return filename + ".jpg"
131+
102132
def get_artifact(self, artifact_id, filename=None, verbose=False):
103133
"""
104134
Download artifacts from EHST. Artifact is a single Hubble product file.
@@ -319,11 +349,11 @@ def query_hst_tap(self, query, async_job=False, output_file=None,
319349
return table
320350

321351
def query_criteria(self, calibration_level=None,
322-
data_product_type=None, intent=None,
323-
obs_collection=None, instrument_name=None,
324-
filters=None, async_job=True, output_file=None,
325-
output_format="votable", verbose=False,
326-
get_query=False):
352+
data_product_type=None, intent=None,
353+
obs_collection=None, instrument_name=None,
354+
filters=None, async_job=True, output_file=None,
355+
output_format="votable", verbose=False,
356+
get_query=False):
327357
"""
328358
Launches a synchronous or asynchronous job to query the HST tap
329359
using calibration level, data product type, intent, collection,
@@ -433,6 +463,132 @@ def __check_list_strings(self, list):
433463
raise ValueError("One of the lists is empty or there are "
434464
"elements that are not strings")
435465

466+
def get_hap_observations(self, async_job=True, output_file=None,
467+
output_format="votable",
468+
verbose=False):
469+
"""Launches a synchronous or asynchronous job to extract ALL HAP
470+
observations
471+
472+
Parameters
473+
----------
474+
async_job : bool, optional, default 'False'
475+
executes the query (job) in asynchronous/synchronous mode (default
476+
synchronous)
477+
output_file : str, optional, default None
478+
file name where the results are saved if dumpToFile is True.
479+
If this parameter is not provided, the jobid is used instead
480+
output_format : str, optional, default 'votable'
481+
results format
482+
verbose : bool, optional, default 'False'
483+
flag to display information about the process
484+
485+
Returns
486+
-------
487+
A table object
488+
"""
489+
query = "select o.*, p.proposal_type from ehst.observation as o LEFT "\
490+
"JOIN ehst.proposal as p on o.proposal_id = p.proposal_id "\
491+
"LEFT JOIN ehst.plane as pl on pl.observation_uuid = "\
492+
"o.observation_uuid where (o.observation_id like '%hst%' AND "\
493+
"p.proposal_type like '%HAP%' AND (o.obs_type like '%HST "\
494+
"Simple%' OR o.obs_type like '%HST Composite%' OR o.obs_type "\
495+
"like '%HST Singleton%') AND o.collection LIKE '%HST%' AND "\
496+
"pl.main_science_plane = 'true') ORDER BY o.observation_id"
497+
if verbose:
498+
print(query)
499+
job = self.query_hst_tap(query=query, async_job=async_job,
500+
output_file=output_file,
501+
output_format=output_format,
502+
verbose=verbose)
503+
try:
504+
table = job.get_results()
505+
except Exception:
506+
raise ValueError('There are not HAP observations in this DB')
507+
508+
return table
509+
510+
def get_hap_proposals(self, async_job=True, output_file=None,
511+
output_format="votable",
512+
verbose=False):
513+
"""Launches a synchronous or asynchronous job to extract ALL HAP
514+
proposals
515+
516+
Parameters
517+
----------
518+
async_job : bool, optional, default 'False'
519+
executes the query (job) in asynchronous/synchronous mode (default
520+
synchronous)
521+
output_file : str, optional, default None
522+
file name where the results are saved if dumpToFile is True.
523+
If this parameter is not provided, the jobid is used instead
524+
output_format : str, optional, default 'votable'
525+
results format
526+
verbose : bool, optional, default 'False'
527+
flag to display information about the process
528+
529+
Returns
530+
-------
531+
A table object
532+
"""
533+
query = "select distinct p.* from ehst.proposal as p LEFT JOIN "\
534+
"ehst.observation as o on o.proposal_id = p.proposal_id "\
535+
"where (p.proposal_type LIKE '%HAP%' AND o.observation_id "\
536+
"like '%hst%' AND o.collection LIKE '%HST%') ORDER BY "\
537+
"p.proposal_id DESC"
538+
if verbose:
539+
print(query)
540+
job = self.query_hst_tap(query=query, async_job=async_job,
541+
output_file=output_file,
542+
output_format=output_format,
543+
verbose=verbose)
544+
try:
545+
table = job.get_results()
546+
except Exception:
547+
raise ValueError('There are not HAP observations in this DB')
548+
return table
549+
550+
def get_hap_publications(self, async_job=False, output_file=None,
551+
output_format="votable",
552+
verbose=False):
553+
"""Launches a synchronous or asynchronous job to extract ALL HAP
554+
publications
555+
556+
Parameters
557+
----------
558+
async_job : bool, optional, default 'False'
559+
executes the query (job) in asynchronous/synchronous mode (default
560+
synchronous)
561+
output_file : str, optional, default None
562+
file name where the results are saved if dumpToFile is True.
563+
If this parameter is not provided, the jobid is used instead
564+
output_format : str, optional, default 'votable'
565+
results format
566+
verbose : bool, optional, default 'False'
567+
flag to display information about the process
568+
569+
Returns
570+
-------
571+
A table object
572+
"""
573+
query = "select distinct pb.* from ehst.publication as pb LEFT JOIN "\
574+
"ehst.publication_proposal as pp on pp.bib_code = "\
575+
"pb.bib_code LEFT JOIN ehst.proposal as p on pp.proposal_id="\
576+
"p.proposal_id LEFT JOIN ehst.observation as o on "\
577+
"o.proposal_id = p.proposal_id WHERE (p.proposal_type "\
578+
"LIKE '%HAP%' AND o.observation_id like '%hst%' AND "\
579+
"o.collection LIKE '%HST%') ORDER BY pb.bib_code DESC"
580+
if verbose:
581+
print(query)
582+
job = self.query_hst_tap(query=query, async_job=async_job,
583+
output_file=output_file,
584+
output_format=output_format,
585+
verbose=verbose)
586+
try:
587+
table = job.get_results()
588+
except Exception:
589+
raise ValueError('There are not HAP observations in this DB')
590+
return table
591+
436592
def get_tables(self, only_names=True, verbose=False):
437593
"""Get the available table in EHST TAP service
438594

astroquery/esa/hubble/tests/dummy_tap_handler.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,10 @@ def launch_job_async(self, query, name=None, output_file=None,
8989
return Job(True)
9090

9191
def query_criteria(self, calibration_level=None,
92-
data_product_type=None, intent=None,
93-
obs_collection=None, instrument_name=None,
94-
filters=None, async_job=False, output_file=None,
95-
output_format="votable", verbose=False):
92+
data_product_type=None, intent=None,
93+
obs_collection=None, instrument_name=None,
94+
filters=None, async_job=False, output_file=None,
95+
output_format="votable", verbose=False):
9696
self.__invokedMethod = 'query_criteria'
9797
self._parameters['calibration_level'] = calibration_level
9898
self._parameters['data_product_type'] = data_product_type

astroquery/esa/hubble/tests/test_esa_hubble.py

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,35 @@ def get_dummy_tap_handler(self):
5858
dummyTapHandler = DummyHubbleTapHandler("launch_job", parameterst)
5959
return dummyTapHandler
6060

61-
def test_download_product(self):
61+
def test_download_product_errors(self):
62+
ehst = ESAHubbleClass(self.get_dummy_tap_handler())
63+
64+
with pytest.raises(ValueError) as err:
65+
ehst.download_product(observation_id="J6FL25S4Q",
66+
product_type="SCIENCE")
67+
assert "This product_type is not allowed" in err.value.args[0]
68+
69+
def test_download_product_by_calibration(self):
70+
parameters = {'observation_id': "J6FL25S4Q",
71+
'cal_level': "RAW",
72+
'filename': "J6FL25S4Q.vot",
73+
'verbose': True}
74+
ehst = ESAHubbleClass(self.get_dummy_tap_handler())
75+
ehst.download_product(observation_id=parameters['observation_id'],
76+
calibration_level=parameters['cal_level'],
77+
filename=parameters['filename'],
78+
verbose=parameters['verbose'])
79+
80+
def test_download_product_by_product_type(self):
6281
parameters = {'observation_id': "J6FL25S4Q",
63-
'calibration_level': "RAW",
82+
'product_type': "SCIENCE_PRODUCT",
6483
'filename': "J6FL25S4Q.vot",
6584
'verbose': True}
6685
ehst = ESAHubbleClass(self.get_dummy_tap_handler())
67-
ehst.download_product(parameters['observation_id'],
68-
parameters['calibration_level'],
69-
parameters['filename'],
70-
parameters['verbose'])
86+
ehst.download_product(observation_id=parameters['observation_id'],
87+
product_type=parameters['product_type'],
88+
filename=parameters['filename'],
89+
verbose=parameters['verbose'])
7190

7291
def test_get_postcard(self):
7392
ehst = ESAHubbleClass(self.get_dummy_tap_handler())

0 commit comments

Comments
 (0)