| title | WaveformModes Guide |
|---|---|
| nav_order | 6 |
{: .no_toc }
{: .no_toc .text-delta }
- TOC {:toc}
Class: nrcats.WaveformModes
Inherits from: sxs.WaveformModes (ndarray subclass)
Auto-generated API reference: For a complete method listing with signatures and docstrings, see API Reference → waveform.
WaveformModes is the central data object returned by all catalog get() calls. It stores
complex gravitational-wave strain multipole modes
Three construction paths are available. In normal usage you will not call these directly —
use the catalog get() method instead.
WaveformModes.load_from_h5(file_path, metadata=metadata_dict, verbosity=0)Reads amp_l{ell}_m{em}/X,Y and phase_l{ell}_m{em}/X,Y datasets. Interpolates all modes
onto a common uniform time grid. Returns a WaveformModes with shape (n_times, n_modes).
WaveformModes.load_from_targz(file_path, metadata=metadata_dict, verbosity=0)Reads ASCII .asc / .dat / .txt files (columns: time, real, imag) from inside
the archive. Missing modes are filled with zeros. Interpolates onto a uniform grid.
WaveformModes(raw_sxs_obj.data, raw_sxs_obj.time, sim_metadata=metadata_dict, **meta)Used internally by SXSCatalog.get(). The sxs.WaveformModes.data property may return a
memoryview; all arithmetic wraps it with np.array(..., dtype=complex).
get_mode() is the primary method for retrieving a scaled individual mode:
mode22 = wfm.get_mode(
2, 2,
total_mass=60.0, # M_sun
distance=100.0, # Mpc
delta_t_seconds=1./4096, # physical seconds (4096 Hz sampling)
)
# mode22 is a complex pycbc.types.TimeSeriesThe amplitude is scaled by
get_td_waveform() sums over all modes with spin-weight
pols = wfm.get_td_waveform(
total_mass=40., # M_sun
distance=100., # Mpc
inclination=0.2, # radians
coa_phase=0.3, # radians
delta_t_seconds=1./4096, # physical seconds
)
hp = pols.real()
hc = -1 * pols.imag()Polarization convention: Returns
conjugate(h)so that.real()gives$$h_+$$ and.imag()gives$$+h_\times$$ . This differs from LAL convention whereimag() = -h_\times. Passlal_convention=Trueto get LAL-compatible output.
# GW frequency at waveform start, normalized to 1 M_sun — divide by total_mass to get Hz
f_start_1msun = wfm.f_lower_at_1Msun()
f_start_hz = f_start_1msun / total_mass_msun
# GW frequency at the relaxation epoch
f_relax_hz = wfm.f_lower_at_relaxation(total_mass=60.0)wfm_trimmed = wfm.trim_to_relaxation_time(total_mass=60.0)Reads the relaxation time from metadata (tries keys 'relaxed-time', 'relaxation_time',
'reference_time').
get_mode() and get_td_waveform() accept two explicit sampling parameters:
| Parameter | Interpretation |
|---|---|
delta_t_seconds |
Physical seconds (e.g. 1/4096 for 4096 Hz sampling) |
delta_t_Msun |
Dimensionless M units (NR native, e.g. 0.5 means |
The returned TimeSeries.delta_t is always in physical seconds.
Deprecated: The old
delta_tkeyword argument (which inferred units from the magnitude) is deprecated. Usedelta_t_secondsordelta_t_Msunexplicitly.
import quaternionic
R = quaternionic.array.from_euler_angles(alpha, beta, gamma)
wfm_rotated = wfm.rotated(R)Applies Wigner D-matrix rotation: $$h^{\text{rot}}{\ell m}(t) = \sum{m'} h_{\ell m'}(t) , D^\ell_{m'm}(R)$$
Uses the spherical package for Wigner D-matrix computation.
from nrcats import apply_wigner_rotation_to_mode_dict
rotated_modes = apply_wigner_rotation_to_mode_dict(
mode_dict, # {(ell, m): pycbc.TimeSeries, ...}
R, # quaternionic rotation
ell_max=4,
)Useful for rotating surrogate model outputs into the NR frame for direct comparison.
This method calculates the match (noise-weighted overlap) between two waveforms, integrated over the entire sphere of possible observer directions (sky-averaged) and maximized over coordinate time shift
The overlap between the full multidimensional strain fields
By expanding the strain fields in spin-weighted spherical harmonics
To align the coordinate frames, the second waveform is transformed via:
$$h_{2, \ell m}^{\text{rot, shifted}}(t) = e^{-i m \phi_c} \sum_{m'=-\ell}^{\ell} h_{2, \ell m'}(t - t_c) , D^{\ell}{m' m}(R)$$
where $$D^\ell{m'm}(R)$$ is the Wigner D-matrix. The returned mismatch
mismatch = wfm_a.match_sphere_averaged(
wfm_b,
psd=my_psd,
f_lower=20.0, # Hz
delta_t_seconds=1./4096,
)This extended method performs the optimization over the infinite-dimensional BMS supertranslation group at null infinity
Supertranslations correspond to direction-dependent retarded-time shifts:
This method optimizes
Note
The scri package is required to compute the spin-weighted Gaunt coupling coefficients
All data stored internally in WaveformModes uses geometrized, mass-scaled dimensionless
units:
| Quantity | Dimensionless unit |
|---|---|
| Time | |
| Amplitude ( |
Physical conversion factors (from nrcats.utils):
import lal
# Time: 1 NR M unit → seconds
m_secs = total_mass_msun * lal.MTSUN_SI
# Amplitude: dimensionless → strain at distance d_Mpc
amp_scale = (lal.G_SI * total_mass_msun * lal.MSUN_SI
/ (lal.C_SI**2 * d_Mpc * 1e6 * lal.PC_SI))_filepath is extracted and stored as a per-instance attribute before the parent
sxs.WaveformModes.__new__() call. This prevents class-level sharing where loading a
second simulation would overwrite the first simulation's cached file path.
sxs.WaveformModes.data may return a non-writable memoryview. All arithmetic in
WaveformModes wraps the data with np.array(..., dtype=complex) before any in-place
operations to avoid ValueError: assignment destination is read-only.