def test_rectangular_coordinates_j2000(): """Tests rectangular_coordinates_j2000() method of Sun class""" epoch = Epoch(1992, 10, 13.0) x, y, z = Sun.rectangular_coordinates_j2000(epoch) assert abs(round(x, 8) - (-0.93740485)) < TOL, \ "ERROR: 1st rectangular_coordinates_j2000() test, 'x' doesn't match" assert abs(round(y, 8) - (-0.3131474)) < TOL, \ "ERROR: 2nd rectangular_coordinates_j2000() test, 'y' doesn't match" assert abs(round(z, 8) - (-0.13577045)) < TOL, \ "ERROR: 3rd rectangular_coordinates_j2000() test, 'z' doesn't match"
def geocentric_position(self, epoch): """This method computes the geocentric position of a minor celestial body (right ascension and declination) for the given epoch, and referred to the standard equinox J2000.0. Additionally, it also computes the elongation angle to the Sun. :param epoch: Epoch to compute geocentric position, as an Epoch object :type epoch: :py:class:`Epoch` :returns: A tuple containing the right ascension, the declination and the elongation angle to the Sun, as Angle objects :rtype: tuple :raises: TypeError if input value is of wrong type. >>> a = 2.2091404 >>> e = 0.8502196 >>> q = a * (1.0 - e) >>> i = Angle(11.94524) >>> omega = Angle(334.75006) >>> w = Angle(186.23352) >>> t = Epoch(1990, 10, 28.54502) >>> minor = Minor(q, e, i, omega, w, t) >>> epoch = Epoch(1990, 10, 6.0) >>> ra, dec, p = minor.geocentric_position(epoch) >>> print(ra.ra_str(n_dec=1)) 10h 34' 13.7'' >>> print(dec.dms_str(n_dec=0)) 19d 9' 32.0'' >>> print(round(p, 2)) 40.51 >>> t = Epoch(1998, 4, 14.4358) >>> q = 1.487469 >>> e = 1.0 >>> i = Angle(0.0) >>> omega = Angle(0.0) >>> w = Angle(0.0) >>> minor = Minor(q, e, i, omega, w, t) >>> epoch = Epoch(1998, 8, 5.0) >>> ra, dec, p = minor.geocentric_position(epoch) >>> print(ra.ra_str(n_dec=1)) 5h 45' 34.5'' >>> print(dec.dms_str(n_dec=0)) 23d 23' 53.0'' >>> print(round(p, 2)) 45.73 """ # First check that input value is of correct types if not isinstance(epoch, Epoch): raise TypeError("Invalid input type") # Get internal parameters aa, bb, cc = self._aa, self._bb, self._cc am, bm, cm = self._am, self._bm, self._cm # Get the mean motion and other orbital parameters n = self._n a = self._a e = self._e w = self._w t = self._t # Time since perihelion t_peri = epoch - t # Now, compute the mean anomaly, in degrees m = t_peri * n m = Angle(m) if e < 0.98: # Elliptic case # With the mean anomaly, use Kepler's equation to find E and v ee, v = kepler_equation(e, m) ee = Angle(ee).to_positive() # Get r er = ee.rad() rr = a * (1.0 - e * cos(er)) elif abs(e - 1.0) < self._tol: # Parabolic case q = self._q ww = (0.03649116245 * (epoch - self._t)) / (q * sqrt(q)) sp = ww / 3.0 iterate = True while iterate: s = (2.0 * sp * sp * sp + ww) / (3.0 * (sp * sp + 1.0)) iterate = abs(s - sp) > self._tol sp = s v = 2.0 * atan(s) v = Angle(v, radians=True) rr = q * (1.0 + s * s) else: # We are in the near-parabolic case v, rr = self._near_parabolic(t_peri) # Compute the heliocentric rectangular equatorial coordinates wr = w.rad() vr = Angle(v).rad() x = rr * am * sin(aa + wr + vr) y = rr * bm * sin(bb + wr + vr) z = rr * cm * sin(cc + wr + vr) # Now let's compute Sun's rectangular coordinates xs, ys, zs = Sun.rectangular_coordinates_j2000(epoch) xi = x + xs eta = y + ys zeta = z + zs delta = sqrt(xi * xi + eta * eta + zeta * zeta) # We need to correct for the effect of light-time. Compute delay tau tau = 0.0057755183 * delta # Recompute some critical parameters t_peri = epoch - t - tau # Now, compute the mean anomaly, in degrees m = t_peri * n m = Angle(m) if e < 0.98: # Elliptic case # With the mean anomaly, use Kepler's equation to find E and v ee, v = kepler_equation(e, m) ee = Angle(ee).to_positive() # Get r er = ee.rad() rr = a * (1.0 - e * cos(er)) elif abs(e - 1.0) < self._tol: # Parabolic case q = self._q ww = (0.03649116245 * (epoch - self._t)) / (q * sqrt(q)) sp = ww / 3.0 iterate = True while iterate: s = (2.0 * sp * sp * sp + ww) / (3.0 * (sp * sp + 1.0)) iterate = abs(s - sp) > self._tol sp = s v = 2.0 * atan(s) v = Angle(v, radians=True) rr = q * (1.0 + s * s) else: # We are in the near-parabolic case v, rr = self._near_parabolic(t_peri) # Compute the heliocentric rectangular equatorial coordinates wr = w.rad() vr = Angle(v).rad() x = rr * am * sin(aa + wr + vr) y = rr * bm * sin(bb + wr + vr) z = rr * cm * sin(cc + wr + vr) xi = x + xs eta = y + ys zeta = z + zs ra = Angle(atan2(eta, xi), radians=True) dec = Angle(atan2(zeta, sqrt(xi * xi + eta * eta)), radians=True) r_sun = sqrt(xs * xs + ys * ys + zs * zs) psi = acos((xi * xs + eta * ys + zeta * zs) / (r_sun * delta)) psi = Angle(psi, radians=True) return ra, dec, psi
def geocentric_position(epoch): """This method computes the geocentric position of Pluto (right ascension and declination) for the given epoch, for the standard equinox J2000.0. :param epoch: Epoch to compute geocentric position, as an Epoch object :type epoch: :py:class:`Epoch` :returns: A tuple containing the right ascension and the declination as Angle objects :rtype: tuple :raises: TypeError if input value is of wrong type. :raises: ValueError if input epoch outside the 1885-2099 range. >>> epoch = Epoch(1992, 10, 13.0) >>> ra, dec = Pluto.geocentric_position(epoch) >>> print(ra.ra_str(n_dec=1)) 15h 31' 43.7'' >>> print(dec.dms_str(n_dec=0)) -4d 27' 29.0'' """ # First check that input value is of correct types if not isinstance(epoch, Epoch): raise TypeError("Invalid input type") # Check that the input epoch is within valid range y = epoch.year() if y < 1885.0 or y > 2099.0: raise ValueError("Epoch outside the 1885-2099 range") # Compute the heliocentric position of Pluto ll, b, r = Pluto.geometric_heliocentric_position(epoch) # Change angles to radians ll = ll.rad() b = b.rad() # Values corresponding to obliquity of ecliptic (epsilon) for J2000.0 sine = 0.397777156 cose = 0.917482062 x = r * cos(ll) * cos(b) y = r * (sin(ll) * cos(b) * cose - sin(b) * sine) z = r * (sin(ll) * cos(b) * sine + sin(b) * cose) # Compute Sun's J2000.0 rectacngular coordinates xs, ys, zs = Sun.rectangular_coordinates_j2000(epoch) # Compute auxiliary quantities xi = x + xs eta = y + ys zeta = z + zs # Compute Pluto's distance to Earth delta = sqrt(xi * xi + eta * eta + zeta * zeta) # Get the light-time difference tau = 0.0057755183 * delta # Repeat the computations using the light-time correction ll, b, r = Pluto.geometric_heliocentric_position(epoch - tau) # Change angles to radians ll = ll.rad() b = b.rad() x = r * cos(ll) * cos(b) y = r * (sin(ll) * cos(b) * cose - sin(b) * sine) z = r * (sin(ll) * cos(b) * sine + sin(b) * cose) # Compute auxiliary quantities xi = x + xs eta = y + ys zeta = z + zs # Compute Pluto's distance to Earth delta = sqrt(xi * xi + eta * eta + zeta * zeta) # Compute right ascension and declination alpha = Angle(atan2(eta, xi), radians=True) dec = Angle(asin(zeta / delta), radians=True) return alpha.to_positive(), dec