.. _astroquery.esa.emds: ********************************************************************** ESDC Multi-Mission Data Services (EMDS) (`astroquery.esa.emds`) ********************************************************************** The ESAC Science Data Centre (ESDC) develops and operates science archives for ESA missions, providing the community with access to Planetary, Heliophysics, and Astronomy data collections. As many mission archives transition into a legacy phase, operating multiple independent archives becomes increasingly resource-intensive and can lead to software obsolescence, limited standardization, reduced interoperability, and fragmented long-term evolution. The ESDC Multi-Mission Data Services (EMDS) initiative addresses these challenges by integrating stand-alone mission archives into a unified and scalable backend system. EMDS promotes cross-disciplinary data discovery and access through standardized interoperability mechanisms, including the IVOA Table Access Protocol (TAP), and by harmonizing interfaces across scientific domains. This approach improves maintainability and scalability, supports the migration of existing archives, and provides a common foundation for future missions and shared user interfaces. ======== Examples ======== --------------- 1. Login/Logout --------------- Some tables and data require authentication to access proprietary or advanced data. Authentication is managed through the ``login()`` and ``logout()`` methods provided by the EMDS Astroquery module. .. doctest-remote-data:: >>> from astroquery.esa.emds import EmdsClass >>> emds = EmdsClass() >>> emds.login() # doctest: +SKIP >>> emds.logout() # doctest: +SKIP ----------------------------------- 2. Get available tables and columns ----------------------------------- The EMDS Astroquery module allows users to explore the data structure of the TAP by listing available tables and their columns. This is useful for understanding what data is accessible before running ADQL queries. .. doctest-remote-data:: >>> from astroquery.esa.emds import EmdsClass >>> emds = EmdsClass() >>> emds.get_tables() # doctest: +IGNORE_OUTPUT [... 24 columns ..., ... 30 columns ..., ... 30 columns ...] By default, ``get_tables()`` returns table objects with metadata. If ``only_names=True`` is provided, the method returns only the table names as strings. This is useful when you only need to inspect or display the available tables without accessing their full metadata. .. doctest-remote-data:: >>> emds.get_tables(only_names=True) # doctest: +IGNORE_OUTPUT ['einsteinprobe.fxt_product', 'einsteinprobe.obscore', 'einsteinprobe.obscore_extended', 'einsteinprobe.preview_products', 'einsteinprobe.wxt_product', 'ivoa.ObsCore', 'smile.cdf_item', 'smile.cdf_modification', 'smile.cdf_parameter', 'smile.cdf_parent', 'smile.cdf_variable', 'smile.dataset', 'smile.descriptor', ...] Once a specific table is selected using ``get_table()``, the returned object provides access to the table metadata, including its columns. .. doctest-remote-data:: >>> ivoa_obscore_table = emds.get_table(table='ivoa.ObsCore') # doctest: +IGNORE_OUTPUT >>> ivoa_obscore_table.columns # doctest: +IGNORE_OUTPUT [, , , , , , ...] .. note:: Only a subset of the available tables and columns is shown in the examples above. ------------------------- 3. Get available missions ------------------------- The EMDS TAP service is a *multi-mission* archive: multiple missions and data collections are exposed through a single TAP endpoint. Each mission typically appears as a distinct value in the ``obs_collection`` field of the EMDS global ObsCore view. .. doctest-remote-data:: >>> from astroquery.esa.emds import EmdsClass >>> emds = EmdsClass() >>> emds.list_missions() # doctest: +IGNORE_OUTPUT obs_collection object -------------- EPSA ---------------------------- 4. ADQL Queries to EMDS TAP ---------------------------- The Query TAP functionality facilitates the execution of custom Table Access Protocol (TAP) queries within the EMDS. Results can be exported to a specified file in the chosen format, and queries may be executed asynchronously. .. doctest-remote-data:: >>> from astroquery.esa.emds import EmdsClass >>> emds = EmdsClass() >>> emds.query_tap( ... query=( ... "SELECT dataproduct_type, obs_collection, obs_id, s_ra, s_dec " ... "FROM ivoa.ObsCore " ... "ORDER BY target_name DESC" ... ) ... ) # doctest: +IGNORE_OUTPUT
dataproduct_type obs_collection obs_id s_ra s_dec deg deg object object object float64 float64 ---------------- -------------- ------------ ----------------- ------------------ arf EPSA 10202076929 -- -- png EPSA 11900006256 -- -- ... ... ... ... ... lc EPSA 11900008319 81.12383618253855 17.41749240154885 pha EPSA 11900008319 81.12383621375398 17.417492453817907 ------------------------------------- 5. Filtering the Obs Core Catalogue ------------------------------------- The EMDS TAP service exposes an ObsCore-compliant catalogue (``ivoa.ObsCore``) that contains observation-level metadata (e.g. sky position, time coverage, instrument/collection identifiers, and access information). Depending on the mission and instrument, the catalogue can contain a large number of rows and many columns, so it is not recommended to retrieve all columns and all rows by default. Instead, users should filter the catalogue by selecting only the columns required for their use case and applying constraints (for example by sky region, observation collection, instrument, data product type, or other ObsCore fields). This module provides a dedicated method to query the EMDS ObsCore view and apply filters based on any available column. To check the columns available in this catalogue, the following method can be executed using ``get_metadata=True``: .. doctest-remote-data:: >>> from astroquery.esa.emds import EmdsClass >>> emds = EmdsClass() >>> obs_metadata = emds.get_observations(get_metadata=True) >>> obs_metadata["Description"].format = "%.10s" >>> obs_metadata["UType"].format = "%.20s" >>> obs_metadata # doctest: +IGNORE_OUTPUT
Column Description Unit Data Type UCD UType str17 object object str6 object object -------------- ----------- ------ --------- ------------------- -------------------- access_estsize Estimated kbyte long phys.size;meta.file obscore:Access.size access_format Content fo None char meta.code.mime obscore:Access.forma ... ... ... ... ... ... t_resolution Temporal r s double time.resolution obscore:Char.TimeAxi t_xel Number of None long meta.number obscore:Char.TimeAxi target_name Object of None char meta.id;src obscore:Target.name Once the columns of interest have been extracted, it is possible to execute the same function with the following options, that can be combined to extract the required data: + Define the reference target or coordinates where a cone search will be executed. .. doctest-remote-data:: >>> from astroquery.esa.emds import EmdsClass >>> emds = EmdsClass() >>> emds.get_observations(target_name='V1589 Cyg') # doctest: +IGNORE_OUTPUT Executed query:SELECT * FROM ivoa.ObsCore WHERE 1=CONTAINS(POINT('ICRS', s_ra, s_dec), CIRCLE('ICRS', 310.7048109, 41.3833259, 1.0))
access_estsize access_format ... t_xel target_name kbyte ... int64 object ... int64 object -------------- --------------------------- ... ----- ----------- 463680 application/x-fits-bintable ... 19233 V1589 Cyg 2888640 application/x-fits-bintable ... -- 0 51840 application/x-fits-bintable ... 961 V1589 Cyg 745920 application/x-fits-bintable ... 19233 V1589 Cyg ... ... ... ... ... 2888640 application/x-fits-bintable ... -- 0 1465920 application/x-fits-bintable ... 19234 V1589 Cyg 362880 application/x-fits-bintable ... 19234 V1589 Cyg 1465920 application/x-fits-bintable ... 19233 V1589 Cyg + Retrieve only a specific set of columns. .. doctest-remote-data:: >>> from astroquery.esa.emds import EmdsClass >>> emds = EmdsClass() >>> emds.get_observations( ... target_name="V1589 Cyg", columns=["s_ra", "s_dec", "obs_id", "s_xel1"] ... ) # doctest: +IGNORE_OUTPUT Executed query:SELECT s_ra, s_dec, obs_id, s_xel1 FROM ivoa.ObsCore WHERE 1=CONTAINS(POINT('ICRS', s_ra, s_dec), CIRCLE('ICRS', 310.7048109, 41.3833259, 1.0))
s_ra s_dec obs_id s_xel1 deg deg float64 float64 object int64 ----------------- ------------------ ----------- ------ 310.6757640621578 41.351414087733275 11900012239 95 310.6755985583337 41.351202980612555 11900012239 600 310.6755985583337 41.351202980612555 11900012239 20 310.6755985583337 41.351202980612555 11900012239 418 ... ... ... ... 310.6755985583337 41.351202980612555 11900012239 600 310.6756375374491 41.351278441170614 11900012239 600 310.6756375374491 41.351278441170614 11900012239 95 310.6757640621578 41.351414087733275 11900012239 600 + Filter by any other column available in the previous method. .. doctest-remote-data:: >>> from astroquery.esa.emds import EmdsClass >>> emds = EmdsClass() >>> emds.get_observations( ... target_name="V1589 Cyg", columns=["s_ra", "s_dec", "obs_id", "s_xel1"], s_xel1=(">", 100) ... ) # doctest: +IGNORE_OUTPUT Executed query:SELECT s_ra, s_dec, obs_id, s_xel1 FROM ivoa.ObsCore WHERE s_xel1 > 100 AND 1=CONTAINS(POINT('ICRS', s_ra, s_dec), CIRCLE('ICRS', 310.7048109, 41.3833259, 1.0))
s_ra s_dec obs_id s_xel1 deg deg float64 float64 object int64 ----------------- ------------------ ----------- ------ 310.6755985583337 41.351202980612555 11900012239 600 310.6755985583337 41.351202980612555 11900012239 418 310.6755993340324 41.35120289084306 11900012239 600 310.6755993340324 41.35120289084306 11900012239 600 310.6755993340324 41.35120289084306 11900012239 418 310.6755985583337 41.351202980612555 11900012239 600 310.6756375374491 41.351278441170614 11900012239 600 310.6757640621578 41.351414087733275 11900012239 600 As it can be observed in the previous examples, additional constraints can be provided using the ``**filters`` syntax, where the keyword corresponds to an ObsCore column name and the value defines the filter to be applied. The method translates these filters into the corresponding ADQL constraints executed by the TAP service. Some examples and their corresponding ADQL transformations are provided below: + By columns: .. doctest-remote-data:: >>> emds.get_observations( ... columns=["dataproduct_type", "obs_collection", "target_name", "obs_id", ... "s_ra", "s_dec", "instrument_name"] ... ) # doctest: +IGNORE_OUTPUT + Exact match (string): - ``obs_collection="EPSA"`` → ``obs_collection = 'EPSA'`` - ``instrument_name="FXT"`` → ``instrument_name = 'FXT'`` .. doctest-remote-data:: >>> emds.get_observations( ... columns=["obs_id", "obs_collection", "instrument_name", "dataproduct_type"], ... obs_collection="EPSA", ... instrument_name="FXT", ... ) # doctest: +IGNORE_OUTPUT + Wildcards (string): ``target_name="AT 2023%"`` → ``target_name ILIKE 'AT 2023%'`` Depending on the configuration, ``*`` may also be accepted as an alias for ``%``. .. doctest-remote-data:: >>> emds.get_observations( ... columns=["obs_id", "target_name"], ... target_name="V1589 Cyg", ... ) # doctest: +IGNORE_OUTPUT + Wildcards (string): ``coordinates`` and ``radius`` .. doctest-remote-data:: >>> emds.get_observations( ... coordinates="81.1238 17.4175", ... radius=0.1, ... columns=["obs_id", "s_ra", "s_dec", "instrument_name"], ... ) # doctest: +IGNORE_OUTPUT .. doctest-remote-data:: >>> emds.get_observations( ... target_name="V1589 Cyg", ... radius=0.1, ... columns=["obs_id", "s_ra", "s_dec", "target_name"], ... ) # doctest: +IGNORE_OUTPUT + String list: ``dataproduct_type=["img", "pha"]`` → ``dataproduct_type = 'img' OR dataproduct_type = 'pha'`` .. doctest-remote-data:: >>> emds.get_observations( ... columns=["obs_id", "dataproduct_type"], ... dataproduct_type=["img", "pha"], ... ) # doctest: +IGNORE_OUTPUT + Numeric comparison: ``t_min=(">", 60000)`` -> ``t_min > 60000`` .. doctest-remote-data:: >>> emds.get_observations( ... columns=["obs_id", "t_min", "t_max"], ... t_min=(">", 60000), ... ) # doctest: +IGNORE_OUTPUT + Filter by numeric interval: ``s_ra=(80, 82)`` -> ``s_ra >= 80 AND s_ra <= 82`` .. doctest-remote-data:: >>> emds.get_observations( ... columns=["obs_id", "s_ra", "s_dec"], ... s_ra=(80, 82), ... s_dec=(16, 18), ... ) # doctest: +IGNORE_OUTPUT + Combined filters: Multiple keyword filters are combined with ``AND``. - ``obs_collection="EPSA", instrument_name="FXT"`` → ``obs_collection = 'EPSA' AND instrument_name = 'FXT'`` .. doctest-remote-data:: >>> emds.get_observations( ... columns=["dataproduct_type", "obs_collection", "target_name", "obs_id", ... "s_ra", "s_dec", "instrument_name"], ... obs_collection="EPSA", ... dataproduct_type=["img", "pha"], ... instrument_name="FXT", ... ) # doctest: +IGNORE_OUTPUT ---------------------------- 6. Downloading data products ---------------------------- Observations in the EMDS catalogue are associated with one or more data products, such as science files or preview images. These products are stored as files on the EMDS data service and can be accessed once the corresponding observation or product identifiers are known. Typically, users first query the product catalogue to identify products of interest and inspect the available metadata. This module provides helper methods to retrieve product information based on a target name or specific selection criteria, such as observation ID, data product type, or other filters. From the selected products, the module exposes the ObsCore metadata required to download the associated files: ``obs_id``, ``obs_publisher_did``, and ``access_url``. In this example, a set of products associated with a given ``target_name`` is retrieved. .. doctest-remote-data:: >>> from astroquery.esa.emds import EmdsClass >>> emds = EmdsClass() >>> products=emds.get_products(target_name='RXCJ0120.9-1351') # doctest: +IGNORE_OUTPUT Executed query:SELECT obs_id, obs_publisher_did, access_url FROM ivoa.ObsCore WHERE 1=CONTAINS(POINT('ICRS', s_ra, s_dec),CIRCLE('ICRS', 20.244917, -13.851944, 1.0)) >>> products
obs_id ... access_url object ... object ----------- ... --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 11900004579 ... https://emds.esac.esa.int/service/data?retrieval_type=PRODUCT&QUERY=SELECT+filepath,filename+from+einsteinprobe.fxt_product+WHERE+filename='fxt_a_11900004579_ff_01_po_3ac.img' 11900004579 ... https://emds.esac.esa.int/service/data?retrieval_type=PRODUCT&QUERY=SELECT+filepath,filename+from+einsteinprobe.fxt_product+WHERE+filename='fxt_b_11900004579_ff_01_po_3ac-without_vign.expo' 11900004579 ... https://emds.esac.esa.int/service/data?retrieval_type=PRODUCT&QUERY=SELECT+filepath,filename+from+einsteinprobe.fxt_product+WHERE+filename='fxt_b_11900004579_ff_01_po_3ac.expo' 11900004579 ... https://emds.esac.esa.int/service/data?retrieval_type=PRODUCT&QUERY=SELECT+filepath,filename+from+einsteinprobe.fxt_product+WHERE+filename='fxt_a_11900004579_ff_01_po_3ac.expo' 11900004579 ... https://emds.esac.esa.int/service/data?retrieval_type=PRODUCT&QUERY=SELECT+filepath,filename+from+einsteinprobe.fxt_product+WHERE+filename='fxt_b_11900004579_ff_01_po_cl_3ac.fits' 11900004579 ... https://emds.esac.esa.int/service/data?retrieval_type=PRODUCT&QUERY=SELECT+filepath,filename+from+einsteinprobe.fxt_product+WHERE+filename='fxt_a_11900004579_ff_01_po_3ac-without_vign.expo' 11900004579 ... https://emds.esac.esa.int/service/data?retrieval_type=PRODUCT&QUERY=SELECT+filepath,filename+from+einsteinprobe.fxt_product+WHERE+filename='fxt_a_11900004579_ff_01_po_cl_3ac.fits' 11900004579 ... https://emds.esac.esa.int/service/data?retrieval_type=PRODUCT&QUERY=SELECT+filepath,filename+from+einsteinprobe.fxt_product+WHERE+filename='fxt_a_11900004579_ff_01_po_3ac.lc' 11900004579 ... https://emds.esac.esa.int/service/data?retrieval_type=PRODUCT&QUERY=SELECT+filepath,filename+from+einsteinprobe.fxt_product+WHERE+filename='fxt_b_11900004579_ff_01_po_3ac.img' 11900004579 ... https://emds.esac.esa.int/service/data?retrieval_type=PRODUCT&QUERY=SELECT+filepath,filename+from+einsteinprobe.fxt_product+WHERE+filename='fxt_b_11900004579_ff_01_po_3ac.lc' .. note:: The output is truncated for brevity. The following example shows how to download a list of files associated with a set of products selected using specific criteria (such as ``target_name`` and other ``filters``). .. doctest-remote-data:: >>> emds.download_products(products) # doctest: +IGNORE_OUTPUT ['fxt_a_11900004579_ff_01_po_3ac.img', 'fxt_b_11900004579_ff_01_po_3ac-without_vign.expo', 'fxt_b_11900004579_ff_01_po_3ac.expo', 'fxt_a_11900004579_ff_01_po_3ac.expo', 'fxt_a_11900004579_ff_01_po_3ac.lc', 'fxt_b_11900004579_ff_01_po_cl_3ac.fits', 'fxt_b_11900004579_ff_01_po_3ac.img', 'fxt_b_11900004579_ff_01_po_3ac.lc', 'fxt_a_11900004579_ff_01_po_3ac-without_vign.expo', 'fxt_a_11900004579_ff_01_po_cl_3ac.fits'] Products download method returns the stored files in the archive, and provides a list of these downloaded files. Reference/API ============= .. automodapi:: astroquery.esa.emds :no-inheritance-diagram: :inherited-members: EMDS submodules =============== .. toctree:: :maxdepth: 1 einsteinprobe/einsteinprobe