def equinox(jd, season, delta): """Return the precise moment of an equinox or solstice event on Earth. Parameters: jd : Julian Day of an approximate time of the event in dynamical time season : one of ("spring", "summer", "autumn", "winter") delta : the required precision in days. Times accurate to a second are reasonable when using the VSOP model. Returns: Julian Day of the event in dynamical time """ # # If we knew that the starting approximate time was close enough # to the actual time, we could pull nut_in_lon() and the aberration # out of the loop and save some calculating. # circ = _circle[season] sun = Sun() for i in range(20): jd0 = jd L, B, R = sun.dimension3(jd) L += nut_in_lon(jd) + aberration_low(R) L, B = vsop_to_fk5(jd, L, B) # Meeus uses jd + 58 * sin(diff(...)) jd += diff_angle(L, circ) * _k_sun_motion if abs(jd - jd0) < delta: return jd raise Error, "bailout"
def rise(jd, raList, decList, h0, delta): """Return the Julian Day of the rise time of an object. Parameters: jd : Julian Day number of the day in question, at 0 hr UT raList : a sequence of three right accension values, in radians, for (jd-1, jd, jd+1) decList : a sequence of three right declination values, in radians, for (jd-1, jd, jd+1) h0 : the standard altitude in radians delta : desired accuracy in days. Times less than one minute are infeasible for rise times because of atmospheric refraction. Returns: Julian Day of the rise time """ longitude = astronomia.globals.longitude latitude = astronomia.globals.latitude THETA0 = sidereal_time_greenwich(jd) deltaT_days = deltaT_seconds(jd) / seconds_per_day cosH0 = (sin(h0) - sin(latitude) * sin(decList[1])) / (cos(latitude) * cos(decList[1])) # # future: return some indicator when the object is circumpolar or always # below the horizon. # if cosH0 < -1.0: # circumpolar return None if cosH0 > 1.0: # never rises return None H0 = acos(cosH0) m0 = (raList[1] + longitude - THETA0) / pi2 m = m0 - H0 / pi2 # this is the only difference between rise() and set() if m < 0: m += 1 elif m > 1: m -= 1 if not 0 <= m <= 1: raise Error, "m is out of range = " + str(m) for bailout in range(20): m0 = m theta0 = modpi2(THETA0 + _k1 * m) n = m + deltaT_days if not -1 < n < 1: return None # Bug: this is where we drop some events ra = interpolate_angle3(n, raList) dec = interpolate3(n, decList) H = theta0 - longitude - ra # if H > pi: # H = H - pi2 H = diff_angle(0.0, H) A, h = equ_to_horiz(H, dec) dm = (h - h0) / (pi2 * cos(dec) * cos(latitude) * sin(H)) m += dm if abs(m - m0) < delta: return jd + m raise Error, "bailout"
def _riseset(jd, raList, decList, h0, delta, mode, longitude=astronomia.globals.longitude, latitude=astronomia.globals.latitude): # Private function since rise/set so similar THETA0 = sidereal_time_greenwich(jd) deltaT_days = deltaT_seconds(jd) / seconds_per_day cosH0 = (np.sin(h0) - np.sin(latitude)*np.sin(decList[1])) / ( np.cos(latitude)*np.cos(decList[1])) # # future: return some indicator when the object is circumpolar or always # below the horizon. # if cosH0 < -1.0: # circumpolar return None if cosH0 > 1.0: # never rises return None H0 = np.arccos(cosH0) m0 = (raList[1] + longitude - THETA0) / pi2 if mode == 'rise': m = m0 - H0 / pi2 # the only difference between rise() and settime() elif mode == 'set': m = m0 + H0 / pi2 # the only difference between rise() and settime() if m < 0: m += 1 elif m > 1: m -= 1 if not 0 <= m <= 1: raise Error("m is out of range = " + str(m)) for bailout in range(20): m0 = m theta0 = modpi2(THETA0 + _k1 * m) n = m + deltaT_days if not -1 < n < 1: return None # Bug: this is where we drop some events ra = interpolate_angle3(n, raList) dec = interpolate3(n, decList) H = theta0 - longitude - ra # if H > pi: # H = H - pi2 H = diff_angle(0.0, H) A, h = equ_to_horiz(H, dec) dm = (h - h0) / (pi2 * np.cos(dec) * np.cos(latitude) * np.sin(H)) m += dm if abs(m - m0) < delta: return jd + m raise Error("bailout")
def transit(jd, raList, delta): """Return the Julian Day of the transit time of an object. Parameters: jd : Julian Day number of the day in question, at 0 hr UT raList : a sequence of three right accension values, in radians, for (jd-1, jd, jd+1) delta : desired accuracy in days. Returns: Julian Day of the transit time """ # # future: report both upper and lower culmination, and transits of objects below # the horizon # longitude = astronomia.globals.longitude THETA0 = sidereal_time_greenwich(jd) deltaT_days = deltaT_seconds(jd) / seconds_per_day m = (raList[1] + longitude - THETA0) / pi2 if m < 0: m += 1 elif m > 1: m -= 1 if not 0 <= m <= 1: raise Error, "m is out of range = " + str(m) for bailout in range(20): m0 = m theta0 = modpi2(THETA0 + _k1 * m) n = m + deltaT_days if not -1 < n < 1: return None # Bug: this is where we drop some events ra = interpolate_angle3(n, raList) H = theta0 - longitude - ra # if H > pi: # H = H - pi2 H = diff_angle(0.0, H) dm = -H / pi2 m += dm if abs(m - m0) < delta: return jd + m raise Error, "bailout"
def transit(jd, raList, delta): """Return the Julian Day of the transit time of an object. Arguments: - `jd` : Julian Day number of the day in question, at 0 hr UT - `raList` : a sequence of three right accension values, in radians, for (jd-1, jd, jd+1) - `delta` : desired accuracy in days. Returns: - Julian Day of the transit time """ # # future: report both upper and lower culmination, and transits of objects # below the horizon # longitude = astronomia.globals.longitude THETA0 = sidereal_time_greenwich(jd) deltaT_days = deltaT_seconds(jd) / seconds_per_day m = (raList[1] + longitude - THETA0) / pi2 if m < 0: m += 1 elif m > 1: m -= 1 if not 0 <= m <= 1: raise Error("m is out of range = " + str(m)) for bailout in range(20): m0 = m theta0 = modpi2(THETA0 + _k1 * m) n = m + deltaT_days if not -1 < n < 1: return None # Bug: this is where we drop some events ra = interpolate_angle3(n, raList) H = theta0 - longitude - ra # if H > pi: # H = H - pi2 H = diff_angle(0.0, H) dm = -H/pi2 m += dm if abs(m - m0) < delta: return jd + m raise Error("bailout")
def geocentric_planet(jd, planet, deltaPsi, epsilon, delta): """Calculate the equatorial coordinates of a planet The results will be geocentric, corrected for light-time and aberration. Arguments: - `jd` : Julian Day in dynamical time - `planet` : must be one of ("Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune") - `deltaPsi` : nutation in longitude, in radians - `epsilon` : True obliquity (corrected for nutation), in radians - `delta` : desired accuracy, in days Returns: - right accension, in radians - declination, in radians """ jd = np.atleast_1d(jd) vsop = VSOP87d() t = jd l0 = -100.0 # impossible value # We need to iterate to correct for light-time and aberration. # At most three passes through the loop always nails it. # Note that we move both the Earth and the other planet during # the iteration. for bailout in range(20): # heliocentric geometric ecliptic coordinates of the Earth L0, B0, R0 = vsop.dimension3(t, "Earth") # heliocentric geometric ecliptic coordinates of the planet L, B, R = vsop.dimension3(t, planet) # rectangular offset cosB0 = np.cos(B0) cosB = np.cos(B) x = R*cosB*np.cos(L) - R0*cosB0*np.cos(L0) y = R*cosB*np.sin(L) - R0*cosB0*np.sin(L0) z = R*np.sin(B) - R0*np.sin(B0) # geocentric geometric ecliptic coordinates of the planet x2 = x*x y2 = y*y l = np.arctan2(y, x) b = np.arctan2(z, np.sqrt(x2 + y2)) # distance to planet in AU dist = np.sqrt(x2 + y2 + z*z) # light time in days tau = 0.0057755183 * dist if abs(diff_angle(l, l0)) < pi2 * delta: break # adjust for light travel time and try again l0 = l t = jd - tau else: raise Error("bailout") # transform to FK5 ecliptic and equinox l, b = vsop_to_fk5(jd, l, b) # nutation in longitude l = l + deltaPsi # equatorial coordinates ra, dec = ecl_to_equ(l, b, epsilon) return ra, dec
def geocentric_planet(jd, planet, deltaPsi, epsilon, delta): """Calculate the equatorial coordinates of a planet The results will be geocentric, corrected for light-time and aberration. Arguments: - `jd` : Julian Day in dynamical time - `planet` : must be one of ("Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune") - `deltaPsi` : nutation in longitude, in radians - `epsilon` : True obliquity (corrected for nutation), in radians - `delta` : desired accuracy, in days Returns: - right accension, in radians - declination, in radians """ jd = np.atleast_1d(jd) vsop = VSOP87d() t = jd l0 = -100.0 # impossible value # We need to iterate to correct for light-time and aberration. # At most three passes through the loop always nails it. # Note that we move both the Earth and the other planet during # the iteration. for bailout in range(20): # heliocentric geometric ecliptic coordinates of the Earth L0, B0, R0 = vsop.dimension3(t, "Earth") # heliocentric geometric ecliptic coordinates of the planet L, B, R = vsop.dimension3(t, planet) # rectangular offset cosB0 = np.cos(B0) cosB = np.cos(B) x = R * cosB * np.cos(L) - R0 * cosB0 * np.cos(L0) y = R * cosB * np.sin(L) - R0 * cosB0 * np.sin(L0) z = R * np.sin(B) - R0 * np.sin(B0) # geocentric geometric ecliptic coordinates of the planet x2 = x * x y2 = y * y l = np.arctan2(y, x) b = np.arctan2(z, np.sqrt(x2 + y2)) # distance to planet in AU dist = np.sqrt(x2 + y2 + z * z) # light time in days tau = 0.0057755183 * dist if abs(diff_angle(l, l0)) < pi2 * delta: break # adjust for light travel time and try again l0 = l t = jd - tau else: raise Error("bailout") # transform to FK5 ecliptic and equinox l, b = vsop_to_fk5(jd, l, b) # nutation in longitude l = l + deltaPsi # equatorial coordinates ra, dec = ecl_to_equ(l, b, epsilon) return ra, dec