Skip to main content

Planets Module

The Planets module provides position calculations for the eight major planets (Mercury through Neptune) using algorithms from Jean Meeus' Astronomical Algorithms.

Overview

Planetary positions are essential for observation planning and understanding solar system dynamics. This module calculates:

  • Equatorial coordinates (RA/Dec)
  • Distance from Earth and Sun
  • Apparent magnitude
  • Elongation from Sun
  • Phase and illumination
  • Rise/set/transit times

Accuracy: Positions typically within 1 arcminute, suitable for telescope pointing and observation planning.

Supported Planets

PlanetSymbolEnum Value
MercuryPlanet.MERCURY
VenusPlanet.VENUS
MarsPlanet.MARS
JupiterPlanet.JUPITER
SaturnPlanet.SATURN
UranusPlanet.URANUS
NeptunePlanet.NEPTUNE

Quick Start

CLI Usage

# Single planet position
starward planets position mars

# All planets summary
starward planets all

# Planet rise/set times
starward planets rise jupiter --lat 40.7 --lon -74.0
starward planets set saturn --lat 40.7 --lon -74.0

# Transit time (when planet is highest)
starward planets transit jupiter --lat 40.7 --lon -74.0

# Current altitude
starward planets altitude mars --lat 40.7 --lon -74.0

Python API

from starward.core.planets import (
Planet, planet_position, all_planet_positions,
planet_rise, planet_set, planet_transit, planet_altitude
)
from starward.core.observer import Observer
from starward.core.time import jd_now

# Get current Mars position
jd = jd_now()
mars = planet_position(Planet.MARS, jd)

print(f"Mars RA: {mars.ra.format_hms()}")
print(f"Mars Dec: {mars.dec.format_dms()}")
print(f"Distance: {mars.distance_au:.3f} AU")
print(f"Magnitude: {mars.magnitude:+.1f}")
print(f"Elongation: {mars.elongation.degrees:.1f}°")
print(f"Illumination: {mars.illumination:.1f}%")

# All planets at once
positions = all_planet_positions(jd)
for planet, pos in positions.items():
print(f"{planet.value}: {pos.elongation.degrees:.0f}° from Sun, mag {pos.magnitude:+.1f}")

# Rise/set/transit for an observer
observer = Observer.from_degrees("Home", 40.7, -74.0)
rise = planet_rise(Planet.JUPITER, observer, jd)
transit = planet_transit(Planet.JUPITER, observer, jd)
set_time = planet_set(Planet.JUPITER, observer, jd)

if rise:
print(f"Jupiter rises: {rise.to_datetime()}")
if transit:
print(f"Jupiter transits: {transit.to_datetime()}")
if set_time:
print(f"Jupiter sets: {set_time.to_datetime()}")

Planet Position

The planet_position() function returns a PlanetPosition object:

FieldDescription
raRight Ascension (Angle)
decDeclination (Angle)
distance_auDistance from Earth in AU
distance_sun_auDistance from Sun in AU
magnitudeApparent visual magnitude
elongationAngular distance from Sun (Angle)
illuminationIlluminated fraction (0-100%)
phase_anglePhase angle (Angle)

Elongation

Elongation indicates a planet's position relative to the Sun:

ElongationMeaning
Conjunction (same direction as Sun)
90°Quadrature (quarter phase for inner planets)
180°Opposition (opposite the Sun, best for outer planets)
mars = planet_position(Planet.MARS, jd)
if mars.elongation.degrees > 150:
print("Mars is near opposition - excellent viewing!")

Apparent Magnitude

Typical magnitude ranges:

PlanetRangeNotes
Venus-4.6 to -3Brightest planet
Jupiter-2.9 to -1.6Always prominent
Mars+1.8 to -2.9Varies greatly with distance
Saturn+1.5 to -0.2Rings affect brightness
Mercury+5 to -2Hard to observe
Uranus+5.6 to +5.9Barely naked-eye
Neptune+7.8 to +8Requires binoculars

Rise, Set, and Transit

Calculate when planets rise, set, and cross the meridian:

observer = Observer.from_degrees("Los Angeles", 34.05, -118.25)
jd = jd_now()

# Jupiter visibility tonight
rise = planet_rise(Planet.JUPITER, observer, jd)
transit = planet_transit(Planet.JUPITER, observer, jd)
set_time = planet_set(Planet.JUPITER, observer, jd)

# Best viewing is around transit
if transit:
alt = planet_altitude(Planet.JUPITER, observer, transit)
print(f"Jupiter highest at {transit.to_datetime()}: {alt.degrees:.1f}° altitude")

Circumpolar Planets

At high latitudes, planets near the celestial pole may never set:

if rise is None and set_time is None:
alt = planet_altitude(Planet.JUPITER, observer, jd)
if alt.degrees > 0:
print("Planet is circumpolar (always above horizon)")
else:
print("Planet never rises at this location")

Observation Planning

Finding the Best Time to Observe

# Check which planets are well-placed tonight
positions = all_planet_positions(jd)

print("Tonight's planets:")
for planet, pos in positions.items():
if pos.elongation.degrees > 30: # Reasonable distance from Sun
print(f" {planet.value}: mag {pos.magnitude:+.1f}, "
f"{pos.elongation.degrees:.0f}° from Sun")

Outer Planet Opposition

Outer planets (Mars through Neptune) are best observed near opposition:

# Check if an outer planet is near opposition
mars = planet_position(Planet.MARS, jd)
if mars.elongation.degrees > 170:
print(f"Mars is near opposition!")
print(f" Distance: {mars.distance_au:.3f} AU")
print(f" Magnitude: {mars.magnitude:+.1f}")

Inner Planet Elongation

Mercury and Venus are best observed at maximum elongation:

venus = planet_position(Planet.VENUS, jd)
print(f"Venus elongation: {venus.elongation.degrees:.1f}°")
# Best viewing when elongation > 40°

Verbose Mode

See the calculation steps:

starward planets position mars --verbose
from starward.verbose import VerboseContext

ctx = VerboseContext()
pos = planet_position(Planet.MARS, jd, verbose=ctx)

for step in ctx.steps:
print(step)

Algorithm Details

This module implements the planetary position algorithms from Jean Meeus' Astronomical Algorithms, which calculate:

  1. Heliocentric coordinates using orbital elements
  2. Geocentric coordinates by combining with Earth's position
  3. Apparent position with light-time correction
  4. Magnitude using standard phase functions

The algorithms provide accuracy suitable for observation planning. For high-precision ephemerides, dedicated services like JPL Horizons are recommended.

See Also