Edit on GitHub

uio.utility.databases.simbad

Getting data from SIMBAD astronomical database.

  1"""
  2Getting data from [SIMBAD](https://simbad.u-strasbg.fr/simbad/)
  3astronomical database.
  4"""
  5
  6from astroquery.simbad import Simbad
  7import re
  8
  9from typing import Optional, Any
 10
 11from ..logs.log import logger
 12from ..databases import tap
 13
 14
 15def findIdentificatorFromAnotherCatalogue(
 16    starName: str,
 17    otherIDname: str,
 18    otherIDversion: Optional[str] = None,
 19    withoutIDprefix: bool = True
 20) -> Optional[str]:
 21    """
 22    Finds object identificator from a particular catalogue. SIMBAD returns
 23    a list of identificators prepended with the catalogue name, and this
 24    function finds the identificator for the specified catalogue and returns
 25    just the identificator. In addition to that, some catalogues have versions,
 26    so it is possible to specify which one if of interest.
 27
 28    For instance, if you need to find the identificator for `TWA 20` star
 29    in `Gaia` catalog version `DR3`, then SIMBAD will return
 30    `Gaia DR3 6132146982868270976` value for it, out of which this function
 31    will extract `6132146982868270976` as the result.
 32
 33    Example:
 34
 35    ``` py
 36    from uio.utility.databases import simbad
 37
 38    otherID = simbad.findIdentificatorFromAnotherCatalogue(
 39        "TWA 20",
 40        "gaia",
 41        "dr3"
 42    )
 43    print(otherID)
 44    ```
 45    """
 46    otherID = None
 47
 48    otherIDs = Simbad.query_objectids(starName)
 49    if otherIDs is None:
 50        logger.warning(
 51            " ".join((
 52                "SIMBAD database doesn't have information",
 53                f"about [{starName}]"
 54            ))
 55        )
 56    else:
 57        logger.debug(f"Checking SIMBAD IDs for [{starName}]:")
 58        for oid in otherIDs:
 59            idCandidate: str = oid["ID"]
 60            logger.debug(f"- {idCandidate}")
 61            if otherIDname.lower() in idCandidate.lower():
 62                idToLookFor = (
 63                    f"{otherIDname} {otherIDversion}"
 64                    if otherIDversion else otherIDname
 65                )
 66                if idToLookFor.lower() in idCandidate.lower():
 67                    if withoutIDprefix:
 68                        prefixRE = re.compile(
 69                            rf"{idToLookFor}\s?",
 70                            re.IGNORECASE
 71                        )
 72                        otherID = prefixRE.sub("", idCandidate)
 73                    else:
 74                        otherID = idCandidate
 75                    break
 76    return otherID
 77
 78
 79def getObjectID(starName: str) -> Optional[int]:
 80    """
 81    Finds object identificator for
 82    [SIMBAD tables](http://simbad.cds.unistra.fr/simbad/tap/tapsearch.html).
 83    It is stored in the `oid` field of the `basic` table.
 84
 85    The discovery process is to compare all the known object identificators
 86    with the `main_id` field value (*also from the `basic` table*). It is
 87    not clear, how exactly SIMBAD maintainers choose the main ID for an object,
 88    so one has to iterate through all the identificators known to SIMBAD.
 89
 90    Example:
 91
 92    ``` py
 93    from uio.utility.databases import simbad
 94
 95    oid = simbad.getObjectID("A2 146")
 96    print(oid)
 97    ```
 98    """
 99    oid: Optional[int] = None
100
101    # check if this name is already the main ID
102    logger.debug(f"Checking whether [{starName}] is already the main ID")
103    rez = tap.queryService(
104        tap.getServiceEndpoint("simbad"),
105        " ".join((
106            "SELECT oid",
107            "FROM basic",
108            f"WHERE main_id = '{starName}'"
109        ))
110    )
111    if rez:
112        oid = rez[0]["oid"]
113        logger.debug(
114            " ".join((
115                f"- yes, that is already the main ID,",
116                "no need to iterate all the identificators.",
117                f"SIMBAD object ID is: {oid}"
118            ))
119        )
120    else:
121        logger.debug(
122            " ".join((
123                "- no, that is not the main ID, will have to iterate",
124                "all the other identificators"
125            ))
126        )
127        ids = Simbad.query_objectids(starName)
128        if ids is None:
129            logger.warning(
130                " ".join((
131                    "SIMBAD database doesn't have information",
132                    f"about [{starName}]"
133                ))
134            )
135        else:
136            logger.debug(f"Checking SIMBAD IDs for [{starName}]:")
137            for id in ids:
138                idValue = id["ID"]
139                logger.debug(f"- {idValue}")
140                if idValue == starName:
141                    logger.debug(
142                        f"...the [{idValue}] has already been tested, skipping"
143                    )
144                    continue
145                rez = tap.queryService(
146                    tap.getServiceEndpoint("simbad"),
147                    " ".join((
148                        "SELECT oid",
149                        "FROM basic",
150                        f"WHERE main_id = '{idValue}'"
151                    ))
152                )
153                if rez:
154                    oid = rez[0]["oid"]
155                    logger.debug(
156                        " ".join((
157                            f"The [{idValue}] is the main ID for [{starName}],",
158                            f"SIMBAD object ID is: {oid}"
159                        ))
160                    )
161                    break
162    return oid
163
164
165def getStellarParameter(
166    starName: str,
167    table: str,
168    param: str
169) -> Optional[tuple[Any, str]]:
170    """
171    A convenience function for querying SIMBAD for a stellar parameter:
172
173    1. Finds SIMBAD's object ID by the star name (*with `uio.utility.databases.simbad.getObjectID`*);
174    2. Queries for a stellar parameter by that object ID (*with `uio.utility.databases.tap.getStellarParameterFromSimbadByObjectID`*).
175
176    Example:
177
178    ``` py
179    from uio.utility.databases import simbad
180
181    starName = "PPM 725297"
182    param = "period"
183    rez = simbad.getStellarParameter(
184        starName,
185        "mesVar",
186        param
187    )
188    if rez:
189        val = rez[0]
190        ref = rez[1]
191        print(f"Value: {val}, reference: {ref}")
192    else:
193        print(f"SIMBAD doesn't have data about [{param}] parameter of [{starName}] object")
194    ```
195    """
196    rez: Optional[tuple[Any, str]] = None
197
198    oid = getObjectID(starName)
199    if oid:
200        # logger.debug(
201        #     f"Found the following object ID for [{starName}]: {oid}"
202        # )
203        rez = tap.getStellarParameterFromSimbadByObjectID(
204            oid,
205            table,
206            param
207        )
208
209    return rez
def findIdentificatorFromAnotherCatalogue( starName: str, otherIDname: str, otherIDversion: Optional[str] = None, withoutIDprefix: bool = True) -> Optional[str]:
16def findIdentificatorFromAnotherCatalogue(
17    starName: str,
18    otherIDname: str,
19    otherIDversion: Optional[str] = None,
20    withoutIDprefix: bool = True
21) -> Optional[str]:
22    """
23    Finds object identificator from a particular catalogue. SIMBAD returns
24    a list of identificators prepended with the catalogue name, and this
25    function finds the identificator for the specified catalogue and returns
26    just the identificator. In addition to that, some catalogues have versions,
27    so it is possible to specify which one if of interest.
28
29    For instance, if you need to find the identificator for `TWA 20` star
30    in `Gaia` catalog version `DR3`, then SIMBAD will return
31    `Gaia DR3 6132146982868270976` value for it, out of which this function
32    will extract `6132146982868270976` as the result.
33
34    Example:
35
36    ``` py
37    from uio.utility.databases import simbad
38
39    otherID = simbad.findIdentificatorFromAnotherCatalogue(
40        "TWA 20",
41        "gaia",
42        "dr3"
43    )
44    print(otherID)
45    ```
46    """
47    otherID = None
48
49    otherIDs = Simbad.query_objectids(starName)
50    if otherIDs is None:
51        logger.warning(
52            " ".join((
53                "SIMBAD database doesn't have information",
54                f"about [{starName}]"
55            ))
56        )
57    else:
58        logger.debug(f"Checking SIMBAD IDs for [{starName}]:")
59        for oid in otherIDs:
60            idCandidate: str = oid["ID"]
61            logger.debug(f"- {idCandidate}")
62            if otherIDname.lower() in idCandidate.lower():
63                idToLookFor = (
64                    f"{otherIDname} {otherIDversion}"
65                    if otherIDversion else otherIDname
66                )
67                if idToLookFor.lower() in idCandidate.lower():
68                    if withoutIDprefix:
69                        prefixRE = re.compile(
70                            rf"{idToLookFor}\s?",
71                            re.IGNORECASE
72                        )
73                        otherID = prefixRE.sub("", idCandidate)
74                    else:
75                        otherID = idCandidate
76                    break
77    return otherID

Finds object identificator from a particular catalogue. SIMBAD returns a list of identificators prepended with the catalogue name, and this function finds the identificator for the specified catalogue and returns just the identificator. In addition to that, some catalogues have versions, so it is possible to specify which one if of interest.

For instance, if you need to find the identificator for TWA 20 star in Gaia catalog version DR3, then SIMBAD will return Gaia DR3 6132146982868270976 value for it, out of which this function will extract 6132146982868270976 as the result.

Example:

from uio.utility.databases import simbad

