Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

gwbpy

Gravitational-wave and pulsar visualization for Blender.

Status: alpha (0.1.0a3). Expect rough edges. Pre-release on PyPI.

What it does

  • animate_binary_physical(): two bodies (black holes or neutron stars) that spiral together and merge, driven by SEOBNRv5HM effective-one-body dynamics, or that sit on a steady circular orbit (for continuous-wave sources).
  • animate_gw_polarization(): a ring, or a tube of rings, of free test particles deformed by a gravitational wave. Linked to a circular binary, or standalone.
  • animate_pulsar(): a spinning neutron star with lighthouse beams, optionally aimed at an observer.
  • animate_pta(): several pulsars around one observer (optionally textured as the Earth), with pulses traveling along the lines of sight. With a circular binary in the scene, its gravitational wave shifts the pulse arrival times.
  • plot_residuals(): one pulsar's timing residuals as a matplotlib image next to the PTA, facing the camera.
  • animate_spacetime(): a rubber-sheet picture of a binary: a grid sheet with a dent under each body and ripples spreading out from it.
  • frame_scene(), camera_tour(), camera_orbit(), camera_targets(): put the camera on any part of the scene, fly between parts, or circle them.

Each function documents its options: in Blender's Python console, run help(gwbpy.animate_pta) and so on. The console also prints what it did, including warnings, so keep Window > Toggle System Console open.

Tested on

  • Blender 5.0 on Windows, with Ubuntu 24.04 under WSL2
  • The physics-environment setup script on Ubuntu 24.04

Not tested: macOS, other Linux distributions, Windows without WSL, and installing the PyPI release into Blender's own Python.

What needs the physics environment

Inspiral binaries (animate_binary_physical(..., inspiral=True), the default) and plot_residuals(). Blender's Python cannot run these libraries, so gwbpy builds a separate Python 3.11 environment at ~/.gwbpy/dynamics-env (inside WSL on Windows) with pyseobnr and lalsuite (which pyseobnr requires, and which brings matplotlib). Calls run a small worker there, read the result back, and keyframe it. Everything else (circular binaries, rings, pulsars, PTA scenes, spacetime sheets and the camera) runs in Blender's own Python with numpy, with no setup step.

Install

  1. Get the gwbpy folder where Blender can import it. The route that has been tested is to put the folder somewhere on disk (a wheel from PyPI is a zip file, so you can unpack one) and add its parent folder to Blender's path, in the Scripting tab:

     import sys
     sys.path.insert(0, r"PATH_TO_FOLDER_CONTAINING_gwbpy")
     import gwbpy
    
  2. For inspiral binaries only, install system packages once, in a Linux or WSL terminal:

     sudo apt update && sudo apt install -y python3-venv libgsl-dev swig build-essential libfftw3-dev libhdf5-dev
    
  3. Then build the physics environment, once:

     gwbpy.setup()
    

    The first run builds from source and takes about 10 minutes. Blender may look frozen meanwhile. If system packages are missing, setup stops and prints the exact command to run. Use gwbpy.setup(force=True) to rebuild.

Examples

A merging pair of black holes:

gwbpy.animate_binary_physical(m1=30, m2=15, merge_frame=100, frames=200,
                              f_lower=80.0, meters_per_unit=20000.0)

A neutron star and a black hole (m1 is the black hole for "BHNS"):

gwbpy.animate_binary_physical(m1=5, m2=1.4, system="BHNS", f_lower=300,
                              merge_frame=250, meters_per_unit=500.0)

A steady circular binary with two polarization rings around it:

gwbpy.animate_binary_physical(m1=30, m2=30, inspiral=False,
                              initial_separation_km=2000, period_frames=60,
                              frames=240, meters_per_unit=300000.0)
gwbpy.animate_gw_polarization(h=0.25, inclination_deg=0, name="face_on")
gwbpy.animate_gw_polarization(h=0.25, inclination_deg=90, name="edge_on")

