Source code for astrocalc.coords.unit_conversion

#!/usr/local/bin/python
# encoding: utf-8
"""
*Convert coordinates from decimal to sexagesimal units and vice-versa*

Author
: David Young
"""
from __future__ import division
from builtins import str
from builtins import object
from past.utils import old_div
import sys
import os
import math
os.environ['TERM'] = 'vt100'


[docs] class unit_conversion(object): """ *The worker class for the unit_conversion module* **Key Arguments** - ``log`` -- logger - ``settings`` -- the settings dictionary (prob not required) **Usage** .. todo:: - add usage info - create a sublime snippet for usage - add ra_sexegesimal_to_decimal ```python usage code ``` .. todo:: - @review: when complete, clean unit_conversion class - @review: when complete add logging - @review: when complete, decide whether to abstract class to another module """ # Initialisation # 1. @flagged: what are the unique attrributes for each object? Add them # to __init__ def __init__( self, log, settings=False ): self.log = log log.debug("instansiating a new 'unit_conversion' object") self.settings = settings # xt-self-arg-tmpx # 2. @flagged: what are the default attrributes each object could have? Add them to variable attribute set here # Variable Data Atrributes # 3. @flagged: what variable attrributes need overriden in any baseclass(es) used # Override Variable Data Atrributes # Initial Actions return None # 4. @flagged: what actions does each object have to be able to perform? Add them here # Method Attributes
[docs] def get(self): """ *get the unit_conversion object* **Return** - ``unit_conversion`` .. todo:: - @review: when complete, clean get method - @review: when complete add logging """ self.log.debug('starting the ``get`` method') unit_conversion = None self.log.debug('completed the ``get`` method') return unit_conversion
[docs] def dec_sexegesimal_to_decimal( self, dec): """ *Convert a declination from sexegesimal format to decimal degrees.* Precision should be respected. If a float is passed to this method, the same float will be returned (useful if unclear which format coordinates are in). The code will attempt to read the sexegesimal value in whatever form it is passed. Any of the following should be handled correctly: - ``+1:58:05.45341`` - ``01:5:05`` - ``+1 58 05.45341`` - ``-23h53m05s`` **Key Arguments** - ``dec`` - DEC in sexegesimal format. **Return** - ``decDeg`` -- declination converted to decimal degrees **Usage** .. todo:: - replace dryxPython declination_sexegesimal_to_decimal with this version in all my code - replace coords_sex_to_dec in all code ```python from astrocalc.coords import unit_conversion converter = unit_conversion( log=log ) dec = converter.dec_sexegesimal_to_decimal( dec="-23:45:21.23232" ) print(dec) # OUTPUT: -23.7558978667 ``` """ self.log.debug( 'completed the ````dec_sexegesimal_to_decimal`` method') import re # TEST TO SEE IF DECIMAL DEGREES PASSED try: dec = float(dec) if dec > -90. and dec < 90.: self.log.debug( 'declination seems to already be in decimal degrees, returning original value' % locals()) return float(dec) except: pass # REMOVE SURROUNDING WHITESPACE dec = str(dec).strip() # LOOK FOR A MINUS SIGN. NOTE THAT -00 IS THE SAME AS 00. regex = re.compile( r'^([\+\-]?(\d|[0-8]\d))\D+([0-5]\d)\D+([0-6]?\d(\.\d+)?)$') decMatch = regex.match(dec) if decMatch: degrees = decMatch.group(1) minutes = decMatch.group(3) seconds = decMatch.group(4) if degrees[0] == '-': sgn = -1 else: sgn = 1 degrees = abs(float(degrees)) minutes = float(minutes) seconds = float(seconds) # PRECISION TEST # 1s = .000277778 DEGREE # THEREFORE REPORT SECONDS TO A PRECISION = INPUT PRECISION + 4 decimalLen = len(repr(seconds).split(".")[-1]) precision = decimalLen + 4 decDeg = (degrees + (minutes / 60.0) + (seconds / 3600.0)) * sgn decDeg = "%0.*f" % (precision, decDeg) else: raise IOError( "could not convert dec to decimal degrees, could not parse sexegesimal input. Original value was `%(dec)s`" % locals()) decDeg = float(decDeg) self.log.debug('decDeg: %(decDeg)s' % locals()) self.log.debug( 'completed the ``dec_sexegesimal_to_decimal`` method') return float(decDeg)
[docs] def ra_sexegesimal_to_decimal( self, ra ): """ *Convert a right-ascension from sexegesimal format to decimal degrees.* Precision should be respected. If a float is passed to this method, the same float will be returned (useful if unclear which format coordinates are in). The code will attempt to read the sexegesimal value in whatever form it is passed. Any of the following should be handled correctly - ``23:45:21.23232`` - ``23h45m21.23232s`` - ``23 45 21.23232`` - ``2 04 21.23232`` - ``04:45 21`` **Key Arguments** - ``ra`` -- ra in sexegesimal units **Return** - ``decimalDegrees`` **Usage** ```python - replace dryxPython ra_sexegesimal_to_decimal with this version in all my code from astrocalc.coords import unit_conversion converter = unit_conversion( log=log ) ra = converter.ra_sexegesimal_to_decimal( ra="04:45 21" ) print(ra) # OUTPUT: 71.3375 ``` """ import re # TEST TO SEE IF DECIMAL DEGREES PASSED try: ra = float(ra) if ra >= 0. and ra <= 360.: self.log.debug( 'RA seems to already be in decimal degrees, returning original value' % locals()) return float(ra) except: pass # REMOVE SURROUNDING WHITESPACE ra = str(ra).strip() regex = re.compile( r'^(\+?(\d|[0-1]\d|2[0-3]))\D+([0-5]\d)\D+([0-6]?\d(\.\d*?)?)(s)?\s*?$') raMatch = regex.match(ra) if raMatch: degrees = raMatch.group(1) minutes = raMatch.group(3) seconds = raMatch.group(4) degrees = abs(float(degrees)) * 15.0 minutes = float(minutes) * 15.0 seconds = float(seconds) * 15.0 # PRECISION TEST # 1s ARCSEC = .000018519 DEGREE # THEREFORE REPORT SECONDS TO A PRECISION = INPUT PRECISION + 5 decimalLen = len(repr(seconds).split(".")[-1]) precision = decimalLen + 5 decimalDegrees = (degrees + (minutes / 60.0) + (seconds / 3600.0)) decimalDegrees = "%0.*f" % (precision, decimalDegrees) else: raise IOError( "could not convert ra to decimal degrees, could not parse sexegesimal input. Original value was `%(ra)s`" % locals()) raDeg = decimalDegrees self.log.debug('raDeg: %(decimalDegrees)s' % locals()) self.log.debug( 'completed the ``ra_sexegesimal_to_decimal`` method') return float(raDeg)
[docs] def ra_decimal_to_sexegesimal( self, ra, delimiter=":"): """ *Convert a right-ascension between decimal degrees and sexegesimal.* Precision should be respected. **Key Arguments** - ``ra`` -- RA in decimal degrees. Will try and convert to float before performing calculation. - ``delimiter`` -- how to delimit the RA units. Default *:* **Return** - ``sexegesimal`` -- ra in sexegesimal units **Usage** .. todo:: - replace ra_to_sex from dryxPython in all code ```python from astrocalc.coords import unit_conversion converter = unit_conversion( log=log ) ra = converter.ra_decimal_to_sexegesimal( ra="-23.454676456", delimiter=":" ) print(ra) # OUT: 22:26:10.87 ``` """ self.log.debug('starting the ``ra_decimal_to_sexegesimal`` method') # CONVERT RA TO FLOAT try: self.log.debug("attempting to convert RA to float") ra = float(ra) except Exception as e: self.log.error( "could not convert RA to float - failed with this error: %s " % (str(e),)) return -1 # COMPLAIN IF RA NOT BETWEEN -360 - 360 if ra > 0. and ra < 360.: pass elif ra < 0 and ra > -360.: ra = 360. + ra else: self.log.error( "RA must be between 0 - 360 degrees") return -1 # PRECISION TEST # 1s ARCSEC = .000018519 DEGREE # THEREFORE REPORT SECONDS TO A PRECISION = INPUT PRECISION - 5 decimalLen = len(repr(ra).split(".")[-1]) precision = decimalLen - 5 # CALCULATION FROM DECIMAL DEGREES import math ra_hh = int(old_div(ra, 15)) ra_mm = int((old_div(ra, 15) - ra_hh) * 60) ra_ss = int(((old_div(ra, 15) - ra_hh) * 60 - ra_mm) * 60) ra_ff = ((old_div(ra, 15) - ra_hh) * 60 - ra_mm) * 60 - ra_ss # SET PRECISION ra_ff = repr(ra_ff)[2:] ra_ff = ra_ff[:precision] if len(ra_ff): ra_ff = "." + ra_ff if precision < 0: ra_ff = "" sexegesimal = '%02d' % ra_hh + delimiter + '%02d' % ra_mm + \ delimiter + '%02d' % ra_ss + ra_ff self.log.debug('completed the ``ra_decimal_to_sexegesimal`` method') return sexegesimal
[docs] def dec_decimal_to_sexegesimal( self, dec, delimiter=":"): """ *Convert a declination between decimal degrees and sexegesimal.* Precision should be respected. **Key Arguments** - ``dec`` -- DEC in decimal degrees. Will try and convert to float before performing calculation. - ``delimiter`` -- how to delimit the RA units. Default *:* **Return** - ``sexegesimal`` -- ra in sexegesimal units **Usage** .. todo:: - replace dec_to_sex in dryxPython in all code ```python from astrocalc.coords import unit_conversion converter = unit_conversion( log=log ) dec = converter.dec_decimal_to_sexegesimal( dec="-3.454676456", delimiter=":" ) print(dec) # OUT: -03:27:16.8 ``` """ self.log.debug('starting the ``dec_decimal_to_sexegesimal`` method') import math # CONVERT DEC TO FLOAT try: self.log.debug("attempting to convert RA to float") dec = float(dec) except Exception as e: self.log.error( "could not convert RA to float - failed with this error: %s " % (str(e),)) return -1 # COMPLAIN IF DEC NOT BETWEEN -90 - 90 if dec > -90. and dec < 90.: pass else: self.log.error( "DEC must be between -90 - 90 degrees") return -1 if (dec >= 0): hemisphere = '+' else: hemisphere = '-' dec *= -1 # PRECISION TEST # 1s = .000277778 DEGREE # THEREFORE REPORT SECONDS TO A PRECISION = INPUT PRECISION - 4 decimalLen = len(repr(dec).split(".")[-1]) precision = decimalLen - 4 dec_deg = int(dec) dec_mm = int((dec - dec_deg) * 60) dec_ss = int(((dec - dec_deg) * 60 - dec_mm) * 60) dec_f = (((dec - dec_deg) * 60 - dec_mm) * 60) - dec_ss # SET PRECISION dec_f = repr(dec_f)[2:] dec_f = dec_f[:precision] if len(dec_f): dec_f = "." + dec_f if precision < 0: dec_f = "" sexegesimal = hemisphere + '%02d' % dec_deg + delimiter + \ '%02d' % dec_mm + delimiter + '%02d' % dec_ss + dec_f self.log.debug('completed the ``dec_decimal_to_sexegesimal`` method') return sexegesimal
# use the tab-trigger below for new method
[docs] def ra_dec_to_cartesian( self, ra, dec): """*Convert an RA, DEC coordinate set to x, y, z cartesian coordinates* **Key Arguments** - ``ra`` -- right ascension in sexegesimal or decimal degress. - ``dec`` -- declination in sexegesimal or decimal degress. **Return** - ``cartesians`` -- tuple of (x, y, z) coordinates .. todo:: - replace calculate_cartesians in all code **Usage** ```python from astrocalc.coords import unit_conversion converter = unit_conversion( log=log ) x, y, z = converter.ra_dec_to_cartesian( ra="23 45 21.23232", dec="+01:58:5.45341" ) print(x, y, z) # OUTPUT: 0.9973699780687104, -0.06382462462791459, 0.034344492110465606 ``` """ self.log.debug('starting the ``ra_dec_to_cartesian`` method') ra = self.ra_sexegesimal_to_decimal( ra=ra ) dec = self.dec_sexegesimal_to_decimal( dec=dec ) ra = math.radians(ra) dec = math.radians(dec) cos_dec = math.cos(dec) cx = math.cos(ra) * cos_dec cy = math.sin(ra) * cos_dec cz = math.sin(dec) cartesians = (cx, cy, cz) self.log.debug('completed the ``ra_dec_to_cartesian`` method') return cartesians
# use the tab-trigger below for new method # xt-class-method