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))
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__))
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
""" 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)