A pulsar timing array whose pulses are shifted by that binary's wave, with a residual plot (the observer is in the binary's orbital plane, so it sees the binary edge-on):

gwbpy.animate_binary_physical(m1=30, m2=30, inspiral=False,
                              initial_separation_km=2000, period_frames=100,
                              frames=400, meters_per_unit=300000.0,
                              body_scale=3.0)
res = gwbpy.animate_pta(observer_position=(35, 0, 0), distance=8,
                        period_frames=10, gw_shift_frames=4,
                        travel_frames=38, pulsar_radius=0.4,
                        observer_size=1.0, observer_texture="earth")
gwbpy.plot_residuals(res, pulsar=0)

A rubber-sheet picture of an inspiral, with the camera kept inside the sheet:

gwbpy.animate_binary_physical(m1=30, m2=15, merge_frame=200, frames=260,
                              f_lower=40.0, meters_per_unit=20000.0)
gwbpy.animate_spacetime(size=80, resolution=100, dent_depth=14.0,
                        dent_width=3.0, ripple_height=2.0)
gwbpy.frame_scene("binary", view="iso", margin=1.5, hide_edges=True)

A camera move from the binary to the PTA:

gwbpy.camera_tour([("binary", 1, "iso"), ("pta", 200, "iso")],
                  transition=80, margin=1.5)

What is physics and what is not

Binary (inspiral=True)

  • Orbital separation and phase come from the SEOBNRv5HM effective-one-body dynamics. Separation is the EOB radial coordinate, not a literal horizon position. Non-spinning only.
  • Black holes are drawn at their Schwarzschild radius. Neutron stars are drawn at a fixed radius (ns_radius_km, default 12 km), and their glow is styling.
  • For systems with neutron stars the orbit still comes from a binary-black-hole model, stopped at contact. Tides, disruption and matter effects are not modeled.
  • Time is stretched; the slowdown factor is printed. If the data end slightly short of contact, a short schematic closing step finishes the merger; it is a visual stand-in, and the ringdown of the bodies is not modeled (close_merger=False removes it).
  • The (2,2) mode of the strain is saved with the orbit and aligned with it (the worker prints the clock fit and phase agreement). Other modes are ignored.

Circular binary (inspiral=False)

  • Newtonian Kepler orbit with no decay. A warning is printed below about 10 M.

Polarization ring

  • Leading-order quadrupole radiation from a circular binary, transverse-traceless gauge, first order in the strain. The strain is greatly exaggerated (the console prints the factor); real strains are of order 1e-21.
  • The phase offset between the ring and the orbit follows a hand derivation and has not been checked against a reference.
  • The tube length and wave delay are a cartoon. Inspiral binaries are not supported yet.

Pulsar and PTA

  • The lighthouse geometry is real; the rest is a cartoon. Spin periods, light travel times and distances are not to scale, the beams are opaque cones, and the signals are uniform stylized spikes (or spheres).
  • With a circular binary in the scene, its wave shifts each pulse's arrival time using the standard timing formula (Earth term and pulsar term), derived by hand. The code is checked against a direct integration of the light travel time and against the Hellings-Downs curve for the Earth term. The pulsar term and the overall sign have not been checked against a published reference. The shifts are hugely exaggerated; their relative sizes follow the real geometry.
  • The pulsars do not move. Positions of pulses in flight are a cartoon; the arrival times at the observer are the observable (see plot_residuals).
  • A PTA listens at nanohertz to supermassive binaries; the circular binary on screen is a stand-in.

Spacetime sheet

  • The ripples are the (2,2) strain of the binary in the orbital plane: analytic for a circular binary, from the model for an inspiral. They give a two-armed spiral that follows the chirp, with amplitude falling as 1/distance. The height is a picture of that pattern, not a physical displacement, and is exaggerated. The wave speed is a visual choice. The pattern is faded out inside the orbit.
  • The dents are the rubber-sheet analogy, not spacetime curvature. Depth is proportional to mass, and on a flat sheet the spheres of a binary with different masses cannot all rest at the bottom of their dents (the console says by how much they hover).

Not modeled anywhere: spin, precession, eccentricity and higher modes.

Known limits

  • SEOBNRv5HM never starts closer than a separation of 10 M. A requested start frequency above about 2044 / (m1 + m2) Hz (masses in solar masses) is lowered to that value, and a note is printed, so every run has at least about 5 orbits.
  • Systems with long inspirals (for example two neutron stars from tens of Hz) are refused above max_orbits, since they alias and create huge numbers of keyframes.
  • If the console warns about more than half a turn per frame, the motion will look aliased. Raise merge_frame, or use a higher f_lower.
  • The spacetime sheet stores one shape key per frame. The console prints the cost first, and the function refuses above max_cost. Large sheets over long clips are slow to build and to play.
  • hide_edges works from the flat outline of the sheet, never zooms out, and cannot help for views that look toward the sheet's horizon (it says so).
  • Colors, glow and images show in Material Preview or renders, not in the Solid viewport.

Image credits

The Earth texture bundled with gwbpy (gwbpy/textures/earth.jpg, used with observer_texture="earth") is "Equirectangular Projected Earth for LARGEST" (https://svs.gsfc.nasa.gov/3615/): NASA/Goddard Space Flight Center Scientific Visualization Studio. The Blue Marble Next Generation data is courtesy of Reto Stockli (NASA/GSFC) and NASA's Earth Observatory. The look was art-directed for a film, so it is not a scientific rendering. This use does not imply NASA endorsement. Check NASA's media usage guidelines before redistributing it separately.

Citing

pyseobnr asks that results made with it acknowledge the software and the model papers:

  • Mihaylov et al., "pySEOBNR: a software package for the next generation of effective-one-body multipolar waveform models", arXiv:2303.18203
  • Pompili et al., "Laying the foundation of the effective-one-body waveform models SEOBNRv5", arXiv:2303.18039

For the polarization pictures, M. Isi, "Parametrizing gravitational wave polarizations" (2022) and its animations at https://maxisi.github.io/gwpols/ (CC-BY-SA 4.0) are a good reference, and for the quadrupole formulas see Maggiore, Gravitational Waves, Vol. 1. For pulsar timing, see Estabrook and Wahlquist (1975), Detweiler (1979) and Hellings and Downs (1983).

Citations were copied or recalled by hand. Check them before use.

License

No license has been chosen yet. pyseobnr, which the physics environment installs, is GPL-3.0-or-later.

Metadata

Release files for gwbpy 0.1.0a3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for gwbpy 0.1.0a3
File Size Uploaded Provenance
gwbpy-0.1.0a3.tar.gz 588.1 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for gwbpy 0.1.0a3
File Interpreter ABI Platform
gwbpy-0.1.0a3-py3-none-any.whl Python 3 none any Details

Total release size: 1.2 MB

Release files / gwbpy-0.1.0a3.tar.gz

Download URL gwbpy-0.1.0a3.tar.gz
Size 588.1 kB
Tags Source
SHA-256 checksum
How to use checksums
7660b650de998de35004553d3ab34146f2a0c26518d6587f94087d29f3d20286
BLAKE2b-256 checksum
How to use checksums
2ba42aaf86430f7b9e65f97c77ed151214d73fced1f0c08901898a48ba7c0664
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / gwbpy-0.1.0a3-py3-none-any.whl

Download URL gwbpy-0.1.0a3-py3-none-any.whl
Size 590.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8e2a4babca6203aa37b2dc76b9e4cf08436933402085a7eb8523383af220d545
BLAKE2b-256 checksum
How to use checksums
a902337d37e696ee9df52da166c8dfc806c220092e9ce330993792bac6054632
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Security for gwbpy 0.1.0a3

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page