def __init__(self, jdn_): assert isinstance(jdn_, JulianDayNumber), \ 'jdn_ should be a JulianDayNumber' T = (jdn_.jdn - epoch_j2000.jdn) / julian_century T_cube = T**3 # @todo - Implement the IAU table accurate to 0.0003" ## Mean elongation of the Moon from Sun D = 297.85036 + (445267.111480 - 0.0019142 * T) * T + T_cube / 189474.0 D = pfmod(D, 360) D = radians(D) ## Mean anomaly of the Earth M_earth = 357.52772 + (35999.050340 - 0.0001603 * T) * T - T_cube / 3000000 M_earth = pfmod(M_earth, 360) M_earth = radians(M_earth) ## Mean anomaly of the Moon M_moon = 134.96298 + (477198.867398 + 0.0086972 * T) * T + T_cube / 56250 M_moon = pfmod(M_moon, 360) M_moon = radians(M_moon) ## Moon's argument of latitude F = 93.271191 + (483202.017538 - 0.0036825 * T) * T + T_cube / 327270 F = pfmod(F, 360) F = radians(F) ## Longitude of ascending node Omega = 125.04452 - (1934.136261 - 0.0020707 * T) * T + T_cube / 450000 Omega = pfmod(Omega, 360) Omega = radians(Omega) # Accurate to 0.5" in dPsi, 0.1" in dEpsilon # See more accurate expression in sun L_sun = pfmod(280.4665 + 36000.7698 * T, 360) L_sun = radians(L_sun) L_moon = pfmod(218.3165 + 481267.8813 * T, 360) L_moon = radians(L_moon) d_psi = -17.20*sin(Omega) - 1.32*sin(2*L_sun) \ - 0.23*sin(2*L_moon) + 0.21*sin(2*Omega) # arc-sec self.d_psi_low = radians(d_psi / 3600.0) d_epsilon = 9.20*cos(Omega) + 0.57*cos(2*L_sun) \ + 0.10*cos(2*L_moon) - 0.09*cos(2*Omega) #arc-sec self.d_epsilon_low = radians(d_epsilon / 3600.0) ## Obliquity (valid only for |U|<1) U = T / 100.0 epsilon = (23 + (26 + 21.448 / 60.0) / 60.0) correction = (((((((( (2.45 * U + 5.79) * U + 27.87) * U + 7.12) * U - 39.05) * U - 249.67) * U - 51.38) * U + 1999.25) * U - 1.55) * U - 4680.93) * U # arc-sec epsilon += (correction / 3600.0) self.epsilon_0 = radians(epsilon)
def canonical(self): # First mod it to lie between 0 and 2*pi two_pis = 2 * pi self.rads = pfmod(self.rads, two_pis) # Now map each quadrant so that the final result lies in -pi/2, pi/2 # 0 - pi/2: no change # pi/2 - pi: map to range pi/2, 0 # pi - 3pi/2: map to range 0, -pi/2 # 3pi/2 - 2pi: map to range -pi/2, 0 if 0 <= self.rads <= pi / 2: pass elif self.rads <= pi: self.rads = pi - self.rads elif self.rads <= 3 * pi / 2: self.rads = -(self.rads - pi) else: # 3*pi/2 < self.rads < 2*pi self.rads -= two_pis # Check that we did every thing right assert fabs( self.rads ) <= pi / 2, 'Latitude should not exceed pi/2 radians either side of 0' return self
def equation_of_kepler_binarysearch(M_, e_, loop_=33): """Calculate the Eccentric anomaly from the Mean Anomaly using binary search. @param M_ The Mean anomaly as a Longitude object @param e_ The eccentricity of the orbit @param loop_ The number of times to @return The Eccentric anomaly as a Longitude object """ assert isinstance(M_, Longitude), 'M_ should be a Longitude' assert isinstance(e_, Number), 'e_ should be a Number' assert 0 <= e_ < 1, 'e_ should lie between 0 and 1' assert type(loop_) is IntType, 'loop_ should be an integer' M_ = pfmod(M_.rads, 2 * pi) if M_ > pi: sign = -1 M_ = 2 * pi - M_ else: sign = 1 E0, D = pi / 2, pi / 4 for idx in range(loop_): M1 = E0 - e * sin(E0) E0 += copysign(D, M_ - M1) D /= 2 E0 *= sign return Longitude(E0)
def __init__(self, jdn_): assert isinstance(jdn_, JulianDayNumber), \ 'jdn_ should be a JulianDayNumber' two_pi = 2 * pi T = (jdn_.jdn - epoch_j2000.jdn) / julian_century # Mean Longitude referred to the mean equinox L_0 = 280.46646 + (36000.76983 + 0.0003032 * T) * T L_0 = pfmod(L_0, 360) L_0 = radians(L_0) # Mean anomaly M = 357.52911 + (35999.05029 - 0.0001537 * T) * T M = pfmod(M, 360) M = radians(M) # Eccentricity of the Earth's orbit e = 0.016708634 - (0.000042037 + 0.0000001267 * T) * T # Equation of the center C = (1.914602 - (0.004817 + 0.000014*T)*T)*sin(M) \ + (0.019993 - 0.000101*T)*sin(2*M) \ + 0.000289*sin(3*M) C = pfmod(C, 360) C = radians(C) # True geometric Longitude referred to the mean equinox of the date self.L = pfmod(L_0 + C, two_pi) # True geometric latitude referred to the mean equinox self.beta = 0 # True anomaly self.v = pfmod(M + C, two_pi) # Radius vector self.R = 1.000001018 * (1 - e**2) / (1 + e * cos(self.v)) # Longitude of ascending node (see more accurate expression in ecliptic) Omega = radians(125.04 - 1934.136 * T) # Apparent Longitude referred to the *true* equinox of the date self.lambda_apparent = degrees(self.L) - 0.00569 - 0.00478 * sin(Omega) self.lambda_apparent = pfmod(self.lambda_apparent, 360) self.lambda_apparent = radians(self.lambda_apparent) # Apparent Latitude referred to the *true* equinox of the date self.beta_apparent = 0 # Equatorial coordinates referred to the mean equinox of the date ecliptic = Ecliptic(jdn_) w_uncorrected = ecliptic.get_obliquity_uncorrected().rads self.alpha = atan2(cos(w_uncorrected) * sin(self.L), cos(self.L)) self.alpha = pfmod(self.alpha, two_pi) self.delta = asin(sin(w_uncorrected) * sin(self.L)) self.delta = pfmod(self.delta, two_pi) # Equatorial coordinates referred to the *true* equinox of the date w_corrected = w_uncorrected + radians(0.00256 * cos(Omega)) self.alpha_apparent = \ atan2(cos(w_corrected)*sin(self.lambda_apparent), cos(self.L)) self.alpha_apparent = pfmod(self.alpha_apparent, two_pi) self.delta_apparent = asin( sin(w_corrected) * sin(self.lambda_apparent)) self.delta_apparent = pfmod(self.delta_apparent, two_pi) # Rectangular Coordinates referred to the mean equinox of the date self.X = self.R * cos(self.beta) * cos(self.L) self.Y = self.R*(cos(self.beta)*sin(self.L)*cos(w_uncorrected) \ - sin(self.beta)*sin(w_uncorrected)) self.Z = self.R*(cos(self.beta)*sin(self.L)*sin(w_uncorrected) \ + sin(self.beta)*cos(w_uncorrected))
def canonical(self): two_pis = 2 * pi self.rads = pfmod(self.rads, two_pis) return self