otherID = simbad.findIdentificatorFromAnotherCatalogue(
    "TWA 20",
    "gaia",
    "dr3"
)
print(otherID)
def getObjectID(starName: str) -> Optional[int]:
 80def getObjectID(starName: str) -> Optional[int]:
 81    """
 82    Finds object identificator for
 83    [SIMBAD tables](http://simbad.cds.unistra.fr/simbad/tap/tapsearch.html).
 84    It is stored in the `oid` field of the `basic` table.
 85
 86    The discovery process is to compare all the known object identificators
 87    with the `main_id` field value (*also from the `basic` table*). It is
 88    not clear, how exactly SIMBAD maintainers choose the main ID for an object,
 89    so one has to iterate through all the identificators known to SIMBAD.
 90
 91    Example:
 92
 93    ``` py
 94    from uio.utility.databases import simbad
 95
 96    oid = simbad.getObjectID("A2 146")
 97    print(oid)
 98    ```
 99    """
100    oid: Optional[int] = None
101
102    # check if this name is already the main ID
103    logger.debug(f"Checking whether [{starName}] is already the main ID")
104    rez = tap.queryService(
105        tap.getServiceEndpoint("simbad"),
106        " ".join((
107            "SELECT oid",
108            "FROM basic",
109            f"WHERE main_id = '{starName}'"
110        ))
111    )
112    if rez:
113        oid = rez[0]["oid"]
114        logger.debug(
115            " ".join((
116                f"- yes, that is already the main ID,",
117                "no need to iterate all the identificators.",
118                f"SIMBAD object ID is: {oid}"
119            ))
120        )
121    else:
122        logger.debug(
123            " ".join((
124                "- no, that is not the main ID, will have to iterate",
125                "all the other identificators"
126            ))
127        )
128        ids = Simbad.query_objectids(starName)
129        if ids is None:
130            logger.warning(
131                " ".join((
132                    "SIMBAD database doesn't have information",
133                    f"about [{starName}]"
134                ))
135            )
136        else:
137            logger.debug(f"Checking SIMBAD IDs for [{starName}]:")
138            for id in ids:
139                idValue = id["ID"]
140                logger.debug(f"- {idValue}")
141                if idValue == starName:
142                    logger.debug(
143                        f"...the [{idValue}] has already been tested, skipping"
144                    )
145                    continue
146                rez = tap.queryService(
147                    tap.getServiceEndpoint("simbad"),
148                    " ".join((
149                        "SELECT oid",
150                        "FROM basic",
151                        f"WHERE main_id = '{idValue}'"
152                    ))
153                )
154                if rez:
155                    oid = rez[0]["oid"]
156                    logger.debug(
157                        " ".join((
158                            f"The [{idValue}] is the main ID for [{starName}],",
159                            f"SIMBAD object ID is: {oid}"
160                        ))
161                    )
162                    break
163    return oid

Finds object identificator for SIMBAD tables. It is stored in the oid field of the basic table.

The discovery process is to compare all the known object identificators with the main_id field value (also from the basic table). It is not clear, how exactly SIMBAD maintainers choose the main ID for an object, so one has to iterate through all the identificators known to SIMBAD.

Example:

from uio.utility.databases import simbad

oid = simbad.getObjectID("A2 146")
print(oid)
def getStellarParameter(starName: str, table: str, param: str) -> Optional[tuple[Any, str]]:
166def getStellarParameter(
167    starName: str,
168    table: str,
169    param: str
170) -> Optional[tuple[Any, str]]:
171    """
172    A convenience function for querying SIMBAD for a stellar parameter:
173
174    1. Finds SIMBAD's object ID by the star name (*with `uio.utility.databases.simbad.getObjectID`*);
175    2. Queries for a stellar parameter by that object ID (*with `uio.utility.databases.tap.getStellarParameterFromSimbadByObjectID`*).
176
177    Example:
178
179    ``` py
180    from uio.utility.databases import simbad
181
182    starName = "PPM 725297"
183    param = "period"
184    rez = simbad.getStellarParameter(
185        starName,
186        "mesVar",
187        param
188    )
189    if rez:
190        val = rez[0]
191        ref = rez[1]
192        print(f"Value: {val}, reference: {ref}")
193    else:
194        print(f"SIMBAD doesn't have data about [{param}] parameter of [{starName}] object")
195    ```
196    """
197    rez: Optional[tuple[Any, str]] = None
198
199    oid = getObjectID(starName)
200    if oid:
201        # logger.debug(
202        #     f"Found the following object ID for [{starName}]: {oid}"
203        # )
204        rez = tap.getStellarParameterFromSimbadByObjectID(
205            oid,
206            table,
207            param
208        )
209
210    return rez

A convenience function for querying SIMBAD for a stellar parameter:

  1. Finds SIMBAD's object ID by the star name (with uio.utility.databases.simbad.getObjectID);
  2. Queries for a stellar parameter by that object ID (with uio.utility.databases.tap.getStellarParameterFromSimbadByObjectID).

Example:

from uio.utility.databases import simbad

starName = "PPM 725297"
param = "period"
rez = simbad.getStellarParameter(
    starName,
    "mesVar",
    param
)
if rez:
    val = rez[0]
    ref = rez[1]
    print(f"Value: {val}, reference: {ref}")
else:
    print(f"SIMBAD doesn't have data about [{param}] parameter of [{starName}] object")