Skip to content

Repository files navigation

SOLSYS

Kepler's three laws

SOLSYS visualizes the solar system with corrected Keplerian physics — from the inner planets out past the Kuiper Belt and Oort Cloud to nearby stars.

The main product is animation: light/dark GIFs of the inner system and a staged 3D zoom from the Oort cloud inward. A side product renders static multi-zoom JPGs (light/dark) and a light-year neighborhood star map. Shared libraries hold orbit math, catalogs, and asteroid-population motion so both products stay in sync.

Built with numpy, pandas, and matplotlib. Orbital elements include elliptical planet orbits, spherical asteroid/Kuiper/Oort shells, Jupiter Trojans/Greeks, Hilda clusters, moons, named asteroids, and hyperbolic interstellar visitors (1I/ʻOumuamua, 2I/Borisov, 3I/ATLAS) from data/interstellar_objects.csv.

What's included

Layer Path Role
CLI render.py Single entry point: animate / static / neighborhood / all
Main product animate/ GIF animations (2D inner system + 3D zoom tour); Blender close-ups planned under animate/scenes/blender/
Side product static/ Multi-zoom JPGs light/dark (2D top-down / 3D) and neighborhood star map
Shared physics solsys/physics/ Constants, orbits, catalogs, belt generators, view registry
Shared motion solsys/motion/ Animated asteroid / Hilda / Trojan / Kuiper / Oort populations

Outputs

  • Main: output/animate/2d/, output/animate/3d/
  • Side: output/2d/, output/3d/, output/neighborhood/

File structure

SOLSYS/
├── render.py                                      # CLI entry point
├── requirements.txt
├── requirements-dev.txt                           # pre-commit, ruff, radon, xenon
├── pyproject.toml                                 # Ruff config
├── .pre-commit-config.yaml                        # Git hook definitions
├── .githooks/
│   └── commit-msg                                 # type(SOLSYS[-N]): subject
├── README.md
├── docs/
│   ├── keplers_three_laws.png                     # Kepler laws diagram
│   └── generate_keplers_laws_figure.py            # Regenerates the diagram
├── data/
│   ├── nearby_stars_30.csv                        # Star catalog (RA/Dec, distances, system_id; includes hosts beyond 30 ly)
│   ├── systems.csv                                # Star systems (sol, alpha_centauri, barnards_star, trappist_1, tabbys_star, …)
│   ├── stellar_orbits.csv                         # Multi-star orbits vs system barycenter
│   ├── planets.csv                                # Exoplanets linked by host_star_uuid
│   ├── interstellar_objects.csv                   # 1I/2I/3I hyperbolic visitors
│   └── tabbys_star_lightcurve.csv                 # Downsampled Kepler LC for Tabby's Star inset
│
├── animate/                                       # MAIN PRODUCT — GIF animations
│   ├── __init__.py
│   ├── solar_system_animator.py                   # SolarSystemAnimator, renderAllAnimations
│   ├── camera_controller.py                       # CameraController
│   ├── animation_styles.py                        # Light/dark styles and timing constants
│   └── scenes/
│       ├── inner_system.py                        # Fixed 2D inner-system scene
│       ├── zoom_tour.py                          # Staged 3D Oort → inner zoom
│       ├── exoplanet_system.py                    # Shared single-host exoplanet top-down animator
│       ├── alpha_centauri.py                      # A–B close-up, wide triple; Proxima via exoplanet_system
│       ├── sol_centauri_cinematic.py              # Sol → α Cen AB cinematic (uses frame transform)
│       ├── barnards_star.py                       # Barnard's Star planets via exoplanet_system
│       ├── trappist_1.py                          # TRAPPIST-1 planets via exoplanet_system
│       ├── tabbys_star.py                         # Tabby's Star dust-cloud dimming schematic
│       ├── interstellar_objects.py                # 1I/2I/3I hyperbolic passages (side + oblique)
│       └── blender/                               # Future planet close-ups
│           └── README.md
│
├── static/                                        # SIDE PRODUCT — still images
│   ├── __init__.py
│   ├── solar_system_visualizer.py                 # SolarSystemVisualizer
│   ├── interstellar_neighborhood_visualizer.py    # InterstellarNeighborhoodVisualizer
│   ├── dimension_plotter.py                       # DimensionPlotter
│   └── hilda_point_generator.py                   # HildaPointGenerator
│
├── tests/                                         # Unit tests (stdlib unittest)
│   ├── test_frame_transform.py                    # Sol ↔ α Cen frame transform
│   └── test_sol_centauri_cinematic.py             # Sol → α Cen cinematic helpers
│
├── solsys/                                        # Shared libraries (no plotting)
│   ├── physics/
│   │   ├── astronomical_constants.py              # AstronomicalConstants
│   │   ├── orbit_calculator.py                    # OrbitCalculator
│   │   ├── frame_transform.py                     # Sol ↔ α Cen AB barycenter frame transform
│   │   ├── belt_point_generator.py                # BeltPointGenerator
│   │   ├── view_definition.py                     # ViewDefinition
│   │   ├── view_registry.py                       # ViewRegistry
│   │   ├── point_density_config.py                # PointDensityConfig
│   │   └── catalogs/
│   │       ├── planet_catalog.py                  # PlanetCatalog, PlanetOrbit (Sol, hard-coded)
│   │       ├── moon_catalog.py                    # MoonCatalog, MoonOrbit
│   │       ├── famous_asteroid_catalog.py         # FamousAsteroidCatalog, FamousAsteroidOrbit
│   │       ├── star_catalog.py                    # StarCatalog
│   │       ├── system_catalog.py                  # SystemCatalog (multi-star systems)
│   │       └── interstellar_object_catalog.py     # InterstellarObjectCatalog (1I/2I/3I)
│   └── motion/
│       ├── mean_anomaly.py                        # meanAnomalyAtFrame, planetMeanAnomalyRad
│       └── animated_asteroid_population.py        # AnimatedAsteroidPopulation, AsteroidPopulationCounts
│
└── output/
    ├── animate/
    │   ├── 2d/                                    # inner_solar_system_{light,dark}.gif
    │   ├── 3d/                                    # solar_system_{light,dark}.gif
│   ├── alpha_centauri/                        # ab / system_wide / proxima_planets GIFs
│   ├── sol_centauri/                          # sol_centauri_cinematic_{light,dark}.gif
│   ├── barnards_star/                         # barnards_star_planets_{light,dark}.gif
│   ├── trappist_1/                            # trappist_1_planets_{light,dark}.gif
│   ├── tabbys_star/                           # tabbys_star_dust_{light,dark}.gif
│   └── interstellar_objects/                  # {oumuamua,borisov,atlas}_{side,oblique}_{light,dark}.gif
    ├── 2d/                                        # Static top-down zoom JPGs (*_{light,dark}.jpg)
    ├── 3d/                                        # Static perspective zoom JPGs (*_{light,dark}.jpg)
    └── neighborhood/                              # interstellar_neighborhood_*ly.jpg

Architecture

render.py
   ├── animate/          ← main product (matplotlib GIFs)
   │      └── uses solsys.motion + solsys.physics
   └── static/           ← side product (matplotlib JPGs)
          └── uses solsys.physics

solsys.physics   → constants, Kepler/hyperbola math, catalogs
solsys.motion    → moving asteroid fields for animation frames

2D views are a top-down projection of the same XYZ geometry used in 3D.

Gallery

Animations (main)

Inner Solar System

Light Dark
Inner 2D light Inner 2D dark

Solar System Zoom

Light Dark
Zoom 3D light Zoom 3D dark

Sol → Alpha Centauri cinematic

Light Dark
Sol Centauri light Sol Centauri dark

Static zoom views (side)

Inner Solar System With Jupiter

Light Dark
Inner light Inner dark

Solar System With Kuiper Belt

Light Dark
Kuiper light Kuiper dark

Solar System With Oort Cloud

Light Dark
Oort light Oort dark

Solar System with Alpha Centauri

Light Dark
Alpha Cen light Alpha Cen dark

Neighbors Within 10 Light Years

Light Dark
10 ly light 10 ly dark

Neighbors Within 25 Light Years

Light Dark
25 ly light 25 ly dark

Matching 3D static views

Inner Solar System With Jupiter

Light Dark
3D Inner light 3D Inner dark

Solar System With Kuiper Belt

Light Dark
3D Kuiper light 3D Kuiper dark

Solar System With Oort Cloud

Light Dark
3D Oort light 3D Oort dark

Solar System with Alpha Centauri

Light Dark
3D Alpha light 3D Alpha dark

Getting started

python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
.venv/bin/pip install -r requirements-dev.txt
.venv/bin/pre-commit install
.venv/bin/pre-commit install --hook-type commit-msg

Git hooks (pre-commit)

After install, commits are gated by:

  • pre-commit — Ruff format + lint on animate/, static/, solsys/, render.py
  • commit-msg — enforces the commit message rules below

Commit message rules

First line must match:

type(SOLSYS): subject
type(SOLSYS-123): subject
Part Rule
type One of feat, fix, chore, docs, clean
Scope SOLSYS or SOLSYS-<ticket> (digits only)
Subject Required non-empty text after :

Examples:

feat(SOLSYS): add light/dark static themes
fix(SOLSYS-42): correct Hilda resonance rate
docs(SOLSYS): document commit message rules
chore(SOLSYS): bump ruff
clean(SOLSYS): remove unused Pluto study script

Merge / revert / fixup / squash commits are allowed through unchanged.

Manual checks:

.venv/bin/pre-commit run --all-files
.venv/bin/ruff format animate static solsys render.py
.venv/bin/ruff check animate static solsys render.py
.venv/bin/radon cc animate static solsys render.py -s -a
.venv/bin/python -m unittest discover -s tests -v

Render everything (~several minutes for animations):

export MPLBACKEND=Agg
.venv/bin/python render.py all

Or render by product:

.venv/bin/python render.py animate --dimension all
.venv/bin/python render.py animate --dimension 3d
.venv/bin/python render.py animate --system alpha_centauri
.venv/bin/python render.py animate --system sol_centauri
.venv/bin/python render.py animate --system barnards_star
.venv/bin/python render.py animate --system trappist_1
.venv/bin/python render.py animate --system tabbys_star
.venv/bin/python render.py animate --system interstellar
.venv/bin/python render.py animate --system interstellar --object borisov
.venv/bin/python render.py animate --system oumuamua
.venv/bin/python render.py static --dimension 2d
.venv/bin/python render.py neighborhood --ly 10

Alpha Centauri (issue #1) is one system_id covering A, B, and Proxima. Animations render to output/animate/alpha_centauri/:

  • alpha_centauri_ab_{light,dark}.gif — A–B binary close-up (±28 AU)
  • alpha_centauri_system_{light,dark}.gif — wide triple with Proxima (~8.7 kau)
  • proxima_planets_{light,dark}.gif — confirmed Proxima planets (via shared exoplanet_system animator)

Sol → Alpha Centauri cinematic (issue #10) flies from our solar system to the A–B close-up, zooms back out, then finishes on Proxima and its planets — all in Sol XYZ via SolCentauriFrameTransform. Animations render to output/animate/sol_centauri/:

  • sol_centauri_cinematic_{light,dark}.gif — Sol → AB → wide → Proxima planets

Barnard's Star (issue #15) is a nearby M dwarf (~6 ly) with four confirmed sub-Earth planets. Animations render via exoplanet_system to output/animate/barnards_star/:

  • barnards_star_planets_{light,dark}.gif — compact planets d, b, c, e

TRAPPIST-1 (issue #7) is a single-host ultracool dwarf (~40.7 ly) with seven confirmed planets. Animations render via exoplanet_system to output/animate/trappist_1/:

  • trappist_1_planets_{light,dark}.gif — compact resonant chain (b–h)

Tabby's Star (issue #17 / Boyajian's Star / KIC 8462852) has no confirmed planets. The scene visualizes the leading uneven circumstellar dust / debris explanation for its irregular Kepler dips (not a megastructure). Animations render to output/animate/tabbys_star/:

  • tabbys_star_dust_{light,dark}.gif — real Kepler LC (data/tabbys_star_lightcurve.csv); orbiting dust clumps of different sizes cross the LOS at observed dip times

ʻOumuamua–Earth flyby (issue #2) and interstellar visitors (issue #5) render from data/interstellar_objects.csv via InterstellarObjectCatalog to output/animate/interstellar_objects/:

  • {oumuamua,borisov,atlas}_{side,oblique}_{light,dark}.gif

CLI: render.py animate --system interstellar (all) or --object oumuamua|borisov|atlas. --system oumuamua remains as an alias for ʻOumuamua only.

Physics notes

  • Planet and asteroid positions use Keplerian ellipses (and a hyperbola for 'Oumuamua).
  • Asteroid / Kuiper / Oort fields use spherical shells in 3D; 2D is the XY projection.
  • Hildas follow a 3:2 resonance angular rate relative to Jupiter.
  • Jupiter Trojans and Greeks sit near the L4 / L5 Lagrange longitudes.
  • Moon orbits are exaggerated for visibility at solar-system zoom levels.
  • Coordinate frames (multi-star): Sol scenes use a heliocentric / Sol-barycentric frame in AU, with +X/+Y/+Z from the equatorial Cartesian mapping in OrbitCalculator.equatorialToCartesianAu (RA/Dec → XYZ). Alpha Centauri scenes use a separate α Cen AB-barycentric frame in AU, plotted face-on in the binary orbital plane (sky inclination stored in CSV but not applied to the 2D schematic). SolCentauriFrameTransform in solsys/physics/frame_transform.py maps between those frames: mass-weighted AB barycenter origin from nearby_stars_30.csv, and rotation from the Centauri orbital plane into Sol XYZ using the A/B (i, Ω) convention shared with OrbitCalculator.ellipticalPosition (toSol / toCentauri). The Sol → Centauri cinematic (animate/scenes/sol_centauri_cinematic.py, --system sol_centauri) consumes this API to place A/B in Sol XYZ while the camera travels from the neighborhood into the binary.

Roadmap

  • Additional star systems via SystemCatalog / data/systems.csv (exoplanet_system.py for planet disks; dedicated scenes for dust / other phenomena)
  • Blender-based planet close-ups / flybys in animate/scenes/blender/

About

This project visualizes the solar system from the inner planets out to the nearest stars, with a special focus on asteroids.

Topics

Resources

Stars

7 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages