Skip to content
CHIME/FRBPublic data

Tutorials

Working with
CHIME/FRB data.

Every catalog on this site can be queried through a public API or downloaded as files. These Python examples cover both, along with the raw data behind the catalogs.

Waterfall of FRB 20181222A, from 800 to 500 MHz over about 70 milliseconds: its bright parts drift from about 715 to 665 MHz within 20 milliseconds.
FRB 20181222AA burst from the repeating source FRB 20180916B, drawn from its waterfall in Catalog 2.

Public API

Query the API

Read-only JSON over HTTPS for every published catalog. No key or sign-up needed.

Open /api/v1 (opens in a new tab)
EndpointReturns
/api/v1Every endpoint and its parameters.
/api/v1/catalogsEvery catalog, with its DOI, papers, versions and row counts.
/api/v1/catalogs/{catalog}One version of a catalog: its columns with units and descriptions, its files and its row counts.
/api/v1/catalogs/{catalog}/burstsThe rows, one per burst or sub-burst (per source in the Repeaters Catalog), a page at a time: follow links.next until it is null.
/api/v1/catalogs/{catalog}/bursts/{name}Every row of one burst, its plots and its neighbours. The name matches in any case or spacing.

01List the catalogs

Each catalog comes with its DOI, papers, versions and row counts. Its id (catalog2, basecat1, repeaters, catalog1) goes in the other endpoints.

Python
import requests

API = "https://chime-frb.ca/api/v1"

catalogs = requests.get(f"{API}/catalogs").json()["catalogs"]
for catalog in catalogs:
    print(catalog["id"], catalog["latest_version"])

02Filter and sort bursts

The ten bursts with the highest dispersion measure, with only the columns needed. Every column key is in the catalog’s glossary.

Python
import requests

API = "https://chime-frb.ca/api/v1"

response = requests.get(
    f"{API}/catalogs/catalog2/bursts",
    params={
        "fields": "ra,dec,dm_fitb",
        "sort": "dm_fitb",
        "order": "desc",
        "per_page": 10,
    },
)
response.raise_for_status()
for row in response.json()["rows"]:
    print(row["tns_name"], row["dm_fitb"])
ParameterMeaning
qSearch burst names, event IDs, repeater names and previous names.
viewall (default), repeat or one-off.
sortA column key to sort by. Missing values sort last.
orderasc (default) or desc.
pagePage number, from 1 (the default).
per_pageRows per page, up to 1,000 (default 100).
fieldsColumn keys to return, separated by commas. Keys that name the row, such as tns_name and sub_num, always come too.
versionA catalog version, e.g. 20251231. Without it, the latest; each catalog lists its versions.

03Fetch a whole catalog

Rows come a page at a time: follow links.next until it is null. Naming a version, here 20251231, keeps an analysis reproducible, since older versions stay available when a new one is published.

Python
import pandas as pd
import requests

API = "https://chime-frb.ca/api/v1"

# Pin the version so results stay the same when a new one is published.
url = f"{API}/catalogs/catalog2/bursts?version=20251231&per_page=1000"
rows = []
while url:
    page = requests.get(url).json()
    rows += page["rows"]
    url = page["links"]["next"]

bursts = pd.DataFrame(rows)
print(len(bursts), "rows")  # one per burst or sub-burst

04Look up one burst

Every row of FRB20180725A (one per sub-burst), its plots, and links to the bursts before and after it. Names match whatever their case or spacing, so frb 20180725a works too.

Python
import requests

API = "https://chime-frb.ca/api/v1"

burst = requests.get(f"{API}/catalogs/catalog2/bursts/FRB20180725A").json()
print(burst["rows"][0]["dm_fitb"])  # one row per sub-burst

# Save its plots
for plot in burst["plots"]:
    with open(f"FRB20180725A_{plot['key']}.png", "wb") as file:
        file.write(requests.get(plot["url"]).content)

Values are exactly as published. Missing values are null, or empty strings in text fields such as notes; Baseband Catalog 1 marks missing measurements -9999.

Errors come back as JSON with a status and a message: 400 for a parameter the API doesn’t understand, 404 for an unknown catalog, version, burst or endpoint, and 503 if the database is briefly unavailable. Try again shortly.

Downloads

Read the catalog files

Each catalog page offers its files under Downloads. Catalog 2 comes as CSV, JSON, FITS and NumPy; the other catalogs work the same way, with their own file names.

01Find the files

The API lists each version’s files, so scripts can fetch them.

Python
import requests

API = "https://chime-frb.ca/api/v1"

catalog = requests.get(f"{API}/catalogs/catalog2").json()
for file in catalog["downloads"]:
    print(file["format"], file["url"])

02Read them in Python

Each tab reads the same Catalog 2 table into Python. Missing measurements are NaN in the files.

import pandas as pd

bursts = pd.read_csv("chimefrbcat2.csv")
print(bursts[["tns_name", "ra", "dec", "dm_fitb"]].head())

# Bursts from repeating sources have a repeater name
repeats = bursts[bursts["repeater_name"].notna()]
print(repeats["repeater_name"].nunique(), "repeating sources")

Raw data

Work with raw data

Each catalog’s raw data, such as waterfalls, localizations and baseband data, is archived permanently at the Canadian Astronomy Data Centre (CADC), where the catalog’s DOI points. Browse an archive, download the files you need, then open them as below.

01HDF5 files

Waterfalls, localizations and baseband data usually come as HDF5 files, ending in .h5. visit lists what a file holds; then read the datasets you need. This waterfall file keeps its dynamic spectrum in frb/wfall and its plot limits in frb/extent, as in the CHIME/FRB Open Data waterfall tutorial (opens in a new tab).

Python
import h5py
import matplotlib.pyplot as plt

with h5py.File("FRB20180725A_waterfall.h5", "r") as file:
    file.visit(print)  # every group and dataset in the file
    wfall = file["frb/wfall"][:]  # intensity, frequency × time
    extent = file["frb/extent"][:]  # the plot's time and frequency limits

plt.imshow(wfall, aspect="auto", interpolation="none", extent=extent)
plt.xlabel("Time [ms]")
plt.ylabel("Frequency [MHz]")
plt.show()

02Pickle files

Some localization files are pickled Python dictionaries, with the confidence map in Z and its limits in extent. This example comes from the previous public site.

Python
import pickle

# Unpickle only files you trust: loading a pickle can run code.
with open("localization_contour.pkl", "rb") as file:
    localization = pickle.load(file)

print(list(localization.keys()))
# ['event_id', 'Z', 'extent', 'results']

print(localization["Z"])  # 2D array of confidence values

Other formats, such as msgpack intensity data and filterbank files, are described in the CHIME/FRB Open Data documentation (opens in a new tab), alongside tutorials for exposure maps, the beam model, injections and VOEvents, and the cfod Python package (opens in a new tab).

Help

Get help

Using the data in a paper? Please cite the catalog papers.