Skip to content

Instantly share code, notes, and snippets.

@chongchonghe
Last active February 4, 2024 02:53
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save chongchonghe/c0c118af42829e6fc5df9f19e7fa87e9 to your computer and use it in GitHub Desktop.
Save chongchonghe/c0c118af42829e6fc5df9f19e7fa87e9 to your computer and use it in GitHub Desktop.
Python solar system (a file in this repo https://github.com/chongchonghe/Python-solar-system )
#!/usr/bin/env python
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from astropy.time import Time
from astroquery.jplhorizons import Horizons
sim_start_date = "2018-01-01" # simulating a solar system starting from this date
sim_duration = 2 * 365 # (int) simulation duration in days
m_earth = 5.9722e24 / 1.98847e30 # Mass of Earth relative to mass of the sun
m_moon = 7.3477e22 / 1.98847e30
class Object: # define the objects: the Sun, Earth, Mercury, etc
def __init__(self, name, rad, color, r, v):
self.name = name
self.r = np.array(r, dtype=np.float)
self.v = np.array(v, dtype=np.float)
self.xs = []
self.ys = []
self.plot = ax.scatter(r[0], r[1], color=color, s=rad**2, edgecolors=None, zorder=10)
self.line, = ax.plot([], [], color=color, linewidth=1.4)
class SolarSystem:
def __init__(self, thesun):
self.thesun = thesun
self.planets = []
self.time = None
self.timestamp = ax.text(.03, .94, 'Date: ', color='w', transform=ax.transAxes, fontsize='x-large')
def add_planet(self, planet):
self.planets.append(planet)
def evolve(self): # evolve the trajectories
dt = 1.0
self.time += dt
plots = []
lines = []
for p in self.planets:
p.r += p.v * dt
acc = -2.959e-4 * p.r / np.sum(p.r**2)**(3./2) # in units of AU/day^2
p.v += acc * dt
p.xs.append(p.r[0])
p.ys.append(p.r[1])
p.plot.set_offsets(p.r[:2])
p.line.set_xdata(p.xs)
p.line.set_ydata(p.ys)
plots.append(p.plot)
lines.append(p.line)
self.timestamp.set_text('Date: ' + Time(self.time, format='jd', out_subfmt='date').iso)
return plots + lines + [self.timestamp]
plt.style.use('dark_background')
fig = plt.figure(figsize=[6, 6])
ax = plt.axes([0., 0., 1., 1.], xlim=(-1.8, 1.8), ylim=(-1.8, 1.8))
ax.set_aspect('equal')
ax.axis('off')
ss = SolarSystem(Object("Sun", 28, 'red', [0, 0, 0], [0, 0, 0]))
ss.time = Time(sim_start_date).jd
colors = ['gray', 'orange', 'blue', 'chocolate']
sizes = [0.38, 0.95, 1., 0.53]
names = ['Mercury', 'Venus', 'Earth', 'Mars']
texty = [.47, .73, 1, 1.5]
for i, nasaid in enumerate([1, 2, 3, 4]): # The 1st, 2nd, 3rd, 4th planet in solar system
obj = Horizons(id=nasaid, location="@sun", epochs=ss.time, id_type='id').vectors()
ss.add_planet(Object(nasaid, 20 * sizes[i], colors[i],
[np.double(obj[xi]) for xi in ['x', 'y', 'z']],
[np.double(obj[vxi]) for vxi in ['vx', 'vy', 'vz']]))
ax.text(0, - (texty[i] + 0.1), names[i], color=colors[i], zorder=1000, ha='center', fontsize='large')
def animate(i):
return ss.evolve()
ani = animation.FuncAnimation(fig, animate, repeat=False, frames=sim_duration, blit=True, interval=20,)
plt.show()
# ani.save('solar_system_6in_150dpi.mp4', fps=60, dpi=150)
@wenzao
Copy link

wenzao commented Oct 9, 2021

I got the following error message:

/solar_system.py:16: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here.
Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
  self.r    = np.array(r, dtype=np.float)
/Users/mengshupan/Desktop/solar_system.py:17: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here.
Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
  self.v    = np.array(v, dtype=np.float)
Traceback (most recent call last):
  File "/opt/miniconda3/lib/python3.9/site-packages/astropy/time/core.py", line 439, in _get_time_fmt
    return cls(val, val2, scale, precision, in_subfmt, out_subfmt)
  File "/opt/miniconda3/lib/python3.9/site-packages/astropy/time/formats.py", line 141, in __init__
    self.out_subfmt = out_subfmt
  File "/opt/miniconda3/lib/python3.9/site-packages/astropy/time/formats.py", line 183, in out_subfmt
    self._select_subfmts(subfmt)
  File "/opt/miniconda3/lib/python3.9/site-packages/astropy/time/formats.py", line 399, in _select_subfmts
    raise ValueError(f'subformat {pattern!r} must match one of '
ValueError: subformat 'date' must match one of ['float', 'long', 'decimal', 'str', 'bytes'] for format jd

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/opt/miniconda3/lib/python3.9/site-packages/matplotlib/cbook/__init__.py", line 270, in process
    func(*args, **kwargs)
  File "/opt/miniconda3/lib/python3.9/site-packages/matplotlib/animation.py", line 991, in _start
    self._init_draw()
  File "/opt/miniconda3/lib/python3.9/site-packages/matplotlib/animation.py", line 1753, in _init_draw
    self._draw_frame(next(self.new_frame_seq()))
  File "/opt/miniconda3/lib/python3.9/site-packages/matplotlib/animation.py", line 1776, in _draw_frame
    self._drawn_artists = self._func(framedata, *self._args)
  File "/Users/mengshupan/Desktop/solar_system.py", line 68, in animate
    return ss.evolve()
  File "/Users/mengshupan/Desktop/solar_system.py", line 47, in evolve
    self.timestamp.set_text('Date: ' + Time(self.time, format='jd', out_subfmt='date').iso)
  File "/opt/miniconda3/lib/python3.9/site-packages/astropy/time/core.py", line 1527, in __init__
    self._init_from_vals(val, val2, format, scale, copy,
  File "/opt/miniconda3/lib/python3.9/site-packages/astropy/time/core.py", line 381, in _init_from_vals
    self._time = self._get_time_fmt(val, val2, format, scale,
  File "/opt/miniconda3/lib/python3.9/site-packages/astropy/time/core.py", line 447, in _get_time_fmt
    raise ValueError(
ValueError: Input values did not match the format class jd:
ValueError: subformat 'date' must match one of ['float', 'long', 'decimal', 'str', 'bytes'] for format jd

@adairaar
Copy link

Change this (line 56):
ss.time = Time(sim_start_date).jd

to this:
ss.time = Time(sim_start_date)
ss.time.format='jd'

And change this (line 47):
self.timestamp.set_text('Date: ' + Time(self.time, format='jd', out_subfmt='date').iso)

to this:
self.timestamp.set_text('Date: ' + self.time.iso)

That fixed the problem for me.

@wenzao
Copy link

wenzao commented Oct 10, 2021

Yes that worked. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment