Example #1
0
def subtends(a1,b1,a2,b2,units="radians"):
    """ Calculate the angle subtended by 2 positions on the surface of a sphere.
        
        Parameters
        ----------
        a1 : float, `Angle`
        b1 : float, `Angle`
        a2 : float, `Angle`
        b2 : float, `Angle`
        units : str
            Specify the units for input / output. 
    """
    
    if units.lower() == "degrees":
        a1 = math.radians(a1)
        b1 = math.radians(b1)
        a2 = math.radians(a2)
        b2 = math.radians(b2)
    elif units.lower() == "radians":
        pass
    elif units.lower() == "hours":
        a1 = math.radians(convert.parseHours(a1)*15.)
        b1 = math.radians(convert.parseHours(b1)*15.)
        a2 = math.radians(convert.parseHours(a2)*15.)
        b2 = math.radians(convert.parseHours(b2)*15.)
    else:
        raise IllegalUnitsError("units must be 'radians', 'degrees', or 'hours' -- you entered: {0}".format(units))
    
    x1 = math.cos(a1)*math.cos(b1)
    y1 = math.sin(a1)*math.cos(b1)
    z1 = math.sin(b1)
    
    x2 = math.cos(a2)*math.cos(b2)
    y2 = math.sin(a2)*math.cos(b2)
    z2 = math.sin(b2)
    
    # [APW] Should this return an Angle object, or a float with units specified above? I think for
    #           a standalone function, it should be the latter...
    #theta = Angle.fromDegrees(math.degrees(math.acos(x1*x2+y1*y2+z1*z2)))
    
    if units.lower() == "degrees":
        return math.degrees(math.acos(x1*x2+y1*y2+z1*z2))
    elif units.lower() == "radians":
        return math.acos(x1*x2+y1*y2+z1*z2)
    elif units.lower() == "hours":
        return math.degrees(math.acos(x1*x2+y1*y2+z1*z2))/15.
    else:
        raise IllegalUnitsError("units must be 'radians', 'degrees', or 'hours' -- you entered: {0}".format(units))
Example #2
0
 def __init__(self, angle, units):
     # Make the `units` string lower case, and validate the `units`
     lowUnits = units.lower()
             
     try:
         if lowUnits == "degrees":
             self.radians = math.radians(convert.parseDegrees(angle))
             
         elif lowUnits == "radians":
             self.radians = float(angle)
             
         elif lowUnits == "hours":
             # can accept string or float in any valid format
             self.radians = convert.hoursToRadians(convert.parseHours(angle))
         
         else:
             raise IllegalUnitsError(units)
     except ValueError:
         raise ValueError("{1}: the angle value given couldn't be parsed (was of type {0})".format(type(angle).__name__, type(self).__name__))
Example #3
0
 def normalize(self, bounds, units, inplace=False):
     """ Normalize the angle to be within the bounds specified. If inplace==True, 
         this replace the internal values, otherwise it returns a new Angle object.
         
         Parameters
         ----------
         bounds : tuple
             A tuple with 2 values (low, hi) where this is the range you would like
             to normalize the angle to. For example, if you have an angle value of 
             752.1834 but you want it to be within the range -180 -> +180, you can
             specifiy `Angle.normalize((-180, 180), units="degrees")`.
     """
     
     # Validate the units
     lowUnits = units.lower()
     convert.parseDegrees(bounds[1])
     if lowUnits == "degrees":
         radianBounds = (math.radians(convert.parseDegrees(bounds[0])), math.radians(convert.parseDegrees(bounds[1])))
     elif lowUnits == "radians":
         radianBounds = (float(bounds[0]), float(bounds[1]))
     elif lowUnits == "hours":
         radianBounds = (convert.hoursToRadians(convert.parseHours(bounds[0])), convert.hoursToRadians(convert.parseHours(bounds[1])))
     
     if inplace:
         obj = self
     else:
         obj = copy.copy(self)
     
     if obj.radians < radianBounds[0]:
         obj.radians = obj.radians % radianBounds[1]
         
     elif obj.radians >= radianBounds[1]:
         if radianBounds[0] == 0:
             obj.radians = obj.radians % radianBounds[1]
         else:
             obj.radians = obj.radians % radianBounds[0]
     
     return obj
Example #4
0
        """ Create an astrodatetime object from a Python datetime object"""
        return astrodatetime(datetimeObj.year, datetimeObj.month, datetimeObj.day, datetimeObj.hour, datetimeObj.minute, datetimeObj.second, datetimeObj.microsecond, tzinfo=datetimeObj.tzinfo)

# Have to put this here to deal with circular imports
import convert

if __name__ == "__main__":
    # Functional and unit tests
    import unittest, sys, math
    
    jd = 2455893.68753
    mjd = convert.jdToMJD(jd)
    y = 2011
    m = 11
    d = 28
    hr,min,seconds = convert.hoursToHMS(convert.parseHours("04:30:02.6"))
    sf, sec = math.modf(seconds)

    class TestAstrodatetime(unittest.TestCase):
        def test_jd(self):
            dt = astrodatetime.fromJD(jd)
            self.assertEqual(y, dt.year)
            self.assertEqual(m, dt.month)
            self.assertEqual(d, dt.day)
            self.assertEqual(hr, dt.hour)
            self.assertEqual(min, dt.minute)
            self.assertEqual(sec, dt.second)
            self.assertAlmostEqual(sf, dt.microsecond/1.E6, 1)
        
        def test_mjd(self):
            dt = astrodatetime.fromMJD(mjd)