Interactive 3D Solar System

This notebook can be used in two ways.

To enable a live Mayavi scene that you can rotate with the mouse and scale with the + and - keys, set the following value to False.

But if you are a contributor to the project who wants to re-render the inline images for a fresh presentation of this notebook online, set the following value to True.

In [1]:
take_screenshots = True
In [2]:
%pylab wx
if take_screenshots:
    %pylab inline
Populating the interactive namespace from numpy and matplotlib
Populating the interactive namespace from numpy and matplotlib
In [3]:
from mayavi import mlab
from mayavi.sources.builtin_surface import BuiltinSurface
from sgp4.earth_gravity import wgs72
from skyfield.constants import AU_KM
from skyfield.api import JulianDate, nine_planets, earth

pylab.rcParams['figure.figsize'] = (8.0, 8.0)

mlab.figure(bgcolor=(0.0, 0.0, 0.0))
planet_color = (0.7, 1.0, 1.0)
yellow = (1.0, 1.0, 0.0)
In [4]:
# One Earth year

day_array = arange(1, 366.3, 0.25)
jd = JulianDate(utc=(2014, 6, day_array, 0, 0, 0))
print 'Start:', jd.tt[0]
print 'End:  ', jd.tt[-1]
Start: 2456809.50078
End:   2457174.75078
In [5]:
def reposition_camera(distance, focalpoint=(0.0, 0.0, 0.0)):
    """Move the camera above the solar system."""
    mlab.view(azimuth=90.0, elevation=360.0 - 23.4,
              distance=distance, focalpoint=focalpoint)
    if take_screenshots:
        imshow(mlab.screenshot(antialiased=True))
        axis('off')
In [6]:
# Get ready to draw!

mlab.clf()

Our first step will be drawing the orbits of the planets over the period of a single Earth year. Note that we are plotting positions in astronomical units (AU), so that the radius of the Earth’s orbit in the plot should be roughly 1.0. Positioning our camera at a distance of 10 AU shows us the four inner planets, out to the orbit of Mars:

In [7]:
for planet in nine_planets:
    x, y, z = planet(jd).position.AU
    mlab.plot3d(x, y, z, color=planet_color,
                tube_radius=None, line_width=2.0)
    print planet.jplname, '- plotted', len(x), 'points'

reposition_camera(10.0)
mercury - plotted 1462 points
venus - plotted 1462 points
earth - plotted 1462 points
mars - plotted 1462 points
jupiter - plotted 1462 points
saturn - plotted 1462 points
uranus - plotted 1462 points
neptune - plotted 1462 points
pluto - plotted 1462 points

We have to step much farther back from the scene, to a distance of over 100 AU, to bring the orbits of the outer planets and Pluto into view.

Jupiter and Saturn are the planets which, over one Earth year, have travelled the blue arcs shown close in against the bottom edge of the inner Solar System. Uranus and then Neptune have moved only small fractions of their huge orbits up near the top of the diagram, while minor planet Pluto sits at the right size of the diagram.

In [8]:
reposition_camera(110.0)

The scale of the Solar System is many times larger than the diameters of any of the objects within it. Even the Sun, which is by far the largest object in the system, cannot easily be seen unless we move in close to the orbit of Mercury:

In [9]:
# Draw a sphere for the Sun

sun_r = 695500.0 / AU_KM  # km
sphere = mlab.points3d(0, 0, 0, name='Sun',
      scale_mode='none', scale_factor=sun_r * 2.0,
      color=yellow, resolution=50)

reposition_camera(distance=1.3)

The Earth by contrast is tiny. To even see it, the camera must zoom in very close to the Earth’s orbit — close enough that you can see the gap between where the Earth was sitting at the end of 2013 and where it was sitting at the end of 2014. The gap between what ought to be “the same position” each year is due to the different positions of the other planets, whose gravity tugs and distorts the Earth’s orbit in a different direction every year:

In [10]:
# Add the Earth

x, y, z = earth(JulianDate(tt=jd.tt[-1])).position.AU
r = wgs72.radiusearthkm / AU_KM
ocean_blue = (0.4, 0.5, 1.0)
sphere = mlab.points3d(x, y, z, name='Globe',
    scale_mode='none', scale_factor=r * 2.0,
    color=ocean_blue, resolution=50)
#sphere.actor.property.specular = 0.20
#sphere.actor.property.specular_power = 10

reposition_camera(distance=0.025, focalpoint=(x, y, z))

The tiny dark-blue dot in the center, at the top of the orbit segment that enters from the bottom, is our home.

If you view this live in a Mayavi window, be sure to first press + (or the same key un-shifted, =) several times to zoom in on the Earth and get a feeling for its size. Then press - until you have zoomed back out to the size of the Solar System, to get a feel for how different the scales are!