def right_ascension(tee, beta, lam): """Return right ascension at moment UT 'tee' of object at latitude 'lam' and longitude 'beta'.""" varepsilon = obliquity(tee) return arctan_degrees((sin_degrees(lam) * cos_degrees(varepsilon)) - (tan_degrees(beta) * sin_degrees(varepsilon)), cos_degrees(lam))
def equation_of_time(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 = 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 = 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 nutation(tee): """Return the longitudinal nutation at moment, tee.""" c = 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(tee, beta, lam): """Return declination at moment UT tee of object at longitude 'lam' and latitude 'beta'.""" varepsilon = obliquity(tee) return arcsin_degrees((sin_degrees(beta) * cos_degrees(varepsilon)) + (cos_degrees(beta) * sin_degrees(varepsilon) * sin_degrees(lam)))
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_longitude(tee): """Return longitude of moon (in degrees) at moment tee. Adapted from "Astronomical Algorithms" by Jean Meeus, Willmann_Bell, Inc., 2nd ed., 1998.""" c = julian_centuries(tee) cap_L_prime = mean_lunar_longitude(c) cap_D = lunar_elongation(c) cap_M = solar_anomaly(c) cap_M_prime = lunar_anomaly(c) cap_F = 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 (cap_L_prime + correction + venus + jupiter + flat_earth + nutation(tee)) % 360
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_longitude(tee) beta = lunar_latitude(tee) alpha =right_ascension(tee, beta, lamb) delta = declination(tee, beta, lamb) theta0 = 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(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 = julian_centuries(tee) cap_D = lunar_elongation(c) cap_M = solar_anomaly(c) cap_M_prime = lunar_anomaly(c) cap_F = 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 alt_lunar_node(tee) + periodic_terms
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 = declination(tee_prime, mpf(0), solar_longitude(tee_prime)) return ((tan_degrees(phi) * tan_degrees(delta)) + (sin_degrees(alpha) / (cos_degrees(delta) * cos_degrees(phi))))
def lunar_latitude(tee): """Return the latitude of moon (in degrees) at moment, tee. Adapted from "Astronomical Algorithms" by Jean Meeus, Willmann_Bell, Inc., 1998.""" c = julian_centuries(tee) cap_L_prime = mean_lunar_longitude(c) cap_D = lunar_elongation(c) cap_M = solar_anomaly(c) cap_M_prime = lunar_anomaly(c) cap_F = 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(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 = julian_centuries(tee) eta = poly( c, [0, secs(mpf(47.0029)), secs(mpf(-0.03302)), secs(mpf(0.000060))]) % 360 cap_P = poly(c, [mpf(174.876384), secs(mpf(-869.8089)), secs(mpf(0.03536))]) % 360 p = 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 (p + cap_P - arg) % 360
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 int(round(exact + error)) / 3438
def solar_longitude(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 = 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 (lam + aberration(tee) + nutation(tee)) % 360
def nth_new_moon(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 = (J2000 + poly(c, [ mpf(5.09766), 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 universal_from_dynamical(approx + correction + extra + additional)