Note

This page was generated from a Jupyter Notebook. Download the notebook (.ipynb)

[1]:
# Skipped in CI: Colab/bootstrap dependency install cell.

ASD Analysis: Pipeline๏ƒ

This tutorial demonstrates how to use SegmentTable for a batch ASD analysis pipeline. We will crop data for each segment, compute ASDs, and visualize the variation.

The segment windows are still gwpy.segments.Segment, and the waveform payload in each row is a GWpy TimeSeries. gwexpy extends that GWpy base-class setup by placing the rows in SegmentTable and applying crop() and asd() across the whole table at once. For the core relationship between GWpy base classes and gwexpy extensions, see SegmentTable: Basics.

[2]:
import warnings

warnings.filterwarnings("ignore", category=UserWarning)
warnings.filterwarnings("ignore", category=DeprecationWarning)

import warnings

with warnings.catch_warnings():
    warnings.simplefilter('ignore')

    import numpy as np
    from gwpy.segments import Segment
    from gwpy.timeseries import TimeSeries

    from gwexpy.table import SegmentTable

    def get_synthetic_data(t0):
        return TimeSeries(np.random.randn(1024), sample_rate=64, t0=t0)

    segs = [Segment(i*16, i*16+16) for i in range(4)]
    st = SegmentTable.from_segments(segs)
    st.add_series_column("raw", data=[get_synthetic_data(seg[0]) for seg in segs], kind="timeseries")
    st

Crop and ASD๏ƒ

We can use sugar APIs like crop() and asd() to process all segments at once.

[3]:
# Cut the data to each segment span so every ASD is computed from intervals that share the same operating state.
st_cropped = st.crop("raw", out_col="cropped")
# Estimate ASD per segment to compare stationary noise floors without smearing glitches or state changes across the whole run.
st_asd = st_cropped.asd("cropped", out_col="asd", fftlength=2.0)
st_asd.display()

[3]:
span raw cropped asd
0 (0, 16) <timeseries: 1024 samples> <timeseries: 1024 samples> <frequencyseries: 65 bins>
1 (16, 32) <timeseries: 1024 samples> <timeseries: 1024 samples> <frequencyseries: 65 bins>
2 (32, 48) <timeseries: 1024 samples> <timeseries: 1024 samples> <frequencyseries: 65 bins>
3 (48, 64) <timeseries: 1024 samples> <timeseries: 1024 samples> <frequencyseries: 65 bins>

Multi-channel Summary๏ƒ

You can map custom functions (like calculating band RMS) using map().

[4]:
def calc_rms(fs):
    return np.sqrt(np.sum(fs.value**2))  # Simplified band-integrated amplitude proxy for comparing segment-to-segment loudness.

st_asd.map("asd", calc_rms, out_col="band_rms", inplace=True)
st_asd.display()

[4]:
span band_rms raw cropped asd
0 (0, 16) 1.425641 <timeseries: 1024 samples> <timeseries: 1024 samples> <frequencyseries: 65 bins>
1 (16, 32) 1.395076 <timeseries: 1024 samples> <timeseries: 1024 samples> <frequencyseries: 65 bins>
2 (32, 48) 1.382460 <timeseries: 1024 samples> <timeseries: 1024 samples> <frequencyseries: 65 bins>
3 (48, 64) 1.437775 <timeseries: 1024 samples> <timeseries: 1024 samples> <frequencyseries: 65 bins>