def nutation(cls, tee): """Return the longitudinal nutation at moment, tee.""" c = cls.julian_centuries(tee) cap_A = poly(c, [mpf(124.90), mpf(-1934.134), mpf(0.002063)]) cap_B = poly(c, [mpf(201.11), mpf(72001.5377), mpf(0.00057)]) return (mpf(-0.004778) * sin_degrees(cap_A) + mpf(-0.0003667) * sin_degrees(cap_B))
def declination(cls, tee, beta, lam): """Return declination at moment UT tee of object at longitude 'lam' and latitude 'beta'.""" varepsilon = cls.obliquity(tee) return arcsin_degrees( (sin_degrees(beta) * cos_degrees(varepsilon)) + (cos_degrees(beta) * sin_degrees(varepsilon) * sin_degrees(lam)))
def lunar_longitude(cls, tee): """Return longitude of moon (in degrees) at moment tee. Adapted from "Astronomical Algorithms" by Jean Meeus, Willmann_Bell, Inc., 2nd ed., 1998.""" c = cls.julian_centuries(tee) cap_L_prime = cls.mean_lunar_longitude(c) cap_D = cls.lunar_elongation(c) cap_M = Solar.solar_anomaly(c) cap_M_prime = cls.lunar_anomaly(c) cap_F = cls.moon_node(c) # see eq. 47.6 in Meeus cap_E = poly(c, [1, mpf(-0.002516), mpf(-0.0000074)]) args_lunar_elongation = \ [0, 2, 2, 0, 0, 0, 2, 2, 2, 2, 0, 1, 0, 2, 0, 0, 4, 0, 4, 2, 2, 1, 1, 2, 2, 4, 2, 0, 2, 2, 1, 2, 0, 0, 2, 2, 2, 4, 0, 3, 2, 4, 0, 2, 2, 2, 4, 0, 4, 1, 2, 0, 1, 3, 4, 2, 0, 1, 2] args_solar_anomaly = \ [0, 0, 0, 0, 1, 0, 0, -1, 0, -1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, -1, 0, 0, 0, 1, 0, -1, 0, -2, 1, 2, -2, 0, 0, -1, 0, 0, 1, -1, 2, 2, 1, -1, 0, 0, -1, 0, 1, 0, 1, 0, 0, -1, 2, 1, 0] args_lunar_anomaly = \ [1, -1, 0, 2, 0, 0, -2, -1, 1, 0, -1, 0, 1, 0, 1, 1, -1, 3, -2, -1, 0, -1, 0, 1, 2, 0, -3, -2, -1, -2, 1, 0, 2, 0, -1, 1, 0, -1, 2, -1, 1, -2, -1, -1, -2, 0, 1, 4, 0, -2, 0, 2, 1, -2, -3, 2, 1, -1, 3] args_moon_node = \ [0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, -2, 2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, -2, 2, 0, 2, 0, 0, 0, 0, 0, 0, -2, 0, 0, 0, 0, -2, -2, 0, 0, 0, 0, 0, 0, 0] sine_coefficients = \ [6288774,1274027,658314,213618,-185116,-114332, 58793,57066,53322,45758,-40923,-34720,-30383, 15327,-12528,10980,10675,10034,8548,-7888, -6766,-5163,4987,4036,3994,3861,3665,-2689, -2602, 2390,-2348,2236,-2120,-2069,2048,-1773, -1595,1215,-1110,-892,-810,759,-713,-700,691, 596,549,537,520,-487,-399,-381,351,-340,330, 327,-323,299,294] correction = ((1.0/1000000.0) * sigma([sine_coefficients, args_lunar_elongation, args_solar_anomaly, args_lunar_anomaly, args_moon_node], lambda v, w, x, y, z: v * pow(cap_E, abs(x)) * sin_degrees((w * cap_D) + (x * cap_M) + (y * cap_M_prime) + (z * cap_F)))) A1 = mpf(119.75) + (c * mpf(131.849)) venus = ((3958/1000000) * sin_degrees(A1)) A2 = mpf(53.09) + c * mpf(479264.29) jupiter = ((318/1000000) * sin_degrees(A2)) flat_earth = ((1962/1000000) * sin_degrees(cap_L_prime - cap_F)) return mod(cap_L_prime + correction + venus + jupiter + flat_earth + cls.nutation(tee), 360)
def direction(self, focus): """Return the angle (clockwise from North) to face focus when standing in location, location. Subject to errors near focus and its antipode.""" y = sin_degrees(focus.longitude - self.longitude) x = ((cos_degrees(self.latitude) * tan_degrees(focus.latitude)) - (sin_degrees(self.latitude) * cos_degrees(self.longitude - focus.longitude))) if x == y == 0 or focus.latitude == 90: return 0 elif focus.latitude == -90: return 180 else: return arctan_degrees(y, x)
def lunar_altitude(self, tee): """Return the geocentric altitude of moon at moment, tee, at location, location, as a small positive/negative angle in degrees, ignoring parallax and refraction. Adapted from 'Astronomical Algorithms' by Jean Meeus, Willmann_Bell, Inc., 1998.""" lamb = Lunar.lunar_longitude(tee) beta = Lunar.lunar_latitude(tee) alpha = Astro.right_ascension(tee, beta, lamb) delta = Astro.declination(tee, beta, lamb) theta0 = Astro.sidereal_from_moment(tee) cap_H = mod(theta0 + self.longitude - alpha, 360) altitude = arcsin_degrees( (sin_degrees(self.latitude) * sin_degrees(delta)) + (cos_degrees(self.latitude) * cos_degrees(delta) * cos_degrees(cap_H))) return mod(altitude + 180, 360) - 180
def lunar_true_node(cls, tee): """Return Angular distance of the true node (the node of the instantaneus lunar orbit) from the equinoctal point at moment, tee. Adapted from eq. 47.7 and pag. 344 in "Astronomical Algorithms" by Jean Meeus, Willmann_Bell, Inc., 2nd ed., 1998 with corrections June 2005.""" c = cls.julian_centuries(tee) cap_D = cls.lunar_elongation(c) cap_M = cls.solar_anomaly(c) cap_M_prime = cls.lunar_anomaly(c) cap_F = cls.moon_node(c) periodic_terms = (-1.4979 * sin_degrees(2 * (cap_D - cap_F)) + -0.1500 * sin_degrees(cap_M) + -0.1226 * sin_degrees(2 * cap_D) + 0.1176 * sin_degrees(2 * cap_F) + -0.0801 * sin_degrees(2 * (cap_M_prime - cap_F))) return cls.alt_lunar_node(tee) + periodic_terms
def equation_of_time(cls, tee): """Return the equation of time (as fraction of day) for moment, tee. Adapted from "Astronomical Algorithms" by Jean Meeus, Willmann_Bell, Inc., 1991.""" c = cls.julian_centuries(tee) lamb = poly(c, [mpf(280.46645), mpf(36000.76983), mpf(0.0003032)]) anomaly = poly(c, [mpf(357.52910), mpf(35999.05030), mpf(-0.0001559), mpf(-0.00000048)]) eccentricity = poly(c, [mpf(0.016708617), mpf(-0.000042037), mpf(-0.0000001236)]) varepsilon = cls.obliquity(tee) y = pow(tan_degrees(varepsilon / 2), 2) equation = ((1/2 / pi) * (y * sin_degrees(2 * lamb) + -2 * eccentricity * sin_degrees(anomaly) + (4 * eccentricity * y * sin_degrees(anomaly) * cos_degrees(2 * lamb)) + -0.5 * y * y * sin_degrees(4 * lamb) + -1.25 * eccentricity * eccentricity * sin_degrees(2 * anomaly))) return signum(equation) * min(abs(equation), Clock.days_from_hours(mpf(12)))
def sine_offset(self, local_time, alpha): """Return sine of angle between position of sun at local time tee and when its depression is alpha at location, location. Out of range when it does not occur.""" phi = self.latitude tee_prime = self.universal_from_local(local_time) delta = Astro.declination(tee_prime, mpf(0), Solar.solar_longitude(tee_prime)) return ((tan_degrees(phi) * tan_degrees(delta)) + (sin_degrees(alpha) / (cos_degrees(delta) * cos_degrees(phi))))
def lunar_latitude(cls, tee): """Return the latitude of moon (in degrees) at moment, tee. Adapted from "Astronomical Algorithms" by Jean Meeus, Willmann_Bell, Inc., 1998.""" c = cls.julian_centuries(tee) cap_L_prime = cls.mean_lunar_longitude(c) cap_D = cls.lunar_elongation(c) cap_M = Solar.solar_anomaly(c) cap_M_prime = cls.lunar_anomaly(c) cap_F = cls.moon_node(c) cap_E = poly(c, [1, mpf(-0.002516), mpf(-0.0000074)]) args_lunar_elongation = \ [0, 0, 0, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 4, 4, 0, 4, 2, 2, 2, 2, 0, 2, 2, 2, 2, 4, 2, 2, 0, 2, 1, 1, 0, 2, 1, 2, 0, 4, 4, 1, 4, 1, 4, 2] args_solar_anomaly = \ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, -1, -1, -1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 1, 0, -1, -2, 0, 1, 1, 1, 1, 1, 0, -1, 1, 0, -1, 0, 0, 0, -1, -2] args_lunar_anomaly = \ [0, 1, 1, 0, -1, -1, 0, 2, 1, 2, 0, -2, 1, 0, -1, 0, -1, -1, -1, 0, 0, -1, 0, 1, 1, 0, 0, 3, 0, -1, 1, -2, 0, 2, 1, -2, 3, 2, -3, -1, 0, 0, 1, 0, 1, 1, 0, 0, -2, -1, 1, -2, 2, -2, -1, 1, 1, -2, 0, 0] args_moon_node = \ [1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 3, 1, 1, 1, -1, -1, -1, 1, -1, 1, -3, 1, -3, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, 3, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1] sine_coefficients = \ [5128122, 280602, 277693, 173237, 55413, 46271, 32573, 17198, 9266, 8822, 8216, 4324, 4200, -3359, 2463, 2211, 2065, -1870, 1828, -1794, -1749, -1565, -1491, -1475, -1410, -1344, -1335, 1107, 1021, 833, 777, 671, 607, 596, 491, -451, 439, 422, 421, -366, -351, 331, 315, 302, -283, -229, 223, 223, -220, -220, -185, 181, -177, 176, 166, -164, 132, -119, 115, 107] beta = ((1.0/1000000.0) * sigma([sine_coefficients, args_lunar_elongation, args_solar_anomaly, args_lunar_anomaly, args_moon_node], lambda v, w, x, y, z: (v * pow(cap_E, abs(x)) * sin_degrees((w * cap_D) + (x * cap_M) + (y * cap_M_prime) + (z * cap_F))))) venus = ((175/1000000) * (sin_degrees(mpf(119.75) + c * mpf(131.849) + cap_F) + sin_degrees(mpf(119.75) + c * mpf(131.849) - cap_F))) flat_earth = ((-2235/1000000) * sin_degrees(cap_L_prime) + (127/1000000) * sin_degrees(cap_L_prime - cap_M_prime) + (-115/1000000) * sin_degrees(cap_L_prime + cap_M_prime)) extra = ((382/1000000) * sin_degrees(mpf(313.45) + c * mpf(481266.484))) return beta + venus + flat_earth + extra
def precession(cls, tee): """Return the precession at moment tee using 0,0 as J2000 coordinates. Adapted from "Astronomical Algorithms" by Jean Meeus, Willmann-Bell, Inc., 1991.""" c = cls.julian_centuries(tee) eta = mod(poly(c, [0, secs(mpf(47.0029)), secs(mpf(-0.03302)), secs(mpf(0.000060))]), 360) cap_P = mod(poly(c, [mpf(174.876384), secs(mpf(-869.8089)), secs(mpf(0.03536))]), 360) p = mod(poly(c, [0, secs(mpf(5029.0966)), secs(mpf(1.11113)), secs(mpf(0.000006))]), 360) cap_A = cos_degrees(eta) * sin_degrees(cap_P) cap_B = cos_degrees(cap_P) arg = arctan_degrees(cap_A, cap_B) return mod(p + cap_P - arg, 360)
def solar_longitude(cls, tee): """Return the longitude of sun at moment 'tee'. Adapted from 'Planetary Programs and Tables from -4000 to +2800' by Pierre Bretagnon and Jean_Louis Simon, Willmann_Bell, Inc., 1986. See also pag 166 of 'Astronomical Algorithms' by Jean Meeus, 2nd Ed 1998, with corrections Jun 2005.""" c = cls.julian_centuries(tee) coefficients = [403406, 195207, 119433, 112392, 3891, 2819, 1721, 660, 350, 334, 314, 268, 242, 234, 158, 132, 129, 114, 99, 93, 86, 78,72, 68, 64, 46, 38, 37, 32, 29, 28, 27, 27, 25, 24, 21, 21, 20, 18, 17, 14, 13, 13, 13, 12, 10, 10, 10, 10] multipliers = [mpf(0.9287892), mpf(35999.1376958), mpf(35999.4089666), mpf(35998.7287385), mpf(71998.20261), mpf(71998.4403), mpf(36000.35726), mpf(71997.4812), mpf(32964.4678), mpf(-19.4410), mpf(445267.1117), mpf(45036.8840), mpf(3.1008), mpf(22518.4434), mpf(-19.9739), mpf(65928.9345), mpf(9038.0293), mpf(3034.7684), mpf(33718.148), mpf(3034.448), mpf(-2280.773), mpf(29929.992), mpf(31556.493), mpf(149.588), mpf(9037.750), mpf(107997.405), mpf(-4444.176), mpf(151.771), mpf(67555.316), mpf(31556.080), mpf(-4561.540), mpf(107996.706), mpf(1221.655), mpf(62894.167), mpf(31437.369), mpf(14578.298), mpf(-31931.757), mpf(34777.243), mpf(1221.999), mpf(62894.511), mpf(-4442.039), mpf(107997.909), mpf(119.066), mpf(16859.071), mpf(-4.578), mpf(26895.292), mpf(-39.127), mpf(12297.536), mpf(90073.778)] addends = [mpf(270.54861), mpf(340.19128), mpf(63.91854), mpf(331.26220), mpf(317.843), mpf(86.631), mpf(240.052), mpf(310.26), mpf(247.23), mpf(260.87), mpf(297.82), mpf(343.14), mpf(166.79), mpf(81.53), mpf(3.50), mpf(132.75), mpf(182.95), mpf(162.03), mpf(29.8), mpf(266.4), mpf(249.2), mpf(157.6), mpf(257.8),mpf(185.1), mpf(69.9), mpf(8.0), mpf(197.1), mpf(250.4), mpf(65.3), mpf(162.7), mpf(341.5), mpf(291.6), mpf(98.5), mpf(146.7), mpf(110.0), mpf(5.2), mpf(342.6), mpf(230.9), mpf(256.1), mpf(45.3), mpf(242.9), mpf(115.2), mpf(151.8), mpf(285.3), mpf(53.3), mpf(126.6), mpf(205.7), mpf(85.9), mpf(146.1)] lam = (mpf(282.7771834) + mpf(36000.76953744) * c + mpf(0.000005729577951308232) * sigma([coefficients, addends, multipliers], lambda x, y, z: x * sin_degrees(y + (z * c)))) return mod(lam + cls.aberration(tee) + cls.nutation(tee), 360)
def right_ascension(cls, tee, beta, lam): """Return right ascension at moment UT 'tee' of object at latitude 'lam' and longitude 'beta'.""" varepsilon = cls.obliquity(tee) return arctan_degrees((sin_degrees(lam) * cos_degrees(varepsilon)) - (tan_degrees(beta) * sin_degrees(varepsilon)), cos_degrees(lam))
def sine_table(cls, entry): """Return the value for entry in the Hindu sine table. Entry, entry, is an angle given as a multiplier of 225'.""" exact = 3438 * sin_degrees(entry * angle(0, 225, 0)) error = 0.215 * signum(exact) * signum(abs(exact) - 1716) return iround(exact + error) / 3438
def nth_new_moon(cls, n): """Return the moment of n-th new moon after (or before) the new moon of January 11, 1. Adapted from "Astronomical Algorithms" by Jean Meeus, Willmann_Bell, Inc., 2nd ed., 1998.""" n0 = 24724 k = n - n0 c = k / mpf(1236.85) approx = (cls.J2000 + poly(c, [mpf(5.09766), cls.MEAN_SYNODIC_MONTH * mpf(1236.85), mpf(0.0001437), mpf(-0.000000150), mpf(0.00000000073)])) cap_E = poly(c, [1, mpf(-0.002516), mpf(-0.0000074)]) solar_anomaly = poly(c, [mpf(2.5534), (mpf(1236.85) * mpf(29.10535669)), mpf(-0.0000014), mpf(-0.00000011)]) lunar_anomaly = poly(c, [mpf(201.5643), (mpf(385.81693528) * mpf(1236.85)), mpf(0.0107582), mpf(0.00001238), mpf(-0.000000058)]) moon_argument = poly(c, [mpf(160.7108), (mpf(390.67050284) * mpf(1236.85)), mpf(-0.0016118), mpf(-0.00000227), mpf(0.000000011)]) cap_omega = poly(c, [mpf(124.7746), (mpf(-1.56375588) * mpf(1236.85)), mpf(0.0020672), mpf(0.00000215)]) E_factor = [0, 1, 0, 0, 1, 1, 2, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] solar_coeff = [0, 1, 0, 0, -1, 1, 2, 0, 0, 1, 0, 1, 1, -1, 2, 0, 3, 1, 0, 1, -1, -1, 1, 0] lunar_coeff = [1, 0, 2, 0, 1, 1, 0, 1, 1, 2, 3, 0, 0, 2, 1, 2, 0, 1, 2, 1, 1, 1, 3, 4] moon_coeff = [0, 0, 0, 2, 0, 0, 0, -2, 2, 0, 0, 2, -2, 0, 0, -2, 0, -2, 2, 2, 2, -2, 0, 0] sine_coeff = [mpf(-0.40720), mpf(0.17241), mpf(0.01608), mpf(0.01039), mpf(0.00739), mpf(-0.00514), mpf(0.00208), mpf(-0.00111), mpf(-0.00057), mpf(0.00056), mpf(-0.00042), mpf(0.00042), mpf(0.00038), mpf(-0.00024), mpf(-0.00007), mpf(0.00004), mpf(0.00004), mpf(0.00003), mpf(0.00003), mpf(-0.00003), mpf(0.00003), mpf(-0.00002), mpf(-0.00002), mpf(0.00002)] correction = ((mpf(-0.00017) * sin_degrees(cap_omega)) + sigma([sine_coeff, E_factor, solar_coeff, lunar_coeff, moon_coeff], lambda v, w, x, y, z: (v * pow(cap_E, w) * sin_degrees((x * solar_anomaly) + (y * lunar_anomaly) + (z * moon_argument))))) add_const = [mpf(251.88), mpf(251.83), mpf(349.42), mpf(84.66), mpf(141.74), mpf(207.14), mpf(154.84), mpf(34.52), mpf(207.19), mpf(291.34), mpf(161.72), mpf(239.56), mpf(331.55)] add_coeff = [mpf(0.016321), mpf(26.651886), mpf(36.412478), mpf(18.206239), mpf(53.303771), mpf(2.453732), mpf(7.306860), mpf(27.261239), mpf(0.121824), mpf(1.844379), mpf(24.198154), mpf(25.513099), mpf(3.592518)] add_factor = [mpf(0.000165), mpf(0.000164), mpf(0.000126), mpf(0.000110), mpf(0.000062), mpf(0.000060), mpf(0.000056), mpf(0.000047), mpf(0.000042), mpf(0.000040), mpf(0.000037), mpf(0.000035), mpf(0.000023)] extra = (mpf(0.000325) * sin_degrees(poly(c, [mpf(299.77), mpf(132.8475848), mpf(-0.009173)]))) additional = sigma([add_const, add_coeff, add_factor], lambda i, j, l: l * sin_degrees(i + j * k)) return cls.universal_from_dynamical(approx + correction + extra + additional)