GWPaint (Gravitational-Wave Paint-by-Numbers) converts gravitational-wave Q-transform spectrograms into visually appealing, discrete grid representations — perfect for outreach, teaching, and printing fun posters.
Given a GPS time (the precise time used by the GW detectors, measured in seconds since January 6, 1980), GWPaint downloads publicly available gravitational-wave data for that moment. Once the data is fetched, GWPaint computes a Q-transform spectrogram and generates a “paint-by-numbers” style grid that you can visualize, color, and print.
If you’re new to some of these concepts:
- If you’re more familiar with UTC (regular calendar time), you can convert UTC to GPS time using this tool.
- A list of known gravitational-wave events and their GPS times can be found here.
- If you’re not familiar with Q-transforms, see this overview.
- For practical examples of generating Q-transforms from GW data, check out GWpy’s qscan tutorial.
Install directly from PyPI:
pip install gwpaintOr install locally for development:
git clone https://github.com/yourusername/gwpaint.git
cd gwpaint
pip install -e .Requires Python ≥ 3.9 and:
numpymatplotlibgwpyrequests-pelicangwdatafindscipyscikit-image
from gwpaint import GWPaintByNumbers
# Create a painter instance
painter = GWPaintByNumbers(
cmap_name="turbo",
n_colors=8,
grid_rows=32,
grid_cols=32,
page_size="A0"
)
# Process a gravitational-wave event (example GPS time for GW150914)
# Pick a detector of your choice eg. H1, L1, V1
# GWpaint will do everything else for you provided data is available at that time
painter.process_event(event_time=1126259462.423, ifo="H1")This runs the full pipeline, saving outputs to ./output.
Below is a walkthrough of the typical GWPaint workflow. Each step produces visualizations you can use for teaching, outreach, or printing.
The classic spectrogram — we typically start here to see the gravitational-wave signal. This is a high resolution cleaned up version of the event we want to visualize.
Demonstrates how parameters can make the spectrogram look noisier or smoother. Some options in GWPaint play around with the relative scaling of features and make the data look noisier or smoother. eg. vmin_percentile=5, vmax_percentile=95 appears more noisy than vmin_percentile=1, vmax_percentile=99. Lower powernorm_gamma generally makes the image noisier with powernorm_gamma=1.0 reproducing the original scaling.
How the spectrogram looks when discretized to few colors. This step can be controlled using grid_rows, grid_cols but also by parameters of the q-transform itself. We select a small number of colours to represent all variation.
The “paint-by-numbers” style grid derived from the spectrogram.
The same grid, now with the assigned colors for each discrete level.
Printable template for outreach or hands-on activities.
Shows the discrete color mapping for reference.
| Parameter | Default | Description |
|---|---|---|
cmap_name |
"turbo" |
Name of the matplotlib colormap to use for coloring the spectrogram/grid. Ignored if custom_colors is provided. |
n_colors |
8 |
Number of discrete colors in the grid. |
custom_colors |
None |
List of custom RGB or hex colors to use instead of a built-in colormap. |
custom_labels |
None |
Optional labels for the discrete colors. If not provided, labels are auto-generated (C0, C1, …). |
grid_rows |
32 |
Number of rows in the output paint-by-numbers grid. |
grid_cols |
32 |
Number of columns in the grid. |
output_dir |
"./output" |
Folder where all generated plots and templates are saved. |
page_size |
"A0" |
Page size for PDF outputs (A0, A1, A2, A3, A4, A5, LETTER). |
line_width |
6 |
Width of grid lines in the output plots. |
padding_cells |
1 |
Number of empty cells to pad around the grid. |
square_cells |
True |
If True, grid cells are forced to be square; otherwise stretched to fit page. |
qrange |
(8, 8) |
Q-transform range (min Q, max Q). |
frange |
(15, 512) |
Frequency range in Hz for the Q-transform. |
vmin_percentile |
5 |
Lower percentile of spectrogram intensity used for normalization. |
vmax_percentile |
95 |
Upper percentile of spectrogram intensity used for normalization. |
time_around_event |
(0.3, 0.15) |
Seconds before and after the event to include in the spectrogram. |
tres |
0.02 |
Time resolution of the Q-transform in seconds. |
fres |
0.2 |
Frequency resolution of the Q-transform in Hz. |
whiten |
True |
If True, whiten the data before computing the Q-transform. |
save_dpi |
100 |
Resolution (dots per inch) for saved plots. |
powernorm_gamma |
1.0 |
Gamma parameter for PowerNorm normalization of spectrogram intensity. |
truncate_cmap |
(0.0, 1.0) |
Fraction of the colormap to use (min, max). |
add_metadata |
False |
If True, adds custom metadata text to templates/reference plots. |
metadata_pos_in_template |
(0.445, 0.06) |
XY coordinates for metadata in template PDFs. |
metadata_event_name |
"" |
Text for metadata (e.g., event name) in template/reference plots. |
metadata_pos_in_reference |
(0.58, 0.01) |
XY coordinates for metadata in colored reference PDFs. |
If you use GWPaint for outreach, teaching, or research demonstrations, please cite it via Zenodo once it’s archived.
I’m happy to add features if there are requests for interactive or outreach-specific functionalities.
- Suggestions and feature requests are welcome!
- Please open an issue or submit a pull request on GitHub.
- GWPaint is open for creative and educational use — have fun!
GWPaint is released under the MIT License. See LICENSE for details.







