Development documentation · 0.2.7 12b76261 · Intro examples tested with 0.2.4 · Version details · Known limitations

Case Study: Event-Synchronized Analysis#

This case study demonstrates an event-synchronized analysis workflow using synthetic data: defining analysis windows around candidate trigger timestamps, associating raw time series with each segment, and generating summary inspection plots via SegmentTable.apply().

Candidate triggers are represented by simulated event metadata (GPS trigger time and detection SNR from an upstream search pipeline). Note that the SNR column here represents pre-computed trigger metadata rather than an online matched-filter SNR computed from the raw waveform.

The event windows are represented by gwpy.segments.Segment, while gwexpy provides table management, series-column association, and batch processing through SegmentTable. The division between GWpy base classes and gwexpy extensions is the same as in SegmentTable: Basics.

import warnings

with warnings.catch_warnings():
    import numpy as np
    import pandas as pd
    from gwpy.segments import Segment
    from gwexpy.table import SegmentTable
    from gwexpy.timeseries import TimeSeries
    # 1. Candidate event triggers from an upstream detection pipeline (synthetic)
    # The table stores GPS trigger times and detection SNR metadata.
    events_df = pd.DataFrame({
        "gps": [1234567890.1, 1234567895.5, 1234567900.2],
        "snr": [15, 8, 22]
    })

    # 2. Create SegmentTable from events
    # Define a 4-second window around each GPS time
    segs = [Segment(t - 2, t + 2) for t in events_df["gps"]]
    st = SegmentTable.from_segments(segs, snr=events_df["snr"])

    # 3. Attach a synthetic raw TimeSeries to each event segment
    raw_series = []
    fs = 256
    for t, snr in zip(events_df["gps"], events_df["snr"]):
        t_arr = np.linspace(t - 2, t + 2, 4 * fs, endpoint=False)
        burst = (snr / 10.0) * np.exp(-((t_arr - t) / 0.1) ** 2) * np.sin(2 * np.pi * 50 * (t_arr - t))
        noise = np.random.default_rng(int(t * 10)).normal(0, 0.2, len(t_arr))
        raw_series.append(TimeSeries(burst + noise, t0=t - 2, dt=1 / fs, unit="V"))
    st.add_series_column("raw", raw_series)
    st
/home/runner/micromamba/envs/gwexpy/lib/python3.11/site-packages/gwpy/time/_ligotimegps.py:42: UserWarning: Wswiglal-redir-stdio:

SWIGLAL standard output/error redirection is enabled in IPython.
This may lead to performance penalties. To disable locally, use:

with lal.no_swig_redirect_standard_output_error():
    ...

To disable globally, use:

lal.swig_redirect_standard_output_error(False)

Note however that this will likely lead to error messages from
LAL functions being either misdirected or lost when called from
Jupyter notebooks.

To suppress this warning, use:

import warnings
warnings.filterwarnings("ignore", "Wswiglal-redir-stdio")
import lal

  from lal import LIGOTimeGPS

Batch Plot Generation#

We can use apply() to generate plots for each event and save them, storing the paths back in the table.

import os
import matplotlib.pyplot as plt
from IPython.display import Image, display

os.makedirs("outputs", exist_ok=True)

def generate_event_plot(row):
    path = f"outputs/event_{row.index}.png"
    fig, ax = plt.subplots(figsize=(6, 2.5))
    ts = row["raw"]
    ax.plot(ts.times.value, ts.value, color="tab:blue", lw=0.8, label="Signal")
    seg = row["span"]
    snr = row["snr"]
    center = (seg[0] + seg[1]) / 2
    ax.axvline(center, color="red", linestyle="--", lw=1.2, label=f"Event (SNR={snr})")
    ax.set(
        xlabel="GPS Time [s]",
        ylabel=f"Signal [{ts.unit}]",
        title=f"Event {row.index} Window (SNR={snr})",
        xlim=(seg[0], seg[1]),
    )
    ax.legend(loc="upper right")
    fig.tight_layout()
    fig.savefig(path)
    plt.close(fig)
    return {"plot_path": path}

st_plots = st.apply(generate_event_plot)
st_plots.display()

display(Image("outputs/event_0.png"))
../../_images/8c983eeba5021d97bdffa893544944324bdcf24106b23133ce9c45c15b5bd9f4.png

Result Summary#

Finally, we can filter the table and export results.

st_best = st_plots.select(mask=st_plots.to_pandas()["snr"] > 10)
display(st_best.to_pandas())

fig = st_best.hist(column="snr")
span snr plot_path
0 (1234567888.1, 1234567892.1) 15 outputs/event_0.png
1 (1234567898.2, 1234567902.2) 22 outputs/event_2.png
../../_images/d2fe3d4e19091d15f0fcec2aa87fbcf4f498899d9dd4e8fe0266b3d30bfc890b.png