shake_movie
Public-facing earthquake videos from SW4 ground-motion simulations, for QuakeCoRE's outreach channel. One command turns a finished SW4 run into a 1080p MP4 with no per-event settings, so the realtime simulation workflow can render, and later upload, a movie for every earthquake it simulates.
shake-movie SW4_INPUT REALISATION [--output MOVIE.mp4]
Next to the movie it writes MOVIE.json with the title, place, date,
magnitude and a description for the upload.
What it reads
Everything comes from files a workflow run already has. The SW4 input file says where the rest is:
| File | From | Used for |
|---|---|---|
topo image (z = 0, cycle 0) |
SW4 imagehdf5 mode=topo |
Terrain mesh and hillshade |
surf_mag images (z = 0, every 0.5 s) |
SW4 imagehdf5 mode=mag |
Shaking, interpolated in time to the frame rate |
surf_hmax image (z = 0, end) |
SW4 imagehdf5 mode=hmax |
Strongest shaking map |
SRF (rupturehdf5) |
the SRF SW4 ran | Fault trace, rupture timing, epicentre |
| Realisation JSON | the workflow | Magnitude, simulated domain, coastline |
The workflow's defaults already write these images. SW4 driven by an SRF slip
rate outputs velocity where its modes say displacement, so mag is ground
velocity and hmax peak horizontal ground velocity. Velocity becomes
intensity through Worden et al. (2012).
The grid is placed on the map exactly as SW4 places it: the PROJ string is
rebuilt the way SW4 assembles it from the grid command. That includes
passing scale=0.9996 through as +scale, which PROJ ignores for tmerc, so
SW4's grid has an effective scale factor of 1. The test fixtures are real SW4
output, and the placement matches SW4's own lat/lon images to float32
rounding (under 1 m).
Look
- Terrain: a muted hypsometric tint from a lowland green, with a baked hillshade and 2x vertical exaggeration. Land and sea come from the coastline, never from elevation: NZCVM stores the sea as 0 m, the same height as much of the Canterbury Plains. Lagoons such as Te Waihora are found as large 0 m patches inside the coastline.
- Shaking: a warm-only ramp ("Ember") that cannot be mistaken for water, see-through below "Weak" and faint over the sea. The legend uses GeoNet's public words: Weak, Light, Moderate, Strong, Severe, Extreme.
- Fault: drawn grey, turning white as it ruptures ("Fault rupturing").
- Ending: a north-up map of the strongest shaking in stepped bands, with the word for each town's shaking printed under its name.
Camera
Every shot is worked out from the rupture and the shaking (camera.py):
- Look across the fault from the side where more people live, keeping north within 60 degrees of screen-up. Point sources look north.
- Frame the ruptured part of the fault plus everywhere shaking at "Light" or above, padded 30%, at least 70 km across.
- Only ever pull back: the framed size is a running maximum.
- Smooth the path with look-ahead, then evaluate it at every frame through monotone splines. The camera glides rather than stepping at SW4's image interval.
- Ease the pitch from 40 to 55 degrees as the view widens, with a slow 12 degree drift for parallax.
The movie runs: a 4 s title over the whole domain, a 2 s dive to the epicentre, the simulation in real time, a 3 s tilt up to the map, and a 6 s hold.
Names
Titles read like "Thursday 26th March Mw 6.3 earthquake". For a realisation
named by a GeoNet public ID (as the realtime workflow names them), the date
(NZ time) and the place ("5 km west of Masterton") come from
GeoNet's quake API. Scenarios have no date, and
their place comes from Nominatim reverse geocoding
("Hurunui District, Canterbury"). Neither needs a key; a movie makes at most
one request to each, identified by this tool's User-Agent. Offshore, or
without a network (--offline), the place is given relative to the nearest
sizeable town in the vendored town list.
Rendering on CPUs
VTK renders off-screen through Mesa (EGL or OSMesa, llvmpipe) where there is
no GPU, as on HPC nodes. The terrain texture is uploaded once per worker, and
each frame only swaps a small shaking texture on a second copy of the terrain.
Mesh size dominates the cost, so a coarser mesh takes over once the camera is
more than 180 km out. Frames are split across worker processes (--workers,
by default the CPUs available) and piped straight into ffmpeg, one segment
each, then joined without re-encoding.
The container needs ffmpeg and Mesa (libegl1 libegl-mesa0 libgl1-mesa-dri, or libosmesa6).
Data
- Coastline: the velocity model's nzcvm coastline when the realisation names
one that exists. Otherwise LINZ NZ Coastlines and Islands Polygons
(Topo 1:150k), CC BY 3.0 NZ,
downloaded once to
~/.cache/shake_movie. - Towns (
shake_movie/nz_places.csv): cities, towns and villages with a population from OpenStreetMap, © OpenStreetMap contributors, ODbL 1.0. - Places and dates: GeoNet and OpenStreetMap Nominatim, as above.
The final map credits SW4, LINZ and OpenStreetMap.
Development
uv sync --all-extras --dev
uvx lefthook install
uv run pytest
The render tests need ffmpeg and an OpenGL driver (Mesa is enough), and skip
without them. tests/fake_sw4.py writes files in SW4's layouts for building
test runs.
Metadata
Release files for shake-movie 2026.10.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| shake_movie-2026.10.1.tar.gz | 209.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| shake_movie-2026.10.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 261.1 kB
Release files / shake_movie-2026.10.1.tar.gz
| Download URL | shake_movie-2026.10.1.tar.gz |
|---|---|
| Size | 209.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
76dd87259dff5eea3a41646ef0df89c9ada6738d45acdcc66877846d49e22cc2
|
|
BLAKE2b-256 checksum How to use checksums |
e8512f71bba159eb7af4796c28fa4cb4dd61d8f1b7ccbd69f3edcd4826c62f24
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.
Transparency logRelease files / shake_movie-2026.10.1-py3-none-any.whl
| Download URL | shake_movie-2026.10.1-py3-none-any.whl |
|---|---|
| Size | 51.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3789b87728ffc0a57de246c885bc4104083e329442c222dd9e463c2b7d60513c
|
|
BLAKE2b-256 checksum How to use checksums |
22449fdaa1110bdee702ef1740ffa2305d5ed304d968ca69e3f4d465d06549fd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.
Transparency log