Black Hole Shadows

Colorful ray-trace image of Black Hole

Black Hole Shadows is a Python ray tracer. It calculates the shadow of a black hole and the gravitational-lensing image of the sky behind it. The physics comes from my paper on arXiv (1912.08833). The code is open source on GitHub.

The original code was research code: dozens of files, thousands of lines of scientific code, many duplicated functions and almost no comments. I gave it to Claude Code with one prompt and asked it to organize the code again. Then I continued to develop it with Claude.

What it calculates

The code sends one light ray for each pixel, from the observer back to the sky. For each ray it integrates the null geodesic equations near the black hole. Each ray ends in one of these states:

  • the ray falls into the black hole (the shadow),
  • the ray hits the thin disk of matter,
  • the ray escapes to the sky (the lensed background).

The final image colours each pixel by this result.

Two spacetimes

  • Schwarzschild black hole with a thin, massive disk (Weyl coordinates, Morgan-Morgan disk). The disk mass MD changes the shadow. The code builds a lambda lookup table once and caches it. With MD = 0 this is the usual Schwarzschild black hole.
  • Kerr black hole (a black hole that turns), in Boyer-Lindquist coordinates. The spin a moves and flattens the shadow. This path needs no lookup table.

How it works

  • Stack: Python, uv, numpy, scipy, matplotlib and numba. ruff and mypy check the code.
  • Numerics: an adaptive Runge-Kutta-Fehlberg (RKF45) integrator, compiled with numba and run in parallel with prange.
  • One command: uv run bh-shadow config.toml traces, saves and plots one case. Each run writes its own folder with an outputs.npz file and a run.json with all parameters.

How it was built

The project started as an experiment: can Claude organize old, disorganized scientific code from a single prompt? The prompt told Claude what was probably wrong or deprecated with the code, what must not change (the numba functions), and that it must not use other information about black holes. An architect agent made the plan, and other agents made the changes.

The first pass removed approximately 4,900 lines and split the physics by spacetime, and the script was running after many years. Later sessions added some improvements, but the core was performed with one prompt.

I wrote about this experiment in a blog post: Can Claude organize old research code? A black hole shadows test.

Links

Code

github.com/neiro-data/Black-Holes-Shadows

Paper

Paper: arXiv:1912.08833