#!/usr/local/bin/python# encoding: utf-8"""*Convert coordinates from decimal to sexagesimal units and vice-versa*Author: David Young"""from__future__importdivisionfrombuiltinsimportstrfrombuiltinsimportobjectfrompast.utilsimportold_divimportsysimportosimportmathos.environ['TERM']='vt100'
[docs]classunit_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=loglog.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 ActionsreturnNone# 4. @flagged: what actions does each object have to be able to perform? Add them here# Method Attributes
[docs]defget(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=Noneself.log.debug('completed the ``get`` method')returnunit_conversion
[docs]defdec_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')importre# TEST TO SEE IF DECIMAL DEGREES PASSEDtry:dec=float(dec)ifdec>-90.anddec<90.:self.log.debug('declination seems to already be in decimal degrees, returning original value'%locals())returnfloat(dec)except:pass# REMOVE SURROUNDING WHITESPACEdec=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)ifdecMatch:degrees=decMatch.group(1)minutes=decMatch.group(3)seconds=decMatch.group(4)ifdegrees[0]=='-':sgn=-1else:sgn=1degrees=abs(float(degrees))minutes=float(minutes)seconds=float(seconds)# PRECISION TEST# 1s = .000277778 DEGREE# THEREFORE REPORT SECONDS TO A PRECISION = INPUT PRECISION + 4decimalLen=len(repr(seconds).split(".")[-1])precision=decimalLen+4decDeg=(degrees+(minutes/60.0)+(seconds/3600.0))*sgndecDeg="%0.*f"%(precision,decDeg)else:raiseIOError("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')returnfloat(decDeg)
[docs]defra_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 ``` """importre# TEST TO SEE IF DECIMAL DEGREES PASSEDtry:ra=float(ra)ifra>=0.andra<=360.:self.log.debug('RA seems to already be in decimal degrees, returning original value'%locals())returnfloat(ra)except:pass# REMOVE SURROUNDING WHITESPACEra=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)ifraMatch:degrees=raMatch.group(1)minutes=raMatch.group(3)seconds=raMatch.group(4)degrees=abs(float(degrees))*15.0minutes=float(minutes)*15.0seconds=float(seconds)*15.0# PRECISION TEST# 1s ARCSEC = .000018519 DEGREE# THEREFORE REPORT SECONDS TO A PRECISION = INPUT PRECISION + 5decimalLen=len(repr(seconds).split(".")[-1])precision=decimalLen+5decimalDegrees=(degrees+(minutes/60.0)+(seconds/3600.0))decimalDegrees="%0.*f"%(precision,decimalDegrees)else:raiseIOError("could not convert ra to decimal degrees, could not parse sexegesimal input. Original value was `%(ra)s`"%locals())raDeg=decimalDegreesself.log.debug('raDeg: %(decimalDegrees)s'%locals())self.log.debug('completed the ``ra_sexegesimal_to_decimal`` method')returnfloat(raDeg)
[docs]defra_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 FLOATtry:self.log.debug("attempting to convert RA to float")ra=float(ra)exceptExceptionase:self.log.error("could not convert RA to float - failed with this error: %s "%(str(e),))return-1# COMPLAIN IF RA NOT BETWEEN -360 - 360ifra>0.andra<360.:passelifra<0andra>-360.:ra=360.+raelse: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 - 5decimalLen=len(repr(ra).split(".")[-1])precision=decimalLen-5# CALCULATION FROM DECIMAL DEGREESimportmathra_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 PRECISIONra_ff=repr(ra_ff)[2:]ra_ff=ra_ff[:precision]iflen(ra_ff):ra_ff="."+ra_ffifprecision<0:ra_ff=""sexegesimal='%02d'%ra_hh+delimiter+'%02d'%ra_mm+ \
delimiter+'%02d'%ra_ss+ra_ffself.log.debug('completed the ``ra_decimal_to_sexegesimal`` method')returnsexegesimal
[docs]defdec_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')importmath# CONVERT DEC TO FLOATtry:self.log.debug("attempting to convert RA to float")dec=float(dec)exceptExceptionase:self.log.error("could not convert RA to float - failed with this error: %s "%(str(e),))return-1# COMPLAIN IF DEC NOT BETWEEN -90 - 90ifdec>-90.anddec<90.:passelse:self.log.error("DEC must be between -90 - 90 degrees")return-1if(dec>=0):hemisphere='+'else:hemisphere='-'dec*=-1# PRECISION TEST# 1s = .000277778 DEGREE# THEREFORE REPORT SECONDS TO A PRECISION = INPUT PRECISION - 4decimalLen=len(repr(dec).split(".")[-1])precision=decimalLen-4dec_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 PRECISIONdec_f=repr(dec_f)[2:]dec_f=dec_f[:precision]iflen(dec_f):dec_f="."+dec_fifprecision<0:dec_f=""sexegesimal=hemisphere+'%02d'%dec_deg+delimiter+ \
'%02d'%dec_mm+delimiter+'%02d'%dec_ss+dec_fself.log.debug('completed the ``dec_decimal_to_sexegesimal`` method')returnsexegesimal
# use the tab-trigger below for new method
[docs]defra_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_deccy=math.sin(ra)*cos_deccz=math.sin(dec)cartesians=(cx,cy,cz)self.log.debug('completed the ``ra_dec_to_cartesian`` method')returncartesians
# use the tab-trigger below for new method# xt-class-method