LALSimUtils
Top-level utility module for LALSimulation interfacing.
A collection of useful data analysis routines built from the SWIG wrappings of LAL and LALSimulation.
- class RIFT.lalsimutils.ChooseWaveformParams(phiref=0.0, deltaT=0.000244140625, m1=1.9884098706980507e+31, m2=1.9884098706980507e+31, s1x=0.0, s1y=0.0, s1z=0.0, s2x=0.0, s2y=0.0, s2z=0.0, fmin=40.0, fref=0.0, dist=3.085677581491367e+22, incl=0.0, lambda1=0.0, lambda2=0.0, waveFlags=None, nonGRparams=None, ampO=0, phaseO=7, approx=84, theta=0.0, phi=0.0, psi=0.0, tref=0.0, radec=False, detector='H1', deltaF=None, fmax=0.0, taper=0, eccentricity=0.0, meanPerAno=0.0, E0=0.0, p_phi0=0.0, a6c=10000.0)
Bases:
objectClass containing all the arguments needed for SimInspiralChooseTD/FDWaveform plus parameters theta, phi, psi, radec to go from h+, hx to h(t)
- if radec==True: (theta,phi) = (DEC,RA) and strain will be computed using
XLALSimDetectorStrainREAL8TimeSeries
- if radec==False: then strain will be computed using a simple routine
that assumes (theta,phi) are spherical coord. in a frame centered at the detector
- FrequencyAtVelocity(v)
- HardAlignedQ()
Test if L,S1,S2 all parallel to z
- OrbitalAngularMomentumAtReference()
- OrbitalAngularMomentumAtReferenceOverM2()
- SoftAlignedQ()
Test if L,S1,S2 all parallel to one another
- TotalAngularMomentumAtReference()
- TotalAngularMomentumAtReferenceOverM2()
- VelocityAtFrequency(f)
- Xi()
- assign_param(p, val)
Syntatic sugar to assign parameters to values. Provides ability to specify a binary by its values of
mchirp, eta
system frame parameters
VERY HELPFUL if you want to change just one parameter at a time (e.g., for Fisher )
- copy()
Create a deep copy, so copy and original can be changed separately This does NOT work reliably (segfault side effects possible)
- copy_lsctables_sim_inspiral(row)
Fill this ChooseWaveformParams with the fields of a row of an lsctables.SimInspiral table (i.e. SimInspiral table in the format as read from a file)
NB: SimInspiral table does not contain deltaT, deltaF, fref, fmax, lambda1, lambda2, waveFlags, nonGRparams, or detector fields, but ChooseWaveformParams does have these fields. This function will not alter these fields, so their values will be whatever values the instance previously had.
Adapted from code by Chris Pankow
- copy_sim_inspiral(row)
Fill this ChooseWaveformParams with the fields of a row of a SWIG wrapped lalmetaio.SimInspiral table
NB: SimInspiral table does not contain deltaT, deltaF, fref, fmax, lambda1, lambda2, waveFlags, nonGRparams, or detector fields, but ChooseWaveformParams does have these fields. This function will not alter these fields, so their values will be whatever values the instance previously had.
- create_sim_inspiral()
Create a sim_inspiral table from P. One element from it
- extract_param(p)
assign_param Syntatic sugar to extract parameters to values. Necessary to make full use of assign_param on
mchirp, eta
system frame parameters
VERY HELPFUL if you want to change just one parameter at a time (e.g., for Fisher )
- extract_system_frame(verbose=False)
Extract system frame angles. Returned in precisely the format needed for use in init_via_system_frame. P.init_via_system_frame(P.extract_system_frame()) should leave the state unchanged. CHECK DONE IN : LIGO-Development-UpdatedSpinningWaveforms/KISTI-MCMC/PrecessingFisher/Python/overlap_versus_systemframe PROBLEM: Polarization angle isn’t stable (oddly?)
- init_via_system_frame(thetaJN=0.0, phiJL=0.0, theta1=0.0, theta2=0.0, phi12=0.0, chi1=0.0, chi2=0.0, psiJ=0.0)
Populate spin directions (and psi_L) using system frame parameters. Note this is NOT using eta Example: P.init_via_system_frame(thetaJN=0.1, phiJL=0.1, theta1=0.1, theta2=0.1, phi12=0.1, chi1=1., chi2=1., psiJ=0.)
- manual_copy()
- print_params(show_system_frame=False)
Print all key-value pairs belonging in the class instance
- randomize(zero_spin_Q=False, aligned_spin_Q=False, volumetric_spin_prior_Q=False, default_inclination=None, default_phase=None, default_polarization=None, dMax=500.0, dMin=1.0, sMax=1)
- scale_to_snr(new_SNR, psd, ifo_list, analyticPSD_Q=True, **kwargs)
evaluates network SNR in the ifo list provided (assuming constant psd for all..may change)
uses network SNR to rescale the distance of the source, so the SNR is now new_SNR
returns current_SNR, for sanity
- swap_components()
- to_lal_dict()
- to_lal_dict_extended(extra_args_dict=None)
- to_lal_dict_extended:
Extended implementation, to address massive proliferation of options to control waveform version See https://git.ligo.org/lscsoft/bilby_pipe/-/merge_requests/371/diffs
- RIFT.lalsimutils.ChooseWaveformParams_array_to_hdf5(P_list, fname='injections', deltaT=0.000244140625, fref=0.0, waveFlags=None, nonGRparams=None, detector='H1', deltaF=None, fMax=0.0)
HDF5 storage for parameters. Compare to lalinference HDF5 i/o https://github.com/lscsoft/lalsuite/blob/master/lalinference/python/lalinference/io/hdf5.py
TERRIBLE CODE: Assumes hardcoded order, does not embed metadata with field names SHOULD RESTRUCTURE to load into record-array like structure
- RIFT.lalsimutils.ChooseWaveformParams_array_to_xml(P_list, fname='injections', minrow=None, maxrow=None, deltaT=0.000244140625, fref=0.0, waveFlags=None, nonGRparams=None, detector='H1', deltaF=None, fMax=0.0)
Standard XML storage for parameters. Note that lambda values are NOT stored in xml table entries — I have a special hack to do this
- class RIFT.lalsimutils.ComplexIP(fLow=10.0, fMax=None, fNyq=2048.0, deltaF=0.125, psd=<built-in function SimNoisePSDaLIGOZeroDetHighPower>, analyticPSD_Q=True, inv_spec_trunc_Q=False, T_spec=0.0, waveform_is_psi4=False)
Bases:
InnerProductComplex-valued inner product. self.ip(h1,h2) computes
fNyq
- 2 int h1(f) h2*(f) / Sn(f) df
-fNyq
And similarly for self.norm(h1)
- N.B. DOES NOT assume h1, h2 are Hermitian - they should contain negative
and positive freqs. packed as
[ -N/2 * df, …, -df, 0, df, …, (N/2-1) * df ] DOES NOT maximize over time or phase
- ip(h1, h2, include_epoch_differences=False)
Compute inner product between two COMPLEX16Frequency Series Accounts for time shfit
- ip_matrix(listA, listB, chunk=262144)
Batched form of ip(): returns the matrix M[a,b] = self.ip(listA[a], listB[b]).
listA, listB are sequences of COMPLEX16FrequencySeries on the same 2-sided grid. The double loop over (a,b) is a single matrix product,
M = 2 df . conj(A) . (B . W)^T , A[a,f] = listA[a](f), B[b,f] = listB[b](f)
which turns O(Na.Nb) separate full-length reductions into one pass over the data plus a GEMM, and skips the frequency bins where the band weight is exactly zero. Accumulated in chunks of chunk bins so the working set stays bounded.
NOT bit-identical to the loop: the reduction order changes (pairwise np.sum over the full array vs. blocked GEMM accumulation over the band). Measured deviation is ~1e-15 relative to max|M| – see DESIGN_precompute_crossterm_batching.md. Callers that need the shipped rounding must keep using ip().
- norm(h)
Compute norm of a COMPLEX16Frequency Series
- class RIFT.lalsimutils.ComplexOverlap(fLow=10.0, fMax=None, fNyq=2048.0, deltaF=0.125, psd=<built-in function SimNoisePSDaLIGOZeroDetHighPower>, analyticPSD_Q=True, inv_spec_trunc_Q=False, T_spec=0.0, full_output=False, interpolate_max=False, waveform_is_psi4=False)
Bases:
InnerProductInner product maximized over time and polarization angle. This inner product does not assume Hermitianity and is therefore valid for waveforms that are complex in the TD, e.g. h+(t) + 1j hx(t). self.IP(h1,h2) computes:
fNyq
- max 2 Abs int h1*(f,tc) h2(f) / Sn(f) df
tc -fNyq
h1, h2 must be COMPLEX16FrequencySeries defined in [-fNyq, fNyq-deltaF] At least one of which should be non-Hermitian for the maximization over phase to work properly.
- If self.full_output==False: returns
The maximized overlap
- If self.full_output==True: returns
The maximized overlap The entire COMPLEX16TimeSeries of overlaps for each possible time shift The index of the above time series at which the maximum occurs The phase rotation which maximizes the real-valued overlap
- ip(h1, h2, **kwargs)
Compute inner product between two non-Hermitian COMPLEX16FrequencySeries
- norm(h)
Compute norm of a non-Hermitian COMPLEX16FrequencySeries
- wrap_times()
Return a vector of wrap-around time offsets, i.e. [ 0, dt, 2 dt, …, N dt, -(N-1) dt, -(N-1) dt, …, -2 dt, -dt ]
This is useful in conjunction with the ‘full_output’ option to plot the overlap vs timeshift. e.g. do:
IP = ComplexOverlap(full_output=True) t = IP.wrap_times() rho, ovlp, rhoIdx, rhoPhase = IP.ip(h1, h2) plot(t, abs(ovlp))
- RIFT.lalsimutils.CreateCompatibleComplexIP(hlmf, **kwargs)
Creates complex IP (no maximization)
- RIFT.lalsimutils.CreateCompatibleComplexOverlap(hlmf, **kwargs)
CreateCompatibleComplexOverlap: accepts dictionary or single instance of COMPLEX16FrequencySeries
- RIFT.lalsimutils.DataFourier(ht)
- RIFT.lalsimutils.DataFourierREAL8(ht)
- RIFT.lalsimutils.DataInverseFourier(hf)
- RIFT.lalsimutils.DataInverseFourierREAL8(hf)
- RIFT.lalsimutils.DataRollBins(ht, nL)
- RIFT.lalsimutils.DataRollTime(ht, DeltaT)
- RIFT.lalsimutils.Fcross(theta, phi, psi)
Antenna pattern as a function of polar coordinates measured from directly overhead a right angle interferometer and polarization angle
- RIFT.lalsimutils.Fplus(theta, phi, psi)
Antenna pattern as a function of polar coordinates measured from directly overhead a right angle interferometer and polarization angle
- class RIFT.lalsimutils.HermitianComplexIP(fLow=10.0, fMax=None, fNyq=2048.0, deltaF=0.125, psd=<built-in function SimNoisePSDaLIGOZeroDetHighPower>, analyticPSD_Q=True, inv_spec_trunc_Q=False, T_spec=0.0, waveform_is_psi4=False)
Bases:
InnerProductComplex-valued inner product. self.ip(h1,h2) computes
fNyq
- 4 int h1(f) h2*(f) / Sn(f) df
fLow
And similarly for self.norm(h1)
- N.B. Assumes h1, h2 are Hermitian - i.e. they store only positive freqs.
with negative freqs. given by h(-f) = h*(f)
DOES NOT maximize over time or phase
- ip(h1, h2)
Compute inner product between two COMPLEX16Frequency Series
- norm(h)
Compute norm of a COMPLEX16Frequency Series
- class RIFT.lalsimutils.InnerProduct(fLow=10.0, fMax=None, fNyq=2048.0, deltaF=0.125, psd=<built-in function SimNoisePSDaLIGOZeroDetHighPower>, analyticPSD_Q=True, inv_spec_trunc_Q=False, T_spec=0.0, waveform_is_psi4=False)
Bases:
objectBase class for inner products
- ip(h1, h2)
Compute inner product between two COMPLEX16Frequency Series
- norm(h)
Compute norm of a COMPLEX16Frequency Series
- RIFT.lalsimutils.Mceta(m1, m2)
Compute chirp mass and symmetric mass ratio from component masses
- RIFT.lalsimutils.NINJA_data_to_hoff(fname, TDlen=0, scaleT=1.0, scaleH=1.0, Fp=1.0, Fc=0.0)
Function to read in data in the NINJA format, i.e. t_i h+(t_i) hx(t_i) and convert it to a COMPLEX16FrequencySeries holding the observed h(f) = FFT[ Fp*h+(t) + Fc*hx(t) ]
If TDlen == -1, do not zero-pad the TD waveform before FFTing If TDlen == 0 (default), zero-pad the TD waveform to the next power of 2 If TDlen == N, zero-pad the TD waveform to length N before FFTing
scaleT and scaleH can be used to rescale the time steps and strain resp. e.g. to get a waveform appropriate for a total mass M you would scale by scaleT = G M / c^3 scaleH = G M / (D c^2)
- RIFT.lalsimutils.NINJA_data_to_hoft(fname, TDlen=-1, scaleT=1.0, scaleH=1.0, Fp=1.0, Fc=0.0)
Function to read in data in the NINJA format, i.e. t_i h+(t_i) hx(t_i) and convert it to a REAL8TimeSeries holding the observed h(t) = Fp*h+(t) + Fc*hx(t)
If TDlen == -1 (default), do not zero-pad the returned waveforms If TDlen == 0, zero-pad returned waveforms to the next power of 2 If TDlen == N, zero-pad returned waveforms to length N
scaleT and scaleH can be used to rescale the time steps and strain resp. e.g. to get a waveform appropriate for a total mass M you would scale by scaleT = G M / c^3 scaleH = G M / (D c^2)
- RIFT.lalsimutils.NINJA_data_to_hp_hc(fname, TDlen=-1, scaleT=1.0, scaleH=1.0, deltaT=0)
Function to read in data in the NINJA format in file ‘fname’, i.e. t_i h+(t_i) hx(t_i) and convert it to two REAL8TimeSeries holding polarizations hp(t) and hc(t)
If TDlen == -1 (default), do not zero-pad the returned waveforms If TDlen == 0, zero-pad returned waveforms to the next power of 2 If TDlen == N, zero-pad returned waveforms to length N
scaleT and scaleH can be used to rescale the time steps and strain resp. e.g. if the input file provides time steps in t/M and the strain has mass and distance scaled out, to get a waveform appropriate for a total mass M and distance D you would scale by scaleT = G M / c^3 scaleH = G M / (D c^2)
Once time is properly scaled into seconds, you can interpolate the waveform to a different sample rate deltaT. e.g. if the file has time steps of t/M = 1 and you use scaleT to rescale for a 100 Msun binary, the time steps will be ~= 0.00049 s. If you provide the argument deltaT = 1./4096. ~= 0.00024 s the waveform will be interpolated and resampled at 4096 Hz.
If deltaT==0, then no interpolation will be done
NOTE: For improved accuracy, we convert h+ + i hx –> A e^(i Phi), interpolate and resample A and Phi, then convert back to h+, hx
- RIFT.lalsimutils.NINJA_data_to_norm_hoff(fname, IP, TDlen=0, scaleT=1.0, scaleH=1.0, Fp=1.0, Fc=0.0)
Function to read in data in the NINJA format, i.e. t_i h+(t_i) hx(t_i) and convert it to a COMPLEX16FrequencySeries holding h(f) = FFT[ Fp*h+(t) + Fc*hx(t) ] normalized so (h|h)=1 for inner product IP
If TDlen == -1, do not zero-pad the TD waveform before FFTing If TDlen == 0 (default), zero-pad the TD waveform to the next power of 2 If TDlen == N, zero-pad the TD waveform to length N before FFTing
scaleT and scaleH can be used to rescale the time steps and strain resp. e.g. to get a waveform appropriate for a total mass M you would scale by scaleT = G M / c^3 scaleH = G M / (D c^2)
- class RIFT.lalsimutils.Overlap(fLow=10.0, fMax=None, fNyq=2048.0, deltaF=0.125, psd=<built-in function SimNoisePSDaLIGOZeroDetHighPower>, analyticPSD_Q=True, inv_spec_trunc_Q=False, T_spec=0.0, full_output=False)
Bases:
InnerProductInner product maximized over time and phase. self.ip(h1,h2) computes:
fNyq
- max 4 Abs int h1*(f,tc) h2(f) / Sn(f) df
tc fLow
h1, h2 must be COMPLEX16FrequencySeries defined in [0, fNyq] (with the negative frequencies implicitly given by Hermitianity)
- If self.full_output==False: returns
The maximized (real-valued, > 0) overlap
- If self.full_output==True: returns
The maximized overlap The entire COMPLEX16TimeSeries of overlaps for each possible time shift The index of the above time series at which the maximum occurs The phase rotation which maximizes the real-valued overlap
- ip(h1, h2)
Compute inner product between two Hermitian COMPLEX16Frequency Series
- norm(h)
Compute norm of a COMPLEX16Frequency Series
- wrap_times()
Return a vector of wrap-around time offsets, i.e. [ 0, dt, 2 dt, …, N dt, -(N-1) dt, -(N-1) dt, …, -2 dt, -dt ]
This is useful in conjunction with the ‘full_output’ option to plot the overlap vs timeshift. e.g. do:
IP = Overlap(full_output=True) t = IP.wrap_times() rho, ovlp, rhoIdx, rhoPhase = IP.ip(h1, h2) plot(t, abs(ovlp))
- RIFT.lalsimutils.RangeProtect(fn, val)
RangeProtect(fn) wraps fn, returning - np.inf in cases where an argument is not finite, and calling the function otherwise. Intended to be used with test_coord_output and coordinate conversion routines, to identify range errors, etc.
This function assumes fn acts on EACH ELEMENT INDIVIDUALLY, and does not reduce the dimension. Not to use.
- RIFT.lalsimutils.RangeProtectReduce(fn, val)
RangeProtect(fn) wraps fn, returning - np.inf in cases where an argument is not finite, and calling the function otherwise. Intended to be used with test_coord_output and coordinate conversion routines, to identify range errors, etc.
This function assumes fn acts to REDUCE the data to one dimension (e.g., a list of points)
- class RIFT.lalsimutils.RealIP(fLow=10.0, fMax=None, fNyq=2048.0, deltaF=0.125, psd=<built-in function SimNoisePSDaLIGOZeroDetHighPower>, analyticPSD_Q=True, inv_spec_trunc_Q=False, T_spec=0.0, waveform_is_psi4=False)
Bases:
InnerProductReal-valued inner product. self.ip(h1,h2) computes
fNyq
- 4 Re int h1(f) h2*(f) / Sn(f) df
fLow
And similarly for self.norm(h1)
DOES NOT maximize over time or phase
- ip(h1, h2)
Compute inner product between two COMPLEX16Frequency Series
- norm(h)
Compute norm of a COMPLEX16Frequency Series
- RIFT.lalsimutils.SphHarmFrequencySeries_to_dict(hlms, Lmax)
Convert a SphHarmFrequencySeries SWIG-wrapped linked list into a dictionary.
The keys are tuples of integers of the form (l,m) and a key-value pair will be created for each (l,m) with 2 <= l <= Lmax, |m| <= l for which lalsimulation.SphHarmFrequencySeriesGetMode(hlms, l, m) returns a non-null pointer.
- RIFT.lalsimutils.SphHarmTimeSeries_to_dict(hlms, Lmax)
Convert a SphHarmTimeSeries SWIG-wrapped linked list into a dictionary.
The keys are tuples of integers of the form (l,m) and a key-value pair will be created for each (l,m) with 2 <= l <= Lmax, |m| <= l for which lalsimulation.SphHarmTimeSeriesGetMode(hlms, l, m) returns a non-null pointer.
- RIFT.lalsimutils.VectorToFrame(vecRef)
Convert vector to a frame, by picking relatively arbitrary vectors perp to it. Used to convert J to a frame. spin_convention == radiation:
Uses the radiation frame conventions to do so., so the ‘z’ direction is orthogonal to the 2nd vector and ‘n’ (the line of sight) defines things
- spin_convention == L:
Trickier, because we will want to define angles of L relative to J ! Pick a random alternate vector
- RIFT.lalsimutils.Yagi13_fit_barlamdel(barlam2, ell)
Yagi 2013 fits for multipolar $bar{lambda}_ell$ = 2 k_ell/(C^{2ell+1} (2ell-1)!!)$ Eq.(10),(61); Tab.I; Fig.8 http://arxiv.org/abs/1311.0872
- RIFT.lalsimutils.Yagi13_fitcoefs(ell)
Coefficients of Yagi 2013 fits for multipolar $bar{lambda}_ell = 2 k_ell/(C^{2ell+1} (2ell-1)!!)$ Tab.I (NS) http://arxiv.org/abs/1311.0872
- RIFT.lalsimutils.barlamdel_to_kappal(q, barlaml, ell)
$kappa^{A,B}_ell(bar{lambda}_ell)$ Assume $q=M_A/M_B>=1$
- RIFT.lalsimutils.check_FD_pending(code)
- RIFT.lalsimutils.chieff_aligned_spins(m1, m2, s1z, s2z, xi)
s1z, s2z with xi = (m1 s1z + m2 s2z)/M and chiminus = (m2 s1z - m1 s2z)/M held from the inputs.
The inverse used by assign_param(‘chieff_aligned’); accepts arrays. Exchange-antisymmetric; for large mass ratio s1z -> xi, s2z -> -chiminus. Can give |s_iz| > 1.
- RIFT.lalsimutils.complex_hoff(P, sgn=-1, fwdplan=None, **kwargs)
CURRENTLY ONLY WORKS WITH TD APPROXIMANTS
Generate a (non-Hermitian) FD waveform from ChooseWaveformParams P by creating a complex TD waveform of the form
h(t) = h+(t) + 1j sgn hx(t) where sgn = -1 (default) or 1
If P.deltaF==None, just pad up to next power of 2 If P.deltaF = 1/X, will generate a TD waveform, zero-pad to length X seconds
and then FFT. Will throw an error if waveform is longer than X seconds
If you do not provide a forward FFT plan, one will be created. If you are calling this function many times, it is best to create it once beforehand and pass it in, e.g.: fwdplan=lal.CreateForwardCOMPLEX16FFTPlan(TDlen,0)
Returns a COMPLEX16FrequencySeries object
- RIFT.lalsimutils.complex_hoft(P, sgn=-1, **kwargs)
Generate a complex TD waveform from ChooseWaveformParams P Returns h(t) = h+(t) + 1j sgn hx(t) where sgn = -1 (default) or 1
Returns a COMPLEX16TimeSeries object
- RIFT.lalsimutils.complex_hoft_IMRPv2(P_copy, sgn=-1)
Generate a complex TD waveform from ChooseWaveformParams P, using SimInspiralTD Returns h(t) = h+(t) + 1j sgn hx(t) where sgn = -1 (default) or 1
Returns a COMPLEX16TimeSeries object
Designed specifically to help interface with IMRPhenomPv2
- RIFT.lalsimutils.complex_norm_hoff(P, IP, sgn=-1, fwdplan=None)
CURRENTLY ONLY WORKS WITH TD APPROXIMANTS
Generate a (non-Hermitian) FD waveform from ChooseWaveformParams P by creating a complex TD waveform of the form
h(t) = h+(t) + 1j sgn hx(t) where sgn = -1 (default) or 1
If P.deltaF==None, just pad up to next power of 2 If P.deltaF = 1/X, will generate a TD waveform, zero-pad to length X seconds
and then FFT. Will throw an error if waveform is longer than X seconds
If you do not provide a forward FFT plan, one will be created. If you are calling this function many times, it is best to create it once beforehand and pass it in, e.g.: fwdplan=lal.CreateForwardCOMPLEX16FFTPlan(TDlen,0)
Returns a COMPLEX16FrequencySeries object
- RIFT.lalsimutils.conj_hlmoff(P, Lmax=2)
- RIFT.lalsimutils.convert_waveform_coordinates(x_in, coord_names=['mc', 'eta'], low_level_coord_names=['m1', 'm2'], enforce_kerr=False, source_redshift=0, fref=None)
A wrapper for ChooseWaveformParams() ‘s coordinate tools (extract_param, assign_param) providing array-formatted coordinate changes. BE VERY CAREFUL, because coordinates may be defined inconsistently (e.g., holding different variables constant: M and eta, or mc and q). Note that if ChooseWaveformParam structuers are built ,the loops can be quite slow
- Special cases:
coordinates in x_out already in x_in are copied over directly
xi==chi_eff, chiMinus, mu1,mu2 : transformed directly from mc, delta_mc, s1z,s2z coordinates, using fast vectorized transformations.
source_redshift: if nonzero, convert m1 -> m1 (1+z)=m_z, as fit is done in the detector frame. We are assuming source-frame sampling
rf_* (geometric4) coordinates: computed from the physical components; require fref.
- RIFT.lalsimutils.convert_waveform_coordinates_with_eos(x_in, coord_names=['mc', 'eta'], low_level_coord_names=['m1', 'm2'], enforce_kerr=False, eos_class=None, no_matter1=False, no_matter2=False, source_redshift=0, backstop_novector=False)
A wrapper for ChooseWaveformParams() ‘s coordinate tools (extract_param, assign_param) providing array-formatted coordinate changes. BE VERY CAREFUL, because coordinates may be defined inconsistently (e.g., holding different variables constant: M and eta, or mc and q)
- RIFT.lalsimutils.deltalamtilde_of_eta_lam1_lam2(eta, lam1, lam2)
This is the definition found in Les Wade’s paper. Les has factored out the quantity sqrt(1-4eta). It is different from Marc Favata’s paper. $deltatildeLambda(eta, Lambda_1, Lambda_2)$. Lambda_1 is assumed to correspond to the more massive (primary) star m_1. Lambda_2 is for the secondary star m_2.
- RIFT.lalsimutils.eccentric_anomaly_from_mean(mean_anomaly, eccentricity)
- RIFT.lalsimutils.enforce_swig_psd_fmin(raw_psd, fmin)
- RIFT.lalsimutils.estimateDeltaF(P, LmaxEff=2)
Input: P Output:estimated duration (in s) based on Newtonian inspiral from P.fmin to infinite frequency
- RIFT.lalsimutils.estimateWaveformDuration(P, LmaxEff=2)
Input: P Output:estimated duration (in s) based on Newtonian inspiral from P.fmin to infinite frequency
- RIFT.lalsimutils.eta_crit(Mc, m2_min)
- RIFT.lalsimutils.evaluate_fvals(lal_2sided_fseries, lal_convention=False)
Associates frequencies with a 2sided lal complex array. Compare with ‘self.longweights’ code Done by HAND in PrecessingOrbitModesOfFrequency Manually reverses convention re sign of omega used in lal!
- lal_convention=False (default): RIFT’s own two-sided packing (arrays produced by
DataFourier/complex_hoff): even length, REVERSED, f[k] = deltaF*(npts/2 - k). WARNING: for odd-length arrays this assigns f on a grid offset by deltaF/2 – it is only correct for the even-length RIFT packing.
- lal_convention=True: the packing of two-sided series returned directly by LAL
generators (e.g. SimInspiralChooseFDModes): ASCENDING [-fNyq, …, 0, …, +fNyq] with DC at index npts//2 (odd length TDlen+1; even length after truncation keeps DC at npts//2). f[k] = deltaF*(k - npts//2), exact for both parities of npts. Use this - not the default - on ChooseFDModes output: the default’s reversal + half-bin offset shifts any |f|-symmetric window by one bin between (l,m) and (l,-m) modes (which live at opposite signs of f), breaking the conjugate-pair identity h_{l,-m}(f) = (-1)^l conj(h_{lm}(-f)) at the percent level.
- Notes:
XXXFrequencySeries have an f0 and a deltaF, and logically they should run from f0….f0+N*df
- I will always use COMPLEX16FrequencySeries, which should run from -fNyq…fNyq-df
with fNyq=fSample/2.=1/(2*deltaT)
In practice, I have a REVERSED frequency series associated…WHY? (finish doc review) Probably an overall sign difference in omega t vs -omega t in FFT definition? LAL documentation isn’t clear with the overall sign.
lal: int dt exp( -i omega t) F(t) = tilde{F}(omega) [lal] me: int dt exp( i omega t) F(t) = tilde{F}(omega)
following Poisson and Will, my old ‘DataFourier’ code, etc
- The low-level code just rotates the original vector right by half the length – so the usual FFTW
code data is mapped right.
- Checks:
P=lalsimutils.ChooseWaveformParams() hf = lalsimutils.complex_hoff(P) lalsimutils.evaluate_fvals(hf) hf.f0
- Notes:
- ‘’Physics convention<math> int dt exp(-i omega t) F(t) </math>
my notes use -2 pi i f t convention
my NR papers text uses int dt exp(-i omega t) convention
- ‘’Other convention (PN-convenient) <math> int dt exp(i omega t) F(t) </math>
Prakash notes use opposite convention
low-level mathematica code (DataFourier) uses int dt exp(i omega t) convention
Poisson and Will uses opposite convention http://arxiv.org/pdf/gr-qc/9502040v1.pdf, as do all subsequent PN work
Cutler and Flanagan use the opposite convention
- RIFT.lalsimutils.evaluate_tvals(lal_tseries)
- RIFT.lalsimutils.extend_swig_psd_series_to_sampling_requirements(raw_psd, dfRequired, fNyqRequired)
extend_psd_series_to_sampling_requirements: Takes a conventional 1-sided PSD and extends into a longer 1-sided PSD array by filling intervening samples. Currently only works by ‘interpolating’ between samples. Assumes fNyq does not change. Assumes the input and output are swig REAL8Timeseries objects
- RIFT.lalsimutils.extract_JL_angles(P, return_inverse=True, phase_factor=1, opening_angle=None)
extract_JL_angles: finds Euler angles for transformation see eg C13, C14 in 2004.06503
Using directly-coded J,L expressions rather than calling the lalsuite routine, to make sure phases agree with what I intend.
- RIFT.lalsimutils.findDeltaF(P, **kwargs)
Given ChooseWaveformParams P, generate the TD waveform, round the length to the next power of 2, and find the frequency bin size corresponding to this length. This is useful b/c deltaF is needed to define an inner product which is needed for norm_hoft and norm_hoff functions
- RIFT.lalsimutils.frame_data_to_hoff(fname, channel, start=None, stop=None, TDlen=0, window_shape=0.0, verbose=True, **kwargs)
Function to read in data in the frame format and convert it to a COMPLEX16FrequencySeries holding h(f) = FFT[ h(t) ]
Before the FFT, applies a Tukey window with shape parameter ‘window_shape’. N.B. if window_shape=0, the window is the identity function
if window_shape=1, the window becomes a Hann window if 0<window_shape<1, the data will transition from zero to full
strength over that fraction of each end of the data segment.
If TDlen == -1, do not zero-pad the TD waveform before FFTing If TDlen == 0 (default), zero-pad the TD waveform to the next power of 2 If TDlen == N, zero-pad the TD waveform to length N before FFTing
- RIFT.lalsimutils.frame_data_to_hoft(fname, channel, start=None, stop=None, window_shape=0.0, verbose=True, deltaT=None, deltaT_internal=None, upsample_method='cubic', use_gwpy=False, **kwargs)
Function to read in data in the frame format and convert it to a REAL8TimeSeries. fname is the path to a LIGO cache file.
Applies a Tukey window to the data with shape parameter ‘window_shape’. N.B. if window_shape=0, the window is the identity function
if window_shape=1, the window becomes a Hann window if 0<window_shape<1, the data will transition from zero to full
strength over that fraction of each end of the data segment.
- Modified to rely on the lalframe read_timeseries function
https://github.com/lscsoft/lalsuite/blob/master/lalframe/python/lalframe/frread.py
- RIFT.lalsimutils.frame_data_to_hoft_old(fname, channel, start=None, stop=None, window_shape=0.0, verbose=True)
Function to read in data in the frame format and convert it to a REAL8TimeSeries. fname is the path to a LIGO cache file.
Applies a Tukey window to the data with shape parameter ‘window_shape’. N.B. if window_shape=0, the window is the identity function
if window_shape=1, the window becomes a Hann window if 0<window_shape<1, the data will transition from zero to full
strength over that fraction of each end of the data segment.
- RIFT.lalsimutils.frame_data_to_non_herm_hoff(fname, channel, start=None, stop=None, TDlen=0, window_shape=0.0, verbose=True, deltaT=None, **kwargs)
Function to read in data in the frame format and convert it to a COMPLEX16FrequencySeries h(f) = FFT[ h(t) ] Create complex FD data that does not assume Hermitianity - i.e. contains positive and negative freq. content
Before the FFT, applies a Tukey window with shape parameter ‘window_shape’. N.B. if window_shape=0, the window is the identity function
if window_shape=1, the window becomes a Hann window if 0<window_shape<1, the data will transition from zero to full
strength over that fraction of each end of the data segment.
If TDlen == -1, do not zero-pad the TD waveform before FFTing If TDlen == 0 (default), zero-pad the TD waveform to the next power of 2 If TDlen == N, zero-pad the TD waveform to length N before FFTing
- RIFT.lalsimutils.get_intp_psd_series_from_xmldoc(fname, inst)
- RIFT.lalsimutils.get_psd_series_from_xmldoc(fname, inst)
- RIFT.lalsimutils.guess_mc_range(event_dict, force_mc_range=None)
- RIFT.lalsimutils.guess_mc_range_mdc(P, force_mc_range=None)
- RIFT.lalsimutils.hdf5_to_ChooseWaveformParams_array(fname='injections', deltaT=0.000244140625, fref=0.0, waveFlags=None, nonGRparams=None, detector='H1', deltaF=None, fMax=0.0)
HDF5 storage for parameters. Compare to lalinference HDF5 i/o https://github.com/lscsoft/lalsuite/blob/master/lalinference/python/lalinference/io/hdf5.py
TERRIBLE CODE: Assumes hardcoded order, does not embed metadata with field names SHOULD RESTRUCTURE to load into record-array like structure
- RIFT.lalsimutils.hlmoff(P, Lmax=2)
Generate the FD h_lm -2-spin-weighted spherical harmonic modes of a GW with parameters P. Returns a SphHarmTimeSeries, a linked-list of modes with a COMPLEX16TimeSeries and indices l and m for each node.
The linked list will contain all modes with l <= Lmax and all values of m for these l.
- RIFT.lalsimutils.hlmoft(P, Lmax=2, nr_polarization_convention=False, fixed_tapering=False, silent=True, fd_standoff_factor=0.964, no_condition=False, fd_L_frame=False, fd_centering_factor=0.9, fd_alignment_postevent_time=None, fd_end_taper_max_time=1.0, **kwargs)
Generate the TD h_lm -2-spin-weighted spherical harmonic modes of a GW with parameters P. Returns a SphHarmTimeSeries, a linked-list of modes with a COMPLEX16TimeSeries and indices l and m for each node.
The linked list will contain all modes with l <= Lmax and all values of m for these l.
nr_polarization_convention : apply a factor -1 to all modes provided by lalsuite
- fd_standoff_factor: for ChooseFDWaveform, reduce starting frequency P.fmin by this factor internally when generating.
FD waveform calculation implicitly assumes fmin is in the inspiral regime (if not you are making bad life choices). Normal default value of 0.964 is based on changing inspiral duration by 10% (1.1^(3/8) ~ 1.036). Any constant factor will change the inspiral duration by a factor (1./fd_standoff_factor)^(8/3) or so.
WARNING: internal_hlm_generator will CHANGE this factor to 0.9, to better match complex_hoft. I’m keeping the default of this function here to match the nominal documentaiton of SimInspiralTD, while internal_hlm_generator has a different factor, chosen to match its actual output.
no_condition: disable conditioning: the ChooseFDModes high-pass/taper, the start tapers of the SEOB, SEOBv3 and IMRPhenomP branches, and the start taper applied to ChooseTDModes / TDModesFromPolarizations output at the end of this function. Used by the td-gs likelihood code path (no windows, no tapers) and for diagnostic plots on impact of/need for conditioning. Does not touch lalsuite’s own internal conditioning of FD-generated models. fd_L_frame: rotate hlmoft to L frame from J frame for return values from ChooseFDModes (XO4/XPHM). fd_end_taper_max_time: cap (seconds) on the ChooseFDModes end taper, which is otherwise 1% of the
buffer. With fd_alignment_postevent_time=2 an uncapped end taper covers the merger once the buffer exceeds ~185 s. None restores the uncapped 1%. Has no effect for buffers <= 100 s.
- RIFT.lalsimutils.hlmoft_FromFD_dict(P, Lmax=2)
Uses Chris Pankow’s interface in lalsuite Do not redshift the source
- RIFT.lalsimutils.hlmoft_IMRPv2_dict(P, sgn=-1)
Reconstruct hlm(t) from h(t,nhat) evaluated in 5 different nhat directions, specifically for IMRPhenomPv2 Using SimInspiralTD evaluated at nhat=zhat (zhat=Jhat), nhat=-zhat, and at three points in the equatorial plane. There is an analytic solution, but for code transparency I do the inverse numerically rather than code it in
- ISSUES
lots of instability in recovery depending on point set used (e.g., degeneracy in aligned spin case). Need to choose intelligently
duration of hlm is longer than deltaF (because of SimInspiralTD) in general.
- RIFT.lalsimutils.hlmoft_SEOB_dict(P, Lmax=2)
Generate the TD h_lm -2-spin-weighted spherical harmonic modes of a GW with parameters P. Returns a dictionary of modes. Just for SEOBNRv2 SEOBNRv1, and EOBNRv2. Uses aligned-spin trick to get (2,2) and (2,-2) modes. A hack. Works for any aligned-spin time-domain waveform with only (2,pm 2) modes though.
- RIFT.lalsimutils.hlmoft_SEOBv3_dict(P, Lmax=2)
Generate the TD h_lm -2-spin-weighted spherical harmonic modes of a GW with parameters P. Returns a dictionary of modes. A hack for SEOBNRv3, because there’s not a natural dictionary output
Will NOT perform the -1 factor correction
- RIFT.lalsimutils.hlmoft_SpinTaylorManual_dict(P, Lmax=2)
Generate the TD h_lm -2-spin-weighted spherical harmonic modes of a GW with parameters P. Returns a dictionary of modes. Just for SpinTaylor, using manual interface provided by Riccardo and Jake.
- RIFT.lalsimutils.hoff(P, Fp=None, Fc=None, fwdplan=None, **kwargs)
Generate a FD waveform from ChooseWaveformParams P. Will return a COMPLEX16FrequencySeries object.
If P.approx is a FD approximant, hoff_FD is called. This path calls SimInspiralChooseFDWaveform
fwdplan must be None for FD approximants.
If P.approx is a TD approximant, hoff_TD is called. This path calls ChooseTDWaveform and performs an FFT.
The TD waveform will be zero-padded so it’s Fourier transform has frequency bins of size P.deltaT. If P.deltaF == None, the TD waveform will be zero-padded to the next power of 2.
- RIFT.lalsimutils.hoff_FD(P, Fp=None, Fc=None, **kwargs)
Generate a FD waveform for a FD approximant. Note that P.deltaF (which is None by default) must be set
- RIFT.lalsimutils.hoff_TD(P, Fp=None, Fc=None, fwdplan=None, **kwargs)
Generate a FD waveform from ChooseWaveformParams P by creating a TD waveform, zero-padding and then Fourier transforming with FFTW3 forward FFT plan fwdplan
If P.deltaF==None, just pad up to next power of 2 If P.deltaF = 1/X, will generate a TD waveform, zero-pad to length X seconds
and then FFT. Will throw an error if waveform is longer than X seconds
If you do not provide a forward FFT plan, one will be created. If you are calling this function many times, you may to create it once beforehand and pass it in, e.g.: fwdplan=lal.CreateForwardREAL8FFTPlan(TDlen,0)
You may pass in antenna patterns Fp, Fc. If none are provided, they will be computed from the information in ChooseWaveformParams
Returns a COMPLEX16FrequencySeries object
- RIFT.lalsimutils.hoft(P, Fp=None, Fc=None, **kwargs)
Generate a TD waveform from ChooseWaveformParams P You may pass in antenna patterns Fp, Fc. If none are provided, they will be computed from the information in ChooseWaveformParams.
Returns a REAL8TimeSeries object
- RIFT.lalsimutils.hoft_from_hlm(hlms, P, return_complex=False, extra_phase_shift=0)
hoft_from_hlm(hlm,P,Lmax): return hoft like output given hlmoft input. Important if hoft is not accessible (e.g., not provided by lalsuite)
- RIFT.lalsimutils.hoft_to_frame_data(fname, channel, hoft)
Function to write h(t) to a frame file in a specific channel. NOT YET DEBUGGED
- RIFT.lalsimutils.lam1_lam2_of_pe_params(eta, lamt, dlamt)
lam1 is for the the primary mass m_1. lam2 is for the the secondary mass m_2. m_1 >= m2.
- RIFT.lalsimutils.lamtilde_of_eta_lam1_lam2(eta, lam1, lam2)
$tildeLambda(eta, Lambda_1, Lambda_2)$. Lambda_1 is assumed to correspond to the more massive (primary) star m_1. Lambda_2 is for the secondary star m_2.
- RIFT.lalsimutils.load_resample_and_clean_psd(psd_fname, det, deltaF, verbose=False)
- RIFT.lalsimutils.lsu_StringFromPNOrder(order)
- RIFT.lalsimutils.m1m2(Mc, eta)
Compute component masses from Mc, eta. Returns m1 >= m2
- RIFT.lalsimutils.mass1(Mc, eta)
Compute larger component mass from Mc, eta
- RIFT.lalsimutils.mass2(Mc, eta)
Compute smaller component mass from Mc, eta
- RIFT.lalsimutils.mchirp(m1, m2)
Compute chirp mass from component masses
- RIFT.lalsimutils.mean_anomaly_from_true(true_anomaly, eccentricity)
- RIFT.lalsimutils.modes_to_k(modes)
- RIFT.lalsimutils.nextPow2(length)
Find next power of 2 <= length
- RIFT.lalsimutils.nhat(th, ph)
- RIFT.lalsimutils.non_herm_hoff(P)
Generate a FD waveform with two-sided spectrum. i.e. not assuming the Hermitian symmetry applies
- RIFT.lalsimutils.norm_hoff(P, IP, Fp=None, Fc=None, fwdplan=None)
Generate a normalized FD waveform from ChooseWaveformParams P. Will return a COMPLEX16FrequencySeries object.
If P.approx is a FD approximant, norm_hoff_FD is called. This path calls SimInspiralChooseFDWaveform
fwdplan must be None for FD approximants.
If P.approx is a TD approximant, norm_hoff_TD is called. This path calls ChooseTDWaveform and performs an FFT.
The TD waveform will be zero-padded so it’s Fourier transform has frequency bins of size P.deltaT. If P.deltaF == None, the TD waveform will be zero-padded to the next power of 2.
- RIFT.lalsimutils.norm_hoff_FD(P, IP, Fp=None, Fc=None)
Generate a FD waveform for a FD approximant normalized according to IP. Note that P.deltaF (which is None by default) must be set. IP and the waveform generated from P must have the same deltaF and
the waveform must extend to at least the highest frequency of IP’s PSD.
- RIFT.lalsimutils.norm_hoff_TD(P, IP, Fp=None, Fc=None, fwdplan=None)
Generate a waveform from ChooseWaveformParams P normalized according to inner product IP by creating a TD waveform, zero-padding and then Fourier transforming with FFTW3 forward FFT plan fwdplan. Returns a COMPLEX16FrequencySeries object.
If P.deltaF==None, just pad up to next power of 2 If P.deltaF = 1/X, will generate a TD waveform, zero-pad to length X seconds
and then FFT. Will throw an error if waveform is longer than X seconds
If you do not provide a forward FFT plan, one will be created. If you are calling this function many times, you may to create it once beforehand and pass it in, e.g.: fwdplan=lal.CreateForwardREAL8FFTPlan(TDlen,0)
You may pass in antenna patterns Fp, Fc. If none are provided, they will be computed from the information in ChooseWaveformParams.
- N.B. IP and the waveform generated from P must have the same deltaF and
the waveform must extend to at least the highest frequency of IP’s PSD.
- RIFT.lalsimutils.polar_angles_in_frame(frm, vec)
Take a vector in the default frame. Evaluate the polar angles of that unit vector in a new (orthonormal) frame ‘frm’. Not the fastest solution. Not naturally vectorizable.
- RIFT.lalsimutils.polar_angles_in_frame_alt(frm, theta, phi, xpy=<module 'numpy' from '/opt/hostedtoolcache/Python/3.11.18/x64/lib/python3.11/site-packages/numpy/__init__.py'>)
Take polar angles in the default frame. Evaluate the polar angles of that unit vector in a new (orthonormal) frame ‘frmInverse’. Probably easier to vectorize
- RIFT.lalsimutils.psd_windowing_factor(window_shape, TDlen)
[Implementing <w^2>, due to https://dcc.ligo.org/LIGO-T1900249] If a PSD is calculated using repeated instances of windowed data, the PSD will be biased downward (i.e., we have less noise than we expect) That’s fine and self-consistent if we will be analyzing data which has the same windowing applied. But if we’re not applying the same window shape to the data we analyze, we need to correct for the difference in noise actually present to the noise used to create the PSD.
Ths routine creates <w^2> for w a window shape. This could be computed much more efficiently (it is not memory-efficient), but this code is cleaner
- RIFT.lalsimutils.pylal_psd_to_swig_psd(raw_pylal_psd)
Why do I do a conversion? I am having trouble returning modified PSDs
- RIFT.lalsimutils.regularize_swig_psd_series_near_nyquist(raw_psd, DeltaFToZero)
regularize_psd_series_near_nyquist Near nyquist, some PSD bins are insane. As a temporary measure, I am going to use this routine to explicitly zero out those frequency bins, using a 30 Hz window near nyquist
- RIFT.lalsimutils.resample_psd_series(psd, df=None, fmin=None, fmax=None)
- RIFT.lalsimutils.rotate_hlm_static(hlm, alphaA, betaA, gammaA, extra_polarization=None)
Rotate output hlm by these Euler angles Note this is a full system rotation, and therefore should be associated with rotation of the physical quantities (e.g., spin vectors, J,L)
extra_polarization is applied at the end, as a multiplicative factor, if nonzero
- RIFT.lalsimutils.rotation_matrix(axis, theta)
- RIFT.lalsimutils.safe_int(mystr)
- RIFT.lalsimutils.sanitize_eta(eta, tol=1e-10, exception='error')
If ‘eta’ is slightly outside the physically allowed range for symmetric mass ratio, push it back in. If ‘eta’ is further outside the physically allowed range, throw an error or return a special value. Explicitly:
If ‘eta’ is in [tol, 0.25], return eta.
If ‘eta’ is in [0, tol], return tol.
If ‘eta’ in is (0.25, 0.25+tol], return 0.25
- If ‘eta’ < 0 OR eta > 0.25+tol,
if exception==’error’ raise a ValueError
if exception is anything else, return exception
- RIFT.lalsimutils.singleIFOSNR(data, psd, fNyq, fmin=None, fmax=None)
Calculate single IFO SNR using inner product class.
- RIFT.lalsimutils.std_and_conj_hlmoff(P, Lmax=2, **kwargs)
- RIFT.lalsimutils.stringGPSNice(tgps)
Return a string with nice formatting displaying the value of a LIGOTimeGPS
- RIFT.lalsimutils.symRatio(m1, m2)
Compute symmetric mass ratio from component masses
- RIFT.lalsimutils.symmetry_sign_exchange(coord_names)
- RIFT.lalsimutils.test_coord_output(x_out)
Checks if any of the x_out are -np.inf. Returns a boolean array [ True, False, False, …] with True if the corresponding coordinate row is ok, false otherwise
- RIFT.lalsimutils.tidal_lambda_from_tilde(mass1, mass2, lam_til, dlam_til)
Determine physical lambda parameters from effective parameters.
- RIFT.lalsimutils.tidal_lambda_tilde(mass1, mass2, lambda1, lambda2)
‘Effective’ lambda parameters. Lackey et al https://arxiv.org/pdf/1402.5156.pdf, Eq. (5,6).
- RIFT.lalsimutils.true_anomaly_from_eccentric(eccentric_anomaly, eccentricity)
- RIFT.lalsimutils.unit_frame()
- RIFT.lalsimutils.unwind_phase(phase, thresh=5.0)
Unwind an array of values of a periodic variable so that it does not jump discontinuously when it hits the periodic boundary, but changes smoothly outside the periodic range.
Note: ‘thresh’, which determines if a discontinuous jump occurs, should be somewhat less than the periodic interval. Empirically, 5 is usually a safe value of thresh for a variable with period 2 pi.
Fast method: take element-by-element differences, use mod 2 pi, and then add
- RIFT.lalsimutils.vecCross(v1, v2)
- RIFT.lalsimutils.vecDot(v1, v2)
- RIFT.lalsimutils.vecUnit(v)
- RIFT.lalsimutils.xml_to_ChooseWaveformParams_array(fname, minrow=None, maxrow=None, deltaT=0.000244140625, fref=0.0, lambda1=0.0, lambda2=0.0, waveFlags=None, nonGRparams=None, detector='H1', deltaF=None, fmax=0.0)
Function to read an xml file ‘fname’ containing a SimInspiralTable, convert rows of the SimInspiralTable into ChooseWaveformParams instances and return an array of the ChooseWaveformParam instances
Can optionally give ‘minrow’ and ‘maxrow’ to convert only rows in the range (starting from zero) [minrow, maxrow). If these arguments are not given, this function will convert the whole SimInspiral table.
The rest of the optional arguments are the fields in ChooseWaveformParams that are not present in SimInspiral tables. Any of these arguments not given values will use the standard default values of ChooseWaveformParams.