Surface-Wave Dispersion Workflow
SeisGo’s dispersion module extracts group/phase velocity dispersion images from
seismic waveform gathers and computes synthetic dispersion curves via forward modeling.
Overview
Waveform gather (traces × samples)
│
▼
get_dispersion_image() ← phase-shift method (Park et al. 1998)
│
▼
Dispersion image (period × velocity)
│
▼
Pick dispersion curve manually or automatically
│
▼
forward_solver() ← synthetic dispersion from Vs model
Extracting a dispersion image
Phase-shift method
from seisgo import dispersion
import numpy as np
# g: 2-D array, shape (n_traces, n_samples)
# t: time vector (s), may be two-sided (negative and positive lags)
# d: distance vector (km), one entry per trace
dimage, velocities, periods = dispersion.get_dispersion_image(
g,
t,
d,
pmin=5, # minimum period (s)
pmax=30, # maximum period (s)
vmin=2.0, # minimum phase velocity (km/s)
vmax=5.0, # maximum phase velocity (km/s)
dp=1, # period increment (s)
dv=0.05, # velocity increment (km/s)
plot=True,
)
dimage shape depends on the time-series polarity:
Two-sided (
tspans negative to positive): returns array of shape(2, n_periods, n_velocities)with index 0 = negative lag, index 1 = positive lag.One-sided: returns
(n_periods, n_velocities).
Picking the best velocity per period
dimage, velocities, periods, best_v = dispersion.get_dispersion_image(
g, t, d,
pmin=5, pmax=30, vmin=2.0, vmax=5.0,
get_best_v=True,
plot=True,
)
Narrowband filtering
Generate a suite of narrowband-filtered waveforms (useful for visual group-velocity analysis):
from seisgo import dispersion
filtered_waveforms, period_vector = dispersion.narrowband_waveforms(
trace, # 1-D array
dt=0.05, # sampling interval (s)
pmin=5,
pmax=30,
dp=1,
pscale="ln", # "ln" (linear) or "nln" (logarithmic)
extend=10, # extra periods for filter roll-off
)
CWT-based dispersion waveforms
filtered_cwt, freq_vector = dispersion.get_dispersion_waveforms_cwt(
trace,
dt=0.05,
fmin=0.03,
fmax=0.2,
dj=1/12,
wvn="morlet",
)
Forward modeling (synthetic dispersion)
Compute Rayleigh or Love wave dispersion curves for a layered Vs model using surf96:
from seisgo import dispersion
import numpy as np
vs = np.array([1.8, 2.5, 3.2, 3.8]) # Vs per layer (km/s)
thickness = np.array([5.0, 10.0, 15.0, 0.0]) # layer thickness (km); 0 = half-space
periods = np.arange(5, 35, 1) # target periods (s)
group_vel = dispersion.forward_solver(
vs,
periods,
thickness,
wave_type="rayleigh",
mode=1,
velocity_type="group",
)
forward_solver internally maps Vs → Vp (using a Vp/Vs ratio of √3) and
density (using an empirical Birch’s law approximation), then calls surf96.
Energy computation options
The energy_type parameter in get_dispersion_image controls how peak energy is measured
in each velocity–period cell:
Option |
Description |
|---|---|
|
Sum of squared amplitudes in the travel-time window (default) |
|
Maximum of the Hilbert envelope |
Plotting tips
import matplotlib.pyplot as plt
plt.figure(figsize=(8, 5))
plt.imshow(
dimage.T,
extent=[periods[0], periods[-1], velocities[0], velocities[-1]],
origin="lower",
aspect="auto",
cmap="jet",
)
plt.colorbar(label="Normalized energy")
plt.xlabel("Period (s)")
plt.ylabel("Phase velocity (km/s)")
plt.show()
See also
Simulation API — 1-D finite-difference acoustic modeling