Source code for pyhetdex.coordinates.transformations

"""Coordinate transformations

Created on Oct 4, 2011

.. moduleauthor: Maximilian Fabricius <>

Notes
-----
    These routines are taken from `astlib <http://astlib.sourceforge.net/>`_

.. todo::
    :func:`~decimal2dms`: the two external if branches are almost exact
    repetitions. Solution: save the sign of the input ``decDeg`` variable;
    convert the input as it were positive, the add the sign before returning.
    Also most of the internal if branches are either superfluous or repetitions
    that can be factored out.

    Also :func:`~decimal2hms` show a fair amount of repetitions, in big part
    similar to the above function.

    Once the refactoring is finished, the tests should be updated to cover all
    the branches.

    :func:`~hms2decimal` tests fail: all the input values in the
    ``setup_class`` method are obtained with
    `ned calculator <https://ned.ipac.caltech.edu/forms/calculator.html>`_.
    The values obtained with the function disagrees at the 7th digit level with
    the value from ``ned`` (should we consider it a failure?). Using only the
    hour, the values is wrong.

    Should we use `astropy.coordinates
    <http://astropy.readthedocs.org/en/v1.0/coordinates/index.html>`_ instead
    of this implementation?


.. testsetup:: *

    from pyhetdex.coordinates.transformations import *
"""


# -----------------------------------------------------------------------------
[docs]def hms2decimal(ra_string, delimiter=":"): """Converts a delimited string of ``Hours:Minutes:Seconds`` format into decimal degrees. Parameters ---------- ra_string : string coordinate string in ``H :M:S`` format delimiter : string delimiter character in ``RAString`` Returns ------- ra_deg : float coordinate in decimal degrees Examples -------- .. doctest:: >>> hms2decimal("02:41:43.033") 40.42930416666667 """ # is it in HH:MM:SS format? if delimiter == "": ra_split = str(ra_string).split() else: ra_split = str(ra_string).split(delimiter) if len(ra_split) > 1: ra_decimal = float(ra_split[0]) if len(ra_split) > 1: ra_decimal = ra_decimal + (float(ra_split[1]) / 60.0) if len(ra_split) > 2: ra_decimal = ra_decimal + (float(ra_split[2]) / 3600.0) ra_deg = (ra_decimal / 24.0) * 360.0 else: ra_deg = float(ra_string) return ra_deg # -----------------------------------------------------------------------------
[docs]def dms2decimal(dec_string, delimiter=":"): """Converts a delimited string of ``Degrees:Minutes:Seconds`` format into decimal degrees. Parameters ---------- dec_string : string coordinate string in ``D :M:S`` format delimiter : string delimiter character in ``dec_string`` Returns ------- dec_deg : float coordinate in decimal degrees Examples -------- .. doctest:: >>> dms2decimal("+40:25:45.50") 40.42930555555555 """ # is it in DD:MM:SS format? if delimiter == "": dec_split = str(dec_string).split() else: dec_split = str(dec_string).split(delimiter) if len(dec_split) > 1: dec_deg = float(dec_split[0]) if dec_split[0].find("-") != -1: if len(dec_split) > 1: dec_deg = dec_deg-(float(dec_split[1]) / 60.0) if len(dec_split) > 2: dec_deg = dec_deg-(float(dec_split[2]) / 3600.0) else: if len(dec_split) > 1: dec_deg = dec_deg+(float(dec_split[1]) / 60.0) if len(dec_split) > 2: dec_deg = dec_deg+(float(dec_split[2]) / 3600.0) else: dec_deg = float(dec_string) return dec_deg # -----------------------------------------------------------------------------
[docs]def decimal2hms(RADeg, delimiter=":"): """Converts decimal degrees to string in ``Hours:Minutes:Seconds`` format with user specified delimiter. Parameters ---------- RADeg : float coordinate in decimal degrees delimiter : string delimiter character in returned string Returns ------- string coordinate string in ``Hour:Minutes:Seconds`` format Examples -------- .. doctest:: >>> decimal2hms(40.42930556) '02:41:43.033' """ hours = (RADeg / 360.0) * 24 if hours < 10 and hours >= 1: sHours = "0" + str(hours)[0] elif hours >= 10: sHours = str(hours)[:2] elif hours < 1: sHours = "00" if str(hours).find(".") == -1: mins = float(hours) * 60.0 else: mins = float(str(hours)[str(hours).index("."):]) * 60.0 if mins < 10 and mins >= 1: sMins = "0" + str(mins)[:1] elif mins >= 10: sMins = str(mins)[:2] elif mins < 1: sMins = "00" secs = (hours - (float(sHours) + float(sMins) / 60.0)) * 3600.0 if secs < 10 and secs > 0.001: sSecs = "0" + str(secs)[:str(secs).find(".") + 4] elif secs < 0.0001: sSecs = "00.001" else: sSecs = str(secs)[:str(secs).find(".") + 4] if len(sSecs) < 5: sSecs = sSecs + "00" # So all to 3dp if float(sSecs) == 60.000: sSecs = "00.00" sMins = str(int(sMins) + 1) if int(sMins) == 60: sMins = "00" return sHours + delimiter + sMins + delimiter + sSecs # -----------------------------------------------------------------------------
[docs]def decimal2dms(decDeg, delimiter=":"): """Converts decimal degrees to string in ``Degrees:Minutes:Seconds`` format with user specified delimiter. Parameters ---------- decDeg : float coordinate in decimal degrees delimiter : string delimiter character in returned string Returns ------- string coordinate string in ``D:M:S`` format Examples -------- .. doctest:: >>> decimal2dms(40.42930556) '+40:25:45.50' """ # Positive if decDeg > 0: if decDeg < 10 and decDeg >= 1: sDeg = "0" + str(decDeg)[0] elif decDeg >= 10: sDeg = str(decDeg)[:2] elif decDeg < 1: sDeg = "00" if str(decDeg).find(".") == -1: mins = float(decDeg) * 60.0 else: mins = float(str(decDeg)[str(decDeg).index("."):]) * 60 if mins < 10 and mins >= 1: sMins = "0" + str(mins)[:1] elif mins >= 10: sMins = str(mins)[:2] elif mins < 1: sMins = "00" secs = (decDeg-(float(sDeg) + float(sMins) / 60.0)) * 3600.0 if secs < 10 and secs > 0: sSecs = "0" + str(secs)[:str(secs).find(".") + 3] elif secs < 0.001: sSecs = "00.00" else: sSecs = str(secs)[:str(secs).find(".") + 3] if len(sSecs) < 5: sSecs = sSecs + "0" # So all to 2dp if float(sSecs) == 60.00: sSecs = "00.00" sMins = str(int(sMins) + 1) if int(sMins) == 60: sMins = "00" sDeg = str(int(sDeg) + 1) return "+" + sDeg + delimiter + sMins + delimiter + sSecs else: if decDeg > -10 and decDeg <= -1: sDeg = "-0" + str(decDeg)[1] elif decDeg <= -10: sDeg = str(decDeg)[:3] elif decDeg > -1: sDeg = "-00" if str(decDeg).find(".") == -1: mins = float(decDeg) * -60.0 else: mins = float(str(decDeg)[str(decDeg).index("."):]) * 60 if mins < 10 and mins >= 1: sMins = "0" + str(mins)[:1] elif mins >= 10: sMins = str(mins)[:2] elif mins < 1: sMins = "00" secs = (decDeg-(float(sDeg)-float(sMins) / 60.0)) * 3600.0 if secs > -10 and secs < 0: # so don't get minus sign sSecs = "0" + str(secs)[1:str(secs).find(".") + 3] elif secs > -0.001: sSecs = "00.00" else: sSecs = str(secs)[1:str(secs).find(".") + 3] if len(sSecs) < 5: sSecs = sSecs + "0" # So all to 2dp if float(sSecs) == 60.00: sSecs = "00.00" sMins = str(int(sMins) + 1) if int(sMins) == 60: sMins = "00" sDeg = str(int(sDeg)-1) return sDeg + delimiter + sMins + delimiter + sSecs