""" Module for parsing astronomical object names to extract embedded coordinates eg: '2MASS J06495091-0737408'. """ import re import numpy as np import astropy.units as u from astropy.coordinates import SkyCoord RA_REGEX = r"()([0-2]\d)([0-5]\d)([0-5]\d)\.?(\d{0,3})" DEC_REGEX = r"([+-])(\d{1,2})([0-5]\d)([0-5]\d)\.?(\d{0,3})" JCOORD_REGEX = "(.*?J)" + RA_REGEX + DEC_REGEX JPARSER = re.compile(JCOORD_REGEX) def _sexagesimal(g): # convert matched regex groups to sexigesimal array sign, h, m, s, frac = g sign = -1 if (sign == "-") else 1 s = f"{s}.{frac}" return sign * np.array([h, m, s], float) def search(name, raise_=False): """Regex match for coordinates in name.""" # extract the coordinate data from name match = JPARSER.search(name) if match is None and raise_: raise ValueError("No coordinate match found!") return match def to_ra_dec_angles(name): """get RA in hourangle and DEC in degrees by parsing name.""" groups = search(name, True).groups() prefix, hms, dms = np.split(groups, [1, 6]) ra = (_sexagesimal(hms) / (1, 60, 60 * 60) * u.hourangle).sum() dec = (_sexagesimal(dms) * (u.deg, u.arcmin, u.arcsec)).sum() return ra, dec def to_skycoord(name, frame="icrs"): """Convert to `name` to `SkyCoords` object.""" return SkyCoord(*to_ra_dec_angles(name), frame=frame) def shorten(name): """Produce a shortened version of the full object name. The shortened name is built from the prefix (usually the survey name) and RA (hour, minute), DEC (deg, arcmin) parts. e.g.: '2MASS J06495091-0737408' --> '2MASS J0649-0737' Parameters ---------- name : str Full object name with J-coords embedded. Returns ------- shortName: str """ match = search(name) return "".join(match.group(1, 3, 4, 7, 8, 9))