Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ esa.euclid

- New cross-match method [#3386]

- New method, ``get_datalinks_metadata``, to retrieve additional columns
from the datalinks metadata. [#3438]

esa.hubble
^^^^^^^^^^

Expand Down
30 changes: 28 additions & 2 deletions astroquery/esa/euclid/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1418,7 +1418,7 @@ def get_spectrum(self, *, source_id, schema='sedm', retrieval_type="ALL", output

return files

def get_datalinks(self, ids, *, linking_parameter='SOURCE_ID', verbose=False):
def get_datalinks(self, ids, *, linking_parameter='SOURCE_ID', options=None, verbose=False):
"""Gets datalinks associated to the provided identifiers
TAP+ only

Expand All @@ -1428,6 +1428,8 @@ def get_datalinks(self, ids, *, linking_parameter='SOURCE_ID', verbose=False):
list of identifiers
linking_parameter : str, optional, default SOURCE_ID, valid values: SOURCE_ID
By default, all the identifiers are considered as source_id
options : str, optional, default None
To let customize the server behaviour
Comment on lines +1431 to +1432
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

options feels very generic; could we be more specific naming this?
Also, I would find it useful to mention what valid values could be for this, from the example below 'METADATA' is one, but how could the user know what else works?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In addition, adding a new kwarg is an API change, thus will need to be mentioned in the changelog

verbose : bool, optional, default 'False'
flag to display information about the process

Expand All @@ -1437,7 +1439,31 @@ def get_datalinks(self, ids, *, linking_parameter='SOURCE_ID', verbose=False):

"""

return self.__eucliddata.get_datalinks(ids=ids, linking_parameter=linking_parameter, verbose=verbose)
return self.__eucliddata.get_datalinks(ids=ids,
linking_parameter=linking_parameter,
options=options,
verbose=verbose)

def get_datalinks_metadata(self, ids, *, linking_parameter='SOURCE_ID', verbose=False):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why have this as a separate method rather than just documenting the one needs to have use options='METADATA'? The narrative documentation example below throw me off the track as starting with that one, and based on the method name I expected only metadata rather than it having the same result as using get_datalinks and some extra metadata.

"""Gets datalinks associated to the provided identifiers, including additional metadata (the datalabs_path)
TAP+ only

Parameters
----------
ids : str, int, list of str or list of int, mandatory
List of identifiers
linking_parameter : str, optional, default SOURCE_ID, valid values: SOURCE_ID
By default, all the identifiers are considered as source_id
verbose : bool, optional, default 'False'
Flag to display information about the process

Returns
-------
A table object

"""

return self.get_datalinks(ids=ids, linking_parameter=linking_parameter, options='METADATA', verbose=verbose)

def get_scientific_product_list(self, *, observation_id=None, tile_index=None, category=None, group=None,
product_type=None, dataset_release='REGREPROC1_R2', verbose=False):
Expand Down
22 changes: 20 additions & 2 deletions astroquery/esa/euclid/tests/test_euclidtap.py
Original file line number Diff line number Diff line change
Expand Up @@ -1220,19 +1220,37 @@ def test_logout(mock_logout):


def test_get_datalinks(monkeypatch):
def get_datalinks_monkeypatched(self, ids, linking_parameter, verbose):
def get_datalinks_monkeypatched(self, ids, linking_parameter, options, verbose):
return Table()

# `EuclidClass` is a subclass of `TapPlus`, but it does not inherit
# `get_datalinks()`, it replaces it with a call to the `get_datalinks()`
# of its `__gaiadata`.
# of its `__eucliddata`.
monkeypatch.setattr(TapPlus, "get_datalinks", get_datalinks_monkeypatched)
euclid = EuclidClass(show_server_messages=False)

result = euclid.get_datalinks(ids=[12345678], verbose=True)
assert isinstance(result, Table)


def test_get_datalinks_metadata(monkeypatch):
def get_datalinks_monkeypatched(self, ids, linking_parameter, options, verbose):
table = TapTableMeta()
table.name = options
return table

# `EuclidClass` is a subclass of `TapPlus`, but it does not inherit
# `get_datalinks()`, it replaces it with a call to the `get_datalinks()`
# of its `__eucliddata`. get_datalinks_metadata delegates to get_datalinks,
# which in turn delegates to TapPlus' get_datalinks
monkeypatch.setattr(TapPlus, "get_datalinks", get_datalinks_monkeypatched)
euclid = EuclidClass(show_server_messages=False)

result = euclid.get_datalinks_metadata(ids=[12345678], verbose=True)
assert isinstance(result, TapTableMeta)
assert result.name == "METADATA"


@pytest.mark.parametrize("background", [False, True])
def test_cross_match_basic(monkeypatch, background, cross_match_basic_kwargs, mock_querier_async):
def load_table_monkeypatched(self, table, verbose):
Expand Down
22 changes: 13 additions & 9 deletions astroquery/utils/tap/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1247,20 +1247,22 @@ def is_valid_user(self, *, user_id=None, verbose=False):
print(f"USER response = {user}")
return user.startswith(f"{user_id}:") and user.count("\\n") == 0

def get_datalinks(self, ids, *, linking_parameter=None, verbose=False):
def get_datalinks(self, ids, *, linking_parameter=None, options=None, verbose=False):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will need to be mentioned in the changelog

"""Gets datalinks associated to the provided identifiers

Parameters
----------
ids : str list, mandatory
list of identifiers
List of identifiers
linking_parameter : str, optional, default SOURCE_ID, valid values: SOURCE_ID, TRANSIT_ID, IMAGE_ID
By default, all the identifiers are considered as source_id
SOURCE_ID: the identifiers are considered as source_id
TRANSIT_ID: the identifiers are considered as transit_id
IMAGE_ID: the identifiers are considered as sif_observation_id
options : str, optional, default None
If present, an extra parameter OPTIONS will be added to the call, to be interpreted by the TAP service
verbose : bool, optional, default 'False'
flag to display information about the process
Flag to display information about the process

Returns
-------
Expand All @@ -1282,15 +1284,17 @@ def get_datalinks(self, ids, *, linking_parameter=None, verbose=False):
if linking_parameter is not None:
ids_arg = f'{ids_arg}&LINKING_PARAMETER={linking_parameter}'

if options is not None:
ids_arg = f'{ids_arg}&OPTIONS={options}'

if verbose:
print(f"Datalink request: {ids_arg}")
connHandler = self.__getconnhandler()
response = connHandler.execute_datalinkpost(subcontext="links",
data=ids_arg,
verbose=verbose)
print(f"Datalink request: ID={ids_arg}")

conn_handler = self.__getconnhandler()
response = conn_handler.execute_datalinkpost(subcontext="links", data=ids_arg, verbose=verbose)
if verbose:
print(response.status, response.reason)
connHandler.check_launch_response_status(response, verbose, 200)
conn_handler.check_launch_response_status(response, verbose, 200)
if verbose:
print("Done.")
results = utils.read_http_response(response, "votable", use_names_over_ids=self.use_names_over_ids)
Expand Down
14 changes: 14 additions & 0 deletions docs/esa/euclid/euclid.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1215,6 +1215,20 @@ To find out the resources associated with a given source:
sedm 2707008224650763513 SOURCE_ID https://eas.esac.esa.int/sas-dd/data?ID=sedm+2707008224650763513&RETRIEVAL_TYPE=SPECTRA_BGS #this Spectra Blue Source --


Euclid also provides a way to execute a similar call by getting the datalabs_path as an additional column:

.. Skipping authentication requiring examples
.. doctest-skip::

>>> from astroquery.esa.euclid import Euclid
>>> Euclid.login()
>>> result = Euclid.get_datalinks_metadata(ids=2707008224650763513)
>>> print(result)
ID linking_parameter access_url service_def ... content_type content_length datalabs_path
... byte
------------------------ ----------------- ------------------------------------------------------------------------------------------------------- ----------- ... ------------ -------------- -----------------------------------
sedm 2707008224650763513 SOURCE_ID https://eas.esac.esa.int/sas-dd/datalink/data?ID=sedm+2707008224650763513&RETRIEVAL_TYPE=SPECTRA_RGS ... -- /data/euclid_q1/Q1_R1/SIR/102158586
sedm 2707008224650763513 SOURCE_ID https://eas.esac.esa.int/sas-dd/datalink/data?ID=sedm+2707008224650763513&RETRIEVAL_TYPE=SPECTRA_BGS ... -- /data/euclid_q1/Q1_R1/SIR/102158586


The query below retrieves a random sample of Euclid sources having spectra.
Expand Down
Loading