def gen_test_data(spin1x, approximant, mode_array): """ compute the difference between two waveforms and compare to expected value """ lalparams = lal.CreateDict() if (mode_array != None): ModeArray = lalsimulation.SimInspiralCreateModeArray() for mode in mode_array: lalsimulation.SimInspiralModeArrayActivateMode( ModeArray, mode[0], mode[1]) lalsimulation.SimInspiralWaveformParamsInsertModeArray( lalparams, ModeArray) common_pars = dict(m1=50 * lal.MSUN_SI, m2=30 * lal.MSUN_SI, s1x=spin1x, s1y=0., s1z=0., s2x=0., s2y=0., s2z=0., distance=1, inclination=np.pi / 3., phiRef=0., longAscNodes=0., eccentricity=0., meanPerAno=0., deltaT=1. / 4096., f_min=30., f_ref=30., params=lalparams, approximant=approximant) pars1 = common_pars.copy() pars2 = common_pars.copy() pars2.update({"inclination": 0.17}) pars2.update({"phiRef": 0.5}) hp1, hc1 = lalsimulation.SimInspiralChooseTDWaveform(**pars1) hp2, hc2 = lalsimulation.SimInspiralChooseTDWaveform(**pars2) # compute amp and phase hp1_amp, hp1_phase = get_amp_phase(hp1.data.data) hc1_amp, hc1_phase = get_amp_phase(hc1.data.data) hp2_amp, hp2_phase = get_amp_phase(hp2.data.data) hc2_amp, hc2_phase = get_amp_phase(hc2.data.data) hp_amp_diff = sum_sqr_diff(hp1_amp, hp2_amp) hp_phase_diff = sum_sqr_diff(hp1_phase, hp2_phase) hc_amp_diff = sum_sqr_diff(hc1_amp, hc2_amp) hc_phase_diff = sum_sqr_diff(hc1_phase, hc2_phase) return hp_amp_diff, hp_phase_diff, hc_amp_diff, hc_phase_diff
def tmplttime(f0, m1, m2, j1, j2, approx): dt = 1.0 / 16384.0 approximant = lalsim.GetApproximantFromString(approx) hp, hc = lalsim.SimInspiralChooseTDWaveform(phiRef=0, deltaT=dt, m1=m1, m2=m2, s1x=0, s1y=0, s1z=j1, s2x=0, s2y=0, s2z=j2, f_min=f0, f_ref=0, r=1, i=0, lambda1=0, lambda2=0, waveFlags=None, nonGRparams=None, amplitudeO=0, phaseO=0, approximant=approximant) h = numpy.array(hp.data.data, dtype=complex) h += 1j * numpy.array(hc.data.data, dtype=complex) try: n = list(abs(h)).index(0) except ValueError: n = len(h) return n * hp.deltaT
def get_SEOBNRv2_WF(q, M, chi1, chi2, f_start, deltaT=1. / (4096 * 4.)): m1 = q * M / (1 + q) m2 = M / (1 + q) hp, hc = lalsim.SimInspiralChooseTDWaveform( #where is its definition and documentation???? m1 * lalsim.lal.MSUN_SI, #m1 m2 * lalsim.lal.MSUN_SI, #m2 0., 0., chi1, #spin vector 1 0., 0., chi2, #spin vector 2 1e6 * lalsim.lal.PC_SI, #distance to source 0., #inclination 0., #phi 0., #longAscNodes 0., #eccentricity 0., #meanPerAno deltaT, # time incremental step f_start, # lowest value of freq f_start, #some reference value of freq (??) lal.CreateDict(), #some lal dictionary lalsim.SimInspiralGetApproximantFromString( 'SpinTaylorT4') #approx method for the model ) h_p, h_c = hp.data.data, hc.data.data times = np.linspace(0, len(h_c) * deltaT, len(h_c)) ph = np.unwrap(np.angle(h_p + 1j * h_c)) omega_22 = (ph[2] - ph[0]) / (2 * deltaT) print("FREQUENCY of THE WF (NP): ", omega_22, omega_22 / (2 * np.pi)) t_max = times[np.argmax(np.abs(h_p + 1j * h_c))] times = times - t_max return times, h_p + 1j * h_c
def _lalsim_td_waveform(**p): lal_pars = lal.CreateDict() if p['phase_order'] != -1: lalsimulation.SimInspiralWaveformParamsInsertPNPhaseOrder( lal_pars, int(p['phase_order'])) if p['amplitude_order'] != -1: lalsimulation.SimInspiralWaveformParamsInsertPNAmplitudeOrder( lal_pars, int(p['amplitude_order'])) if p['spin_order'] != -1: lalsimulation.SimInspiralWaveformParamsInsertPNSpinOrder( lal_pars, int(p['spin_order'])) if p['tidal_order'] != -1: lalsimulation.SimInspiralWaveformParamsInsertPNTidalOrder( lal_pars, p['tidal_order']) if p['eccentricity_order'] != -1: lalsimulation.SimInspiralWaveformParamsInsertPNEccentricityOrder( lal_pars, p['eccentricity_order']) if p['lambda1']: lalsimulation.SimInspiralWaveformParamsInsertPNTidalLambda1( lal_pars, p['lambda1']) if p['lambda2']: lalsimulation.SimInspiralWaveformParamsInsertPNTidalLambda2( lal_pars, p['lambda2']) if p['dquad_mon1']: lalsimulation.SimInspiralWaveformParamsInsertPNTidaldQuadMon1( lal_pars, p['dquad_mon1']) if p['dquad_mon2']: lalsimulation.SimInspiralWaveformParamsInsertPNTidaldQuadMon2( lal_pars, p['dquad_mon2']) if p['numrel_data']: lalsimulation.SimInspiralWaveformParamsInsertNumRelData( lal_pars, str(p['numrel_data'])) if p['modes_choice']: lalsimulation.SimInspiralWaveformParamsInsertModesChoice( lal_pars, p['modes_choice']) if p['frame_axis']: lalsimulation.SimInspiralWaveformParamsInsertFrameAxis( lal_pars, p['frame_axis']) if p['side_bands']: lalsimulation.SimInspiralWaveformParamsInsertSideband( lal_pars, p['side_bands']) #nonGRparams can be straightforwardly added if needed, however they have to # be invoked one by one hp1, hc1 = lalsimulation.SimInspiralChooseTDWaveform( float(pnutils.solar_mass_to_kg(p['mass1'])), float(pnutils.solar_mass_to_kg(p['mass2'])), float(p['spin1x']), float(p['spin1y']), float(p['spin1z']), float(p['spin2x']), float(p['spin2y']), float(p['spin2z']), pnutils.megaparsecs_to_meters(float(p['distance'])), float(p['inclination']), float(p['coa_phase']), float(p['long_asc_nodes']), float(p['eccentricity']), float(p['mean_per_ano']), float(p['delta_t']), float(p['f_lower']), float(p['f_ref']), lal_pars, _lalsim_enum[p['approximant']]) #lal.DestroyDict(lal_pars) hp = TimeSeries(hp1.data.data[:], delta_t=hp1.deltaT, epoch=hp1.epoch) hc = TimeSeries(hc1.data.data[:], delta_t=hc1.deltaT, epoch=hc1.epoch) return hp, hc
def generate_template(mass1, mass2, S, f_low, sample_rate, template_duration, approximant, amplitude_order, phase_order): template_length = sample_rate * template_duration if approximant == lalsimulation.TaylorF2: zf, _ = lalsimulation.SimInspiralChooseFDWaveform( 0, 1 / template_duration, mass1 * lal.LAL_MSUN_SI, mass2 * lal.LAL_MSUN_SI, 0, 0, 0, 0, 0, 0, f_low, 0, 1e6 * lal.LAL_PC_SI, 0, 0, 0, None, None, amplitude_order, phase_order, approximant) lal.ResizeCOMPLEX16FrequencySeries(zf, 0, template_length // 2 + 1) # Generate over-whitened template psd = lal.CreateREAL8FrequencySeries(None, zf.epoch, zf.f0, zf.deltaF, lal.lalDimensionlessUnit, len(zf.data.data)) psd.data.data = S(abscissa(psd)) zW = matched_filter_spa(zf, psd) elif approximant == lalsimulation.TaylorT4: hplus, hcross = lalsimulation.SimInspiralChooseTDWaveform( 0, 1 / sample_rate, mass1 * lal.LAL_MSUN_SI, mass2 * lal.LAL_MSUN_SI, 0, 0, 0, 0, 0, 0, f_low, f_low, 1e6 * lal.LAL_PC_SI, 0, 0, 0, None, None, amplitude_order, phase_order, approximant) ht = lal.CreateREAL8TimeSeries(None, lal.LIGOTimeGPS(-template_duration), hplus.f0, hplus.deltaT, hplus.sampleUnits, template_length) hf = lal.CreateCOMPLEX16FrequencySeries(None, lal.LIGOTimeGPS(0), 0, 0, lal.lalDimensionlessUnit, template_length // 2 + 1) plan = CreateForwardREAL8FFTPlan(template_length, 0) ht.data.data[:-len(hplus.data.data)] = 0 ht.data.data[-len(hplus.data.data):] = hplus.data.data lal.REAL8TimeFreqFFT(hf, ht, plan) psd = lal.CreateREAL8FrequencySeries(None, hf.epoch, hf.f0, hf.deltaF, lal.lalDimensionlessUnit, len(hf.data.data)) psd.data.data = S(abscissa(psd)) zWreal = matched_filter_real(hf, psd) ht.data.data[:-len(hcross.data.data)] = 0 ht.data.data[-len(hcross.data.data):] = hcross.data.data lal.REAL8TimeFreqFFT(hf, ht, plan) zWimag = matched_filter_real(hf, psd) zW = lal.CreateCOMPLEX16TimeSeries(None, zWreal.epoch, zWreal.f0, zWreal.deltaT, zWreal.sampleUnits, len(zWreal.data.data)) zW.data.data = zWreal.data.data + zWimag.data.data * 1j else: raise ValueError("unrecognized approximant") return zW.data.data[::-1].conj() * np.sqrt( 2) * template_duration / sample_rate / 2
def __init__(self, mass1, mass2, S, f_low, approximant, amplitude_order, phase_order): """Create a TaylorF2 signal model with the given masses, PSD function S(f), PN amplitude order, and low-frequency cutoff.""" if approximant == lalsimulation.TaylorF2: # Frequency-domain post-Newtonian inspiral waveform. h, _ = lalsimulation.SimInspiralChooseFDWaveform( 0, 1, mass1 * lal.LAL_MSUN_SI, mass2 * lal.LAL_MSUN_SI, 0, 0, 0, 0, 0, 0, f_low, 0, 1e6 * lal.LAL_PC_SI, 0, 0, 0, None, None, amplitude_order, 0, approximant) # Find indices of first and last nonzero samples. nonzero = np.nonzero(h.data.data)[0] first_nonzero = nonzero[0] last_nonzero = nonzero[-1] elif approximant == lalsimulation.TaylorT4: # Time-domain post-Newtonian inspiral waveform. hplus, hcross = lalsimulation.SimInspiralChooseTDWaveform( 0, 1 / 4096, mass1 * lal.LAL_MSUN_SI, mass2 * lal.LAL_MSUN_SI, 0, 0, 0, 0, 0, 0, f_low, f_low, 1e6 * lal.LAL_PC_SI, 0, 0, 0, None, None, amplitude_order, phase_order, approximant) hplus.data.data += hcross.data.data hplus.data.data /= np.sqrt(2) h = lal.CreateCOMPLEX16FrequencySeries( None, lal.LIGOTimeGPS(0), 0, 0, lal.lalDimensionlessUnit, len(hplus.data.data) // 2 + 1) plan = CreateForwardREAL8FFTPlan(len(hplus.data.data), 0) lal.REAL8TimeFreqFFT(h, hplus, plan) f = h.f0 + len(h.data.data) * h.deltaF first_nonzero = long(np.floor((f_low - h.f0) / h.deltaF)) last_nonzero = long(np.ceil((2048 - h.f0) / h.deltaF)) last_nonzero = min(last_nonzero, len(h.data.data) - 1) else: raise ValueError("unrecognized approximant") # Frequency sample points self.dw = 2 * np.pi * h.deltaF f = h.f0 + h.deltaF * np.arange(first_nonzero, last_nonzero + 1) self.w = 2 * np.pi * f # Throw away leading and trailing zeros. h = h.data.data[first_nonzero:last_nonzero + 1] self.denom_integrand = 4 / (2 * np.pi) * (np.square(h.real) + np.square(h.imag)) / S(f) self.den = np.trapz(self.denom_integrand, dx=self.dw)
def _lalsim_td_waveform(**p): hp, hc = lalsimulation.SimInspiralChooseTDWaveform( float(p['phi0']), float(p['delta_t']), float(solar_mass_to_kg(p['mass1'])), float(solar_mass_to_kg(p['mass2'])), float(p['spin1x']), float(p['spin1y']), float(p['spin1z']), float(p['spin2x']), float(p['spin2y']), float(p['spin2z']), float(p['f_lower']), 0, parsecs_to_meters(float(p['distance'])), float(p['inclination']), 0, 0, None, None, int(p['amplitude_order']), int(p['phase_order']), _lalsim_enum[p['approximant']]) hp = TimeSeries(hp.data.data, delta_t=hp.deltaT, epoch=hp.epoch) hc = TimeSeries(hc.data.data, delta_t=hc.deltaT, epoch=hc.epoch) return hp, hc
def _lalsim_td_waveform(**p): fail_tolerant_waveform_generation lal_pars = _check_lal_pars(p) #nonGRparams can be straightforwardly added if needed, however they have to # be invoked one by one try: hp1, hc1 = lalsimulation.SimInspiralChooseTDWaveform( float(pnutils.solar_mass_to_kg(p['mass1'])), float(pnutils.solar_mass_to_kg(p['mass2'])), float(p['spin1x']), float(p['spin1y']), float(p['spin1z']), float(p['spin2x']), float(p['spin2y']), float(p['spin2z']), pnutils.megaparsecs_to_meters(float(p['distance'])), float(p['inclination']), float(p['coa_phase']), float(p['long_asc_nodes']), float(p['eccentricity']), float(p['mean_per_ano']), float(p['delta_t']), float(p['f_lower']), float(p['f_ref']), lal_pars, _lalsim_enum[p['approximant']]) except RuntimeError: if not fail_tolerant_waveform_generation: raise # For some cases failure modes can occur. Here we add waveform-specific # instructions to try to work with waveforms that are known to fail. if 'SEOBNRv3' in p['approximant']: # Try doubling the sample time and redoing. # Don't want to get stuck in a loop though! if 'delta_t_orig' not in p: p['delta_t_orig'] = p['delta_t'] p['delta_t'] = p['delta_t'] / 2. if p['delta_t_orig'] / p['delta_t'] > 9: raise hp, hc = _lalsim_td_waveform(**p) p['delta_t'] = p['delta_t_orig'] hp = resample_to_delta_t(hp, hp.delta_t*2) hc = resample_to_delta_t(hc, hc.delta_t*2) return hp, hc raise #lal.DestroyDict(lal_pars) hp = TimeSeries(hp1.data.data[:], delta_t=hp1.deltaT, epoch=hp1.epoch) hc = TimeSeries(hc1.data.data[:], delta_t=hc1.deltaT, epoch=hc1.epoch) return hp, hc
def _lalsim_td_waveform(**p): flags = lalsimulation.SimInspiralCreateWaveformFlags() lalsimulation.SimInspiralSetSpinOrder(flags, p['spin_order']) lalsimulation.SimInspiralSetTidalOrder(flags, p['tidal_order']) ########### def rulog2(val): return 2.0**numpy.ceil(numpy.log2(float(val))) f_final = rulog2(seobnrrom_final_frequency(**p)) f_nyq = 0.5 / p['delta_t'] if f_final > f_nyq: print 'Final frequecny {0} is greater than given nyquist frequecny {1}'.format( f_final, f_nyq) p['delta_t'] = 0.5 / f_final ########## if p['numrel_data']: lalsimulation.SimInspiralSetNumrelData(flags, str(p['numrel_data'])) hp1, hc1 = lalsimulation.SimInspiralChooseTDWaveform( float(p['coa_phase']), float(p['delta_t']), float(pnutils.solar_mass_to_kg(p['mass1'])), float(pnutils.solar_mass_to_kg(p['mass2'])), float(p['spin1x']), float(p['spin1y']), float(p['spin1z']), float(p['spin2x']), float(p['spin2y']), float(p['spin2z']), float(p['f_lower']), float(p['f_ref']), pnutils.megaparsecs_to_meters(float(p['distance'])), float(p['inclination']), float(p['lambda1']), float(p['lambda2']), flags, None, int(p['amplitude_order']), int(p['phase_order']), _lalsim_enum[p['approximant']]) hp = TimeSeries(hp1.data.data[:], delta_t=hp1.deltaT, epoch=hp1.epoch) hc = TimeSeries(hc1.data.data[:], delta_t=hc1.deltaT, epoch=hc1.epoch) if f_final > f_nyq: p['delta_t'] = 0.5 / f_nyq print "Need to resample at delta_t {0}".format(p['delta_t']) hp = resample_to_delta_t(hp, p['delta_t']) hc = resample_to_delta_t(hc, p['delta_t']) return hp, hc
def _lalsim_td_waveform(**p): flags = lalsimulation.SimInspiralCreateWaveformFlags() lalsimulation.SimInspiralSetSpinOrder(flags, p['spin_order']) lalsimulation.SimInspiralSetTidalOrder(flags, p['tidal_order']) hp, hc = lalsimulation.SimInspiralChooseTDWaveform( float(p['coa_phase']), float(p['delta_t']), float(pnutils.solar_mass_to_kg(p['mass1'])), float(pnutils.solar_mass_to_kg(p['mass2'])), float(p['spin1x']), float(p['spin1y']), float(p['spin1z']), float(p['spin2x']), float(p['spin2y']), float(p['spin2z']), float(p['f_lower']), float(p['f_ref']), pnutils.megaparsecs_to_meters(float(p['distance'])), float(p['inclination']), float(p['lambda1']), float(p['lambda2']), flags, None, int(p['amplitude_order']), int(p['phase_order']), _lalsim_enum[p['approximant']]) hp = TimeSeries(hp.data.data[:] * 1, delta_t=hp.deltaT, epoch=hp.epoch) hc = TimeSeries(hc.data.data[:] * 1, delta_t=hc.deltaT, epoch=hc.epoch) return hp, hc
def _lalsim_td_waveform(**p): lal_pars = _check_lal_pars(p) #nonGRparams can be straightforwardly added if needed, however they have to # be invoked one by one hp1, hc1 = lalsimulation.SimInspiralChooseTDWaveform( float(pnutils.solar_mass_to_kg(p['mass1'])), float(pnutils.solar_mass_to_kg(p['mass2'])), float(p['spin1x']), float(p['spin1y']), float(p['spin1z']), float(p['spin2x']), float(p['spin2y']), float(p['spin2z']), pnutils.megaparsecs_to_meters(float(p['distance'])), float(p['inclination']), float(p['coa_phase']), float(p['long_asc_nodes']), float(p['eccentricity']), float(p['mean_per_ano']), float(p['delta_t']), float(p['f_lower']), float(p['f_ref']), lal_pars, _lalsim_enum[p['approximant']]) #lal.DestroyDict(lal_pars) hp = TimeSeries(hp1.data.data[:], delta_t=hp1.deltaT, epoch=hp1.epoch) hc = TimeSeries(hc1.data.data[:], delta_t=hc1.deltaT, epoch=hc1.epoch) return hp, hc
def generate_LAL_waveform(approximant, q, chiA0, chiB0, dt, M, \ dist_mpc, f_low, f_ref, inclination=0, phi_ref=0., ellMax=None, \ single_mode=None): distance = dist_mpc * 1.0e6 * PC_SI approxTag = lalsim.SimInspiralGetApproximantFromString(approximant) # component masses of the binary m1_kg = M * MSUN_SI * q / (1. + q) m2_kg = M * MSUN_SI / (1. + q) if single_mode is not None and ellMax is not None: raise Exception("Specify only one of single_mode or ellMax") dictParams = lal.CreateDict() # If ellMax, load all modes with ell<=ellMax if ellMax is not None: ma = lalsim.SimInspiralCreateModeArray() for ell in range(2, ellMax + 1): lalsim.SimInspiralModeArrayActivateAllModesAtL(ma, ell) lalsim.SimInspiralWaveformParamsInsertModeArray(dictParams, ma) elif single_mode is not None: # If a single_mode is given, load only that mode (l,m) and (l,-m) dictParams = set_single_mode(dictParams, single_mode[0], single_mode[1]) hp, hc = lalsim.SimInspiralChooseTDWaveform(\ m1_kg, m2_kg, chiA0[0], chiA0[1], chiA0[2], \ chiB0[0], chiB0[1], chiB0[2], \ distance, inclination, phi_ref, 0, 0, 0,\ dt, f_low, f_ref, dictParams, approxTag) h = np.array(hp.data.data - 1.j * hc.data.data) t = dt * np.arange(len(h)) return t, h
def time_domain_oscillatory(self, delta_t=None, modes=None, inc=None, phase=None): """ Get the mode decomposition of the waveform approximant. Since the waveforms we consider only contain content about the ell=|m|=2 modes. We can therefore evaluate the waveform for a face-on system, where only the (2, 2) mode is non-zero. Parameters ---------- delta_t: float, optional Time step for waveform. modes: list, optional List of modes to try to generate. inc: float, optional Inclination of the source, if None, the spherical harmonic modes will be returned. phase: float, optional Phase at coalescence of the source, if None, the spherical harmonic modes will be returned. Returns ------- h_lm: dict Spin-weighted spherical harmonic decomposed waveform. times: np.array Times on which waveform is evaluated. """ if self.h_lm is None: if modes is None: modes = self.available_modes else: modes = modes if not set(modes).issubset(self.available_modes): print('Requested {} unavailable modes'.format(' '.join( set(modes).difference(self.available_modes)))) modes = list(set(modes).union(self.available_modes)) print('Using modes {}'.format(' '.join(modes))) fmin, fRef = 20, 20 theta = 0.0 phi = 0.0 longAscNodes = 0.0 eccentricity = 0.0 meanPerAno = 0.0 approx = lalsim.GetApproximantFromString(self.name) WFdict = None if delta_t is None: delta_t = 0.1 * (self.m1_SI + self.m2_SI) * utils.GG /\ utils.CC ** 3 else: delta_t = delta_t hplus, hcross = lalsim.SimInspiralChooseTDWaveform( self.m1_SI, self.m2_SI, self.S1[0], self.S1[1], self.S1[2], self.S2[0], self.S2[1], self.S2[2], self.distance_SI, theta, phi, longAscNodes, eccentricity, meanPerAno, delta_t, fmin, fRef, WFdict, approx) h = hplus.data.data - 1j * hcross.data.data h_22 = h / harmonics.sYlm(-2, 2, 2, theta, phi) times = np.linspace(0, delta_t * len(h), len(h)) times -= times[np.argmax(abs(h_22))] h_lm = {(2, 2): h_22, (2, -2): np.conjugate(h_22)} else: h_lm = self.h_lm times = self.times if inc is None or phase is None: return h_lm, times else: return combine_modes(h_lm, inc, phase), times
def gen_test_data(): """ compute the difference between two waveforms and compare to expected value """ common_pars = dict(m1=50 * lal.MSUN_SI, m2=30 * lal.MSUN_SI, s1x=0, s1y=0, s1z=-0.45, s2x=0, s2y=0, s2z=0.98, distance=1, inclination=0., phiRef=0., longAscNodes=0., eccentricity=0., meanPerAno=0., deltaT=1. / 4096., f_min=30., f_ref=30., params=None, approximant=lalsimulation.TEOBResumS) pars1 = common_pars.copy() pars2 = common_pars.copy() pars2.update({"m2": 20. * lal.MSUN_SI}) hp1, hc1 = lalsimulation.SimInspiralChooseTDWaveform(**pars1) hp2, hc2 = lalsimulation.SimInspiralChooseTDWaveform(**pars2) # compute amp and phase hp1_amp, hp1_phase = get_amp_phase(hp1.data.data) hc1_amp, hc1_phase = get_amp_phase(hc1.data.data) hp2_amp, hp2_phase = get_amp_phase(hp2.data.data) hc2_amp, hc2_phase = get_amp_phase(hc2.data.data) npeak1 = np.argmax(hp1_amp) npeak2 = np.argmax(hp2_amp) ni = min(npeak1, npeak2) no = min(hp1.data.length - npeak1, hp2.data.length - npeak2) # Truncate and align waveforms in place w.r.t. peak hp1_amp = hp1_amp[npeak1 - ni:npeak1 + no] hc1_amp = hc1_amp[npeak1 - ni:npeak1 + no] hp2_amp = hp2_amp[npeak2 - ni:npeak2 + no] hc2_amp = hc2_amp[npeak2 - ni:npeak2 + no] hp1_phase = hp1_phase[npeak1 - ni:npeak1 + no] hc1_phase = hc1_phase[npeak1 - ni:npeak1 + no] hp2_phase = hp2_phase[npeak2 - ni:npeak2 + no] hc2_phase = hc2_phase[npeak2 - ni:npeak2 + no] hp_amp_diff = sum_sqr_diff(hp1_amp, hp2_amp) hp_phase_diff = sum_sqr_diff(hp1_phase, hp2_phase) hc_amp_diff = sum_sqr_diff(hc1_amp, hc2_amp) hc_phase_diff = sum_sqr_diff(hc1_phase, hc2_phase) # since we want to compare decimals, we return the above quantities as 0.xxxxx.. # by dividing them for their order of magnitude +1 return hp_amp_diff / 1e6, hp_phase_diff / 1e3, hc_amp_diff / 1e6, hc_phase_diff / 1e3
def gen_bbh(fs, T_obs, psd, isnr=1.0, det='H1', beta=[0.8, 1.0], par=None): """ generates a BBH timedomain signal """ N = T_obs * fs # the total number of time samples dt = 1 / fs # the sampling time (sec) f_low = 12.0 # lowest frequency of waveform (Hz) amplitude_order = 0 phase_order = 7 approximant = lalsimulation.IMRPhenomD dist = 1e6 * lal.PC_SI # put it as 1 MPc # make waveform # loop until we have a long enough waveform - slowly reduce flow as needed flag = False while not flag: hp, hc = lalsimulation.SimInspiralChooseTDWaveform( par.m1 * lal.MSUN_SI, par.m2 * lal.MSUN_SI, 0, 0, 0, 0, 0, 0, dist, par.iota, 0, 0, 0, 0, 1 / fs, f_low, f_low, lal.CreateDict(), approximant) flag = True if hp.data.length > 2 * N else False f_low -= 1 # decrease by 1 Hz each time hp = hp.data.data hc = hc.data.data # compute reference idx ref_idx = np.argmax(hp**2 + hc**2) # make signal - apply antenna and shifts ht_shift, hp_shift, hc_shift = make_bbh(hp, hc, fs, par.ra, par.dec, par.psi, det) # place signal into timeseries - including shift ts = np.zeros(N) hp = np.zeros(N) hc = np.zeros(N) ht_temp = ht_shift[int(ref_idx - par.idx):] hp_temp = hp_shift[int(ref_idx - par.idx):] hc_temp = hc_shift[int(ref_idx - par.idx):] if len(ht_temp) < N: ts[:len(ht_temp)] = ht_temp hp[:len(ht_temp)] = hp_temp hc[:len(ht_temp)] = hc_temp else: ts = ht_temp[:N] hp = hp_temp[:N] hc = hc_temp[:N] # the start index of the central region sidx = int(0.5 * fs * T_obs * (safe - 1.0) / safe) # apply aggressive window to cut out signal in central region # window is non-flat for 1/8 of desired Tobs # the window has dropped to 50% at the Tobs boundaries win = np.zeros(N) tempwin = tukey(int((16.0 / 15.0) * N / safe), alpha=1.0 / 8.0) win[int((N - tempwin.size) / 2):int((N - tempwin.size) / 2) + tempwin.size] = tempwin ts *= win hp *= win hc *= win # compute SNR of pre-whitened data intsnr = get_snr(ts, T_obs, fs, psd.data.data, par.fmin) # normalise the waveform using either integrated or peak SNR intsnr = np.array(intsnr) scale = isnr / intsnr ts *= scale hp *= scale hc *= scale intsnr *= scale print '{}: computed the network SNR = {}'.format(time.asctime(), isnr) return ts, hp, hc
def generate_waveform(m1, m2, s1=0., s2=0., d=1., iota=0., phi_0=0., t_coal=0.4, t_step=5e-5, f_min=None, t_min=None, verbose=False, approx="SEOBNRv2_opt"): """ generate_waveform ================= Wrapper to lalsimulation.SimInspiralChooseTDWaveform() to generate a single waveform. Wave is not preprocessed. Input: m1,m2,s1,s2,d,iota,phi_0 orbital parameters t_coal approximate time to coalescence in reduced grid (ignored if f_min or t_min is set) t_step EOB integration time to be given to lal f_min starting frequency in Hz (if None, it will be determined by t_coal; ignored if t_min is set) t_min starting time in s (if None, t_coal will be returned) verbose whether to print messages for each wave... Output: times (D,) times at which wave is evaluated h_p (N,D) plus polarization of the wave h_c (N,D) cross polarization of the wave """ import lal import lalsimulation as lalsim q = m1 / m2 mtot = (m1 + m2) #*lal.MTSUN_SI mc = (m1 * m2)**(3. / 5.) / (m1 + m2)**(1. / 5.) mc /= 1.21 #M_c / 1.21 M_sun if t_min is not None: f_min = .8 * ((151 * (t_min / mtot)**(-3. / 8.) * (((1 + q)**2) / q)**(3. / 8.)) / mtot) if f_min is None: f_min = .9 * ((151 * (t_coal)**(-3. / 8.) * (((1 + q)**2) / q)**(3. / 8.)) / mtot) if verbose: print("Generating wave @: ", m1, m2, s1, s2, d, iota, phi_0) hp, hc = lalsim.SimInspiralChooseTDWaveform( #where is its definition and documentation???? m1 * lalsim.lal.MSUN_SI, #m1 m2 * lalsim.lal.MSUN_SI, #m2 0., 0., s1, #spin vector 1 0., 0., s2, #spin vector 2 d * 1e6 * lalsim.lal.PC_SI, #distance to source iota, #inclination phi_0, #phi 0., #longAscNodes 0., #eccentricity 0., #meanPerAno t_step, # time incremental step f_min, # lowest value of freq f_min, #some reference value of freq (??) lal.CreateDict(), #some lal dictionary lalsim.GetApproximantFromString(approx) #approx method for the model ) h_p, h_c = hp.data.data, hc.data.data amp = np.sqrt(h_p**2 + h_c**2) #(indices, ) = np.where(amp!=0) #trimming zeros of amplitude #h_p = h_p[indices] #h_c = h_c[indices] times = np.linspace(0.0, h_p.shape[0] * t_step, h_p.shape[0]) #time actually t_m = times[np.argmax(amp)] times = times - t_m if t_min is not None: arg = np.argmin(np.abs(times + t_min)) else: arg = 0 return times[arg:], h_p[arg:], h_c[arg:]
def create_dataset_TD(N_data, N_grid, filename=None, t_coal=0.5, q_range=(1., 5.), m2_range=None, s1_range=(-0.8, 0.8), s2_range=(-0.8, 0.8), t_step=1e-5, approximant="SEOBNRv2_opt", alpha=0.35, path_TEOBResumS=None): """ create_dataset_TD ================= Create a dataset for training a ML model to fit GW waveforms in time domain. The dataset consists in 3 parameters theta=(q, spin1z, spin2z) associated to the waveform computed in frequency domain for a grid of N_grid points in the range given by the user. More specifically, data are stored in 3 vectors: theta_vector vector holding source parameters q, spin1, spin2 amp_vector vector holding amplitudes for each source evaluated at some N_grid equally spaced points ph_vector vector holding phase for each source evaluated at some N_grid equally spaced points This routine add N_data data to filename if one is specified (if file is not empty it must contain data with the same N_grid); otherwise the datasets are returned as np vectors. All the waves are evaluated at a constant distance of 1Mpc. Values of q and m2 as well as spins are drawn randomly in the range given by the user: it holds m1 = q *m2 M_sun. The waveforms are computed with a time step t_step; starting from a frequency f_min (set by the routine according to t_coal and m_tot). Waves are given in a rescaled time grid (i.e. t/m_tot) with N_grid points: t=0 occurs when at time of maximum amplitude. A higher density of grid points is placed in the post merger phase. Dataset can be generated either with a lal method (the approximant should be specified by the approximant keyword) either with an implementation of TEOBResumS (in this case a path to a local installation of TEOBResumS should be provided). If lal is used, lalsuite package shall be installed (note that lalsuite is not a prerequisite for mlgw) Dataset can be loaded with load_dataset. Input: N_data size of dataset N_grid number of grid points to evaluate filename name of the file to save dataset in (If is None, nothing is saved on a file) t_coal time to coalescence to start computation from (measured in reduced grid) q_range tuple with range for random q values. if single value, q is kept fixed at that value m2_range tuple with range for random m2 values. if single value, m2 is kept fixed at that value. If None, m2 will be chosen s.t. m_tot = m1+m2 = 20. M_sun spin_mag_max_1 tuple with range for random spin #1 values. if single value, s1 is kept fixed at that value spin_mag_max_2 tuple with range for random spin #1 values. if single value, s2 is kept fixed at that value t_step time step to generate the wave with approximant string for the approximant model to be used (in lal convention; to be used only if lal ought to be used) alpha distorsion factor for time grid. (In range (0,1], when it's close to 0, more grid points are around merger) path_TEOBResumS path to a local installation of TEOBResumS with routine 'EOBRun_module' (if given, it overwrites the aprroximant entry) Output: if filename is given None if filename is not given theta_vector (N_data,3) vector holding ordered set of parameters used to generate amp_dataset and ph_dataset amp_dataset (N_data,N_grid) dataset with amplitudes ph_dataset (N_data,N_grid) dataset with phases times (N_grid,) vector holding times at which waves are evaluated (t=0 is the time of maximum amplitude) """ d = 1. inclination = 0. #np.pi/2. if path_TEOBResumS is not None: approximant = "TEOBResumS" if approximant == "TEOBResumS": #see https://bitbucket.org/eob_ihes/teobresums/src/development/ for the implementation of TEOBResumS try: import sys sys.path.append( path_TEOBResumS) #path to local installation of TEOBResumS import EOBRun_module except: raise RuntimeError( "No valid imput source for module 'EOBRun_module' for TEOBResumS. Unable to continue." ) else: try: import lal import lalsimulation as lalsim except: raise RuntimeError( "Impossible to load lalsimulation: try pip install lalsuite") LALpars = lal.CreateDict() approx = lalsim.SimInspiralGetApproximantFromString(approximant) #checking if N_grid is fine if not isinstance(N_grid, int): raise TypeError("N_grid is " + str(type(N_grid)) + "! Expected to be a int.") if isinstance(m2_range, tuple): D_theta = 4 #m2 must be included as a feature else: D_theta = 3 #creating time_grid t_end = 5.2e-4 #estimated maximum time for ringdown: WF will be killed after that time #t_end = 6e-5 #ONLY FOR mode = 3 (very ugly here...) time_grid = np.linspace(-np.power(np.abs(t_coal), alpha), np.power(t_end, alpha), N_grid) time_grid = np.multiply(np.sign(time_grid), np.power(np.abs(time_grid), 1. / alpha)) #adding 0 to time grid index_0 = np.argmin(np.abs(time_grid)) time_grid[index_0] = 0. #0 is alway set in the grid #setting t_coal_freq for generating a waves if np.abs(t_coal) < 0.05: t_coal_freq = 0.05 else: t_coal_freq = np.abs(t_coal) if filename is not None: #doing header if file is empty - nothing otherwise if not os.path.isfile( filename ): #file doesn't exist: must be created with proper header filebuff = open(filename, 'w') print("New file ", filename, " created") freq_header = np.concatenate((np.zeros( (3, )), time_grid, time_grid)) freq_header = np.reshape(freq_header, (1, len(freq_header))) np.savetxt(filebuff, freq_header, header="# row: theta " + str(D_theta) + " | amp (1," + str(N_grid) + ")| ph (1," + str(N_grid) + ")\n# N_grid = " + str(N_grid) + " | t_coal =" + str(t_coal) + " | t_step =" + str(t_step) + " | q_range = " + str(q_range) + " | m2_range = " + str(m2_range) + " | s1_range = " + str(s1_range) + " | s2_range = " + str(s2_range), newline='\n') else: filebuff = open(filename, 'a') if filename is None: amp_dataset = np.zeros( (N_data, N_grid)) #allocating storage for returning data ph_dataset = np.zeros((N_data, N_grid)) theta_vector = np.zeros((N_data, D_theta)) for i in range(N_data): #loop on data to be created if i % 50 == 0 and i != 0: #if i%1 == 0 and i != 0: #debug print("Generated WF ", i) #setting value for data if isinstance(m2_range, tuple): m2 = np.random.uniform(m2_range[0], m2_range[1]) elif m2_range is not None: m2 = float(m2_range) if isinstance(q_range, tuple): q = np.random.uniform(q_range[0], q_range[1]) else: q = float(q_range) if isinstance(s1_range, tuple): spin1z = np.random.uniform(s1_range[0], s1_range[1]) else: spin1z = float(s1_range) if isinstance(s2_range, tuple): spin2z = np.random.uniform(s2_range[0], s2_range[1]) else: spin2z = float(s2_range) if m2_range is None: m2 = 20. / (1 + q) m1 = q * m2 else: m1 = q * m2 #computing f_min f_min = .9 * ((151 * (t_coal_freq)**(-3. / 8.) * (((1 + q)**2) / q)**(3. / 8.)) / (m1 + m2)) #in () there is the right scaling formula for frequency in order to get always the right reduced time #this should be multiplied by a prefactor (~1) for dealing with some small variation due to spins #getting the wave if approximant != "TEOBResumS": #using lal to create WFs hptilde, hctilde = lalsim.SimInspiralChooseTDWaveform( #where is its definition and documentation???? m1 * lalsim.lal.MSUN_SI, #m1 m2 * lalsim.lal.MSUN_SI, #m2 0., 0., spin1z, #spin vector 1 0., 0., spin2z, #spin vector 2 d * 1e6 * lalsim.lal.PC_SI, #distance to source inclination, #inclination 0., #phi ref 0., #longAscNodes 0., #eccentricity 0., #meanPerAno t_step, # time incremental step f_min, # lowest value of time f_min, #some reference value of time (??) lal.CreateDict(), #some lal dictionary approx #approx method for the model ) #print(f_min, t_step)#debug #print(m1,m2, spin1z,spin2z) #debug h_p, h_c = np.array(hptilde.data.data), np.array( hctilde.data.data) #complex waveform time_full = np.linspace( 0.0, hptilde.data.length * t_step, hptilde.data.length) #time grid at which wave is computed if approximant == "TEOBResumS": #using TEOBResumS mode = 1 pars = { 'M': m1 + m2, 'q': m1 / m2, 'Lambda1': 0., 'Lambda2': 0., 'chi1': spin1z, 'chi2': spin2z, 'domain': 0, # TD 'arg_out': 0, # Output hlm/hflm. Default = 0 'use_mode_lm': [mode], # List of modes to use/output through EOBRunPy 'srate_interp': 1. / t_step, # srate at which to interpolate. Default = 4096. 'use_geometric_units': 0, # Output quantities in geometric units. Default = 1 'initial_frequency': f_min, # in Hz if use_geometric_units = 0, else in geometric units 'interp_uniform_grid': 2, # Interpolate mode by mode on a uniform grid. Default = 0 (no interpolation) 'distance': d, 'inclination': inclination, #'nqc':2, #{"no", "auto", "manual"} #'nqc_coefs_flx': 2, # {"none", "nrfit_nospin20160209", "fit_spin_202002", "fromfile"} #'nqc_coefs_hlm':0 } if mode != 1: warnings.warn("Using non dominant mode " + str(mode)) time_full, h_p, h_c = EOBRun_module.EOBRunPy(pars) if isinstance(m2_range, tuple): temp_theta = [m1, m2, spin1z, spin2z] else: temp_theta = [m1 / m2, spin1z, spin2z] temp_amp = np.sqrt(np.square(h_p) + np.square(h_c)) temp_ph = np.unwrap(np.arctan2(h_c, h_p)) time_full = (time_full - time_full[np.argmax(temp_amp)]) / ( m1 + m2) #grid is scaled to standard grid #setting waves to the chosen std grid temp_amp = np.interp(time_grid, time_full, temp_amp) temp_ph = np.interp(time_grid, time_full, temp_ph) #here you need to decide what is better #temp_ph = temp_ph - temp_ph[0] #all phases are shifted by a constant to make every wave start with 0 phase id0 = np.where(time_grid == 0)[0] temp_ph = temp_ph - temp_ph[ id0] #all phases are shifted by a constant to make every wave start with 0 phase at t=0 (i.e. at maximum amplitude) #removing spourious gaps (if present) (do I need it??) (index, ) = np.where( temp_amp / np.max(temp_amp) < 1e-10) #there should be a way to choose the right threshold... if len(index) > 0: #print("Wave killed") temp_amp[index] = 0 #temp_amp[index[0]-1] temp_ph[index] = temp_ph[index[0] - 1] if filename is None: amp_dataset[ i, :] = temp_amp #putting waveform in the dataset to return ph_dataset[i, :] = temp_ph #phase theta_vector[i, :] = temp_theta if filename is not None: #saving to file to_save = np.concatenate((temp_theta, temp_amp, temp_ph)) to_save = np.reshape(to_save, (1, len(to_save))) np.savetxt(filebuff, to_save) if filename is None: return theta_vector, amp_dataset.real, ph_dataset.real, time_grid else: filebuff.close() return None
# add what we need p = default_args p['mass1']=10. p['mass2']=10. p['delta_t'] = 1./4096 p['f_lower'] = 40. p['approximant']='IMRPhenomD' lal_pars = _check_lal_pars(p) # make the waveform hp1, hc1 = lalsimulation.SimInspiralChooseTDWaveform( float(pnutils.solar_mass_to_kg(p['mass1'])), float(pnutils.solar_mass_to_kg(p['mass2'])), float(p['spin1x']), float(p['spin1y']), float(p['spin1z']), float(p['spin2x']), float(p['spin2y']), float(p['spin2z']), pnutils.megaparsecs_to_meters(float(p['distance'])), float(p['inclination']), float(p['coa_phase']), float(p['long_asc_nodes']), float(p['eccentricity']), float(p['mean_per_ano']), float(p['delta_t']), float(p['f_lower']), float(p['f_ref']), lal_pars, _lalsim_enum[p['approximant']]) hp = TimeSeries(hp1.data.data[:], delta_t=hp1.deltaT, epoch=hp1.epoch) ''' p['dchi0'] = 1 lal_pars = _check_lal_pars(p) sp1, sc1 = lalsimulation.SimInspiralChooseTDWaveform( float(pnutils.solar_mass_to_kg(p['mass1'])), float(pnutils.solar_mass_to_kg(p['mass2'])), float(p['spin1x']), float(p['spin1y']), float(p['spin1z']), float(p['spin2x']), float(p['spin2y']), float(p['spin2z']),
def generate_waveform(m1, m2, s1=0.): q = m1 / m2 mtot = (m1 + m2) #*lal.MTSUN_SI mc = (m1 * m2)**(3. / 5.) / (m1 + m2)**(1. / 5.) mc /= 1.21 #M_c / 1.21 M_sun print(m1, m2, mc, mtot) print(mc**(-5. / 8.) * mtot**(-3. / 8.), (((1 + q)**2) / q)**(3. / 8.) / mtot) # f_min = 134 * mc **(-5./8.)*(1.2)**(-3./8.) * mtot**(-3.8) f_min = .9 * ((151 * (.25)**(-3. / 8.) * (((1 + q)**2) / q)**(3. / 8.)) / mtot) #in () there is the right scaling formula for frequency in order to get always the right reduced time #it should be multiplied by a prefactor for dealing with some small variation in spin #sounds like a good choice... and also it is able to reduce erorrs in phase reconstruction print(f_min) hptilde, hctilde = lalsim.SimInspiralChooseTDWaveform( #where is its definition and documentation???? m1 * lalsim.lal.MSUN_SI, #m1 m2 * lalsim.lal.MSUN_SI, #m2 0., 0., s1, #spin vector 1 0., 0., 0., #spin vector 2 1. * 1e6 * lalsim.lal.PC_SI, #distance to source 0., #inclination 0., #phi ref 0., #longAscNodes 0., #eccentricity 0., #meanPerAno 5e-5, # time incremental step f_min, # lowest value of freq f_min, #some reference value of freq (??) lal.CreateDict(), #some lal dictionary # lalsim.GetApproximantFromString('IMRPHenomPv2') #approx method for the model lalsim.GetApproximantFromString('SEOBNRv2_opt' ) #approx method for the model ) h = (hptilde.data.data + 1j * hctilde.data.data) (indices, ) = np.where(np.abs(h) != 0) #trimming zeros of amplitude h = h[indices] time_full = np.linspace(0.0, h.shape[0] * 5e-5, h.shape[0]) #time actually t_m = time_full[np.argmax(np.abs(h))] time_full = time_full - t_m #[-???,??] #building a proper time grid split_point = -0.01 time = np.hstack( (np.linspace(time_full[0], split_point, 3000), np.linspace(split_point, time_full[-1], 1500))) #time = time_full #time_pos = np.logspace(np.log10(1e-2), np.log10(np.max(time_full)), 1000) #time_neg = np.flip(-np.logspace(np.log10(1e-2), np.log10(-np.min(time_full)), 4000)) #time = np.hstack((time_neg,time_pos)) #print("time neg/pos: ",time_neg,time_pos) #print(time_full, time) #time = np.linspace(hptilde.data.length*0.9, hptilde.data.length, hptilde.data.length*.1) #time actually rescaled_time = time / mtot amp = np.abs(h) ph = np.unwrap(np.angle(h)) amp = np.interp(time, time_full, amp) ph = np.interp(time, time_full, ph) ph = ph - ph[ 0] #is it fine to shift waves at will?? Can I do this or am I losing some physical informations?? (this is the purpose of phi_ref!!!!) h = amp * np.exp(1j * ph) # return time, rescaled_time, h return time, rescaled_time, amp, ph
def spin_tidal_eob(m1, m2, s1z, s2z, lambda1, lambda2, f_min, delta_t=1.0 / 16384.0, distance=1.0, inclination=0.0, approximant='SEOBNRv4T', verbose=True): """EOB waveform with aligned spin and tidal interactions. l=3 tidal interaction and l=2,3 f-mode calculated with universal relations. Parameters ---------- approximant : 'TEOBv2' or 'TEOBv4' or the new names 'SEOBNRv2T' or 'SEOBNRv4T'. Based on the inspiral model given by 'SEOBNRv2' or 'SEOBNRv4'. Returns ------- Waveform object """ # print m1, m2, s1z, s2z, lambda1, lambda2, f_min, delta_t, distance, inclination f_ref = 0. phiRef = 0. # Must have aligned spin s1x, s1y, s2x, s2y = 0., 0., 0., 0. # Eccentricity is not part of the model longAscNodes = 0. eccentricity = 0. meanPerAno = 0. # Set the EOB approximant if (approximant not in ['TEOBv2', 'TEOBv4', 'SEOBNRv2T', 'SEOBNRv4T']): raise Exception, "Approximant must be 'TEOBv2' or 'TEOBv4' or 'SEOBNRv2T' or 'SEOBNRv4T'." lal_approx = LS.GetApproximantFromString(approximant) # Insert matter parameters lal_params = lal.CreateDict() LS.SimInspiralWaveformParamsInsertTidalLambda1(lal_params, lambda1) LS.SimInspiralWaveformParamsInsertTidalLambda2(lal_params, lambda2) if verbose: ap = LS.GetStringFromApproximant(lal_approx) L2A = LS.SimInspiralWaveformParamsLookupTidalLambda1(lal_params) L2B = LS.SimInspiralWaveformParamsLookupTidalLambda2(lal_params) L3A = LS.SimInspiralWaveformParamsLookupTidalOctupolarLambda1( lal_params) L3B = LS.SimInspiralWaveformParamsLookupTidalOctupolarLambda2( lal_params) w2A = LS.SimInspiralWaveformParamsLookupTidalQuadrupolarFMode1( lal_params) w2B = LS.SimInspiralWaveformParamsLookupTidalQuadrupolarFMode2( lal_params) w3A = LS.SimInspiralWaveformParamsLookupTidalOctupolarFMode1( lal_params) w3B = LS.SimInspiralWaveformParamsLookupTidalOctupolarFMode2( lal_params) print 'Approximant: ' + str(ap) print 'm1={:.2f}, m2={:.2f}'.format(m1, m2) print 's1z={:.2f}, s2z={:.2f}'.format(s1z, s2z) print 'delta_t={:.6f}, 1/delta_t={:.5}, f_min={:.2f}'.format( delta_t, 1. / delta_t, f_min) print 'L2A, L2B, L3A, L3B, w2A, w2B, w3A, w3B:' print '{:.1f}, {:.1f}, {:.1f}, {:.1f}, {:.4f}, {:.4f}, {:.4f}, {:.4f}'.format( L2A, L2B, L3A, L3B, w2A, w2B, w3A, w3B) sys.stdout.flush() # Evaluate waveform hp, hc = LS.SimInspiralChooseTDWaveform(m1 * lal.MSUN_SI, m2 * lal.MSUN_SI, s1x, s1y, s1z, s2x, s2y, s2z, distance * lal.PC_SI, inclination, phiRef, longAscNodes, eccentricity, meanPerAno, delta_t, f_min, f_ref, lal_params, lal_approx) # Extract time array from lalsimulation's structures tstart = hp.epoch.gpsSeconds + hp.epoch.gpsNanoSeconds * 1.0e-9 ts = tstart + hp.deltaT * np.arange(hp.data.length) return ts, hp.data.data, hc.data.data
phi = sim_inspiral.coa_phase psi = sim_inspiral.polarization end_time = lal.LIGOTimeGPS(sim_inspiral.geocent_end_time, sim_inspiral.geocent_end_time_ns) epoch = end_time - 256 # GPS start time of data gmst = lal.GreenwichMeanSiderealTime(end_time) approximant, amplitude_order, phase_order = timing.get_approximant_and_orders_from_string(sim_inspiral.waveform) if approximant != lalsimulation.TaylorT4: raise ValueError("unrecognized approximant") # Generate injection hplus, hcross = lalsimulation.SimInspiralChooseTDWaveform( phi, 1 / sample_rate, mass1 * lal.MSUN_SI, mass2 * lal.MSUN_SI, spin1x, spin1y, spin1z, spin2x, spin2y, spin2z, f_low, f_low, DL * 1e6 * lal.PC_SI, inc, 0, 0, None, None, amplitude_order, phase_order, approximant) hplus.epoch += end_time hcross.epoch += end_time # Realize detector noise and add injection data = [inject(hplus, hcross, ifo, psd) for ifo, psd in zip(opts.detector, psds)] net_snr, sngl_inspirals = max(detect_net_snr_and_sngls(opts.detector, data, horizons, templates) for templates, horizons in zip(template_bank, horizons_bank)) # If too few triggers were found, then skip this event. if len(sngl_inspirals) < opts.min_triggers:
def create_dataset_TD(N_data, N_grid, modes, basefilename, t_coal = 0.5, q_range = (1.,5.), m2_range = None, s1_range = (-0.8,0.8), s2_range = (-0.8,0.8), t_step = 1e-5, alpha = 0.35, approximant = "SEOBNRv2_opt", path_TEOBResumS = None): """ create_dataset_TD ================= Create datasets for training a ML model to fit GW modes in time domain. Each dataset is saved in a different file (basefilename.mode). The dataset consists in 3 parameters theta=(q, spin1z, spin2z) associated to the modes computed in time domain for a grid of N_grid points in the range given by the user. More specifically, data are stored in 3 vectors: theta_vector vector holding source parameters q, spin1, spin2 amp_vector vector holding amplitudes for each source evaluated at some discrete grid points ph_vector vector holding phase for each source evaluated at some discrete grid points This routine add N_data data to filename if one is specified (if file is not empty it must contain data with the same N_grid); otherwise the datasets are returned as np vectors. Values of q and m2 as well as spins are drawn randomly in the range given by the user: it holds m1 = q *m2 M_sun. The waveforms are computed with a time step t_step; starting from a time in reduced grid tau min (s/M_Sun). Waves are given in a rescaled time grid (i.e. t/m_tot) with N_grid points: t=0 occurs when the 22 mode has a peak. A higher density of grid points is placed close to the merger. Dataset is generated either with an implementation of TEOBResumS (a path to a local installation of TEOBResumS should be provided) either with SEOBNRv4HM (lalsuite installation required). It can be given an TD lal approximant with no HM; in this case, only the 22 mode can be generated. Datasets can be loaded with load_dataset. Input: N_data size of dataset N_grid number of grid points to evaluate modes [] list of modes (each a (l,m) tuple) to generate and fill the dataset with basefilename basename of the file to save dataset in (each dataset is saved in basefilename.lm) t_coal time to coalescence to start computation from (measured in reduced grid) q_range tuple with range for random q values. if single value, q is kept fixed at that value m2_range tuple with range for random m2 values. if single value, m2 is kept fixed at that value. If None, m2 will be chosen s.t. m_tot = m1+m2 = 20. M_sun spin_mag_max_1 tuple with range for random spin #1 values. if single value, s1 is kept fixed at that value spin_mag_max_2 tuple with range for random spin #1 values. if single value, s2 is kept fixed at that value t_step time step to generate the wave with approximant string for the approximant model to be used (in lal convention; to be used only if lal is to be used) alpha distorsion factor for time grid. (In range (0,1], when it's close to 0, more grid points are around merger) approximant lal approximant to be used for generating the modes, or "TEOBResumS" (in the latter case a local installation must be provided by the argument path_TEOBResumS) path_TEOBResumS path to a local installation of TEOBResumS with routine 'EOBRun_module' (if given, it overwrites the aproximant entry) """ #imports if path_TEOBResumS is not None: approximant = "TEOBResumS" if isinstance(modes,tuple): modes = [modes] if not isinstance(modes,list): raise TypeError("Wrong kind of mode {} given. Expected a list [(l,m)]".format(modes)) if approximant == "TEOBResumS": #see https://bitbucket.org/eob_ihes/teobresums/src/development/ for the implementation of TEOBResumS try: import sys sys.path.append(path_TEOBResumS) #path to local installation of TEOBResumS import EOBRun_module except: raise RuntimeError("No valid imput source for module 'EOBRun_module' for TEOBResumS. Unable to continue.") else: try: import lal import lalsimulation as lalsim except: raise RuntimeError("Impossible to load lalsimulation: try pip install lalsuite") LALpars = lal.CreateDict() approx = lalsim.SimInspiralGetApproximantFromString(approximant) prefactor = 4.7864188273360336e-20 # G/c^2*(M_sun/Mpc) #checking that all is good with modes if approximant == "SEOBNRv4HM": for mode in modes: if mode not in [(2,2),(2,1), (3,3), (4,4), (5,5)]: raise ValueError("Currently SEOBNRv4HM approximants do not implement the chosen HM") else: if modes != [(2,2)]: raise ValueError("The chosen lal approximant does not implement HMs") #checking if N_grid is fine if not isinstance(N_grid, int): raise TypeError("N_grid is "+str(type(N_grid))+"! Expected to be a int.") if isinstance(m2_range, tuple): D_theta = 4 #m2 must be included as a feature else: D_theta = 3 ######setting the time grid time_grid_list = [] t_end_list = [] if approximant == "TEOBResumS": modes_to_k = lambda modes:[int(x[0]*(x[0]-1)/2 + x[1]-2) for x in modes] # [(l,m)] -> [k] k_modes = modes_to_k(modes) #setting a list of time grids for mode in modes: #ugly setting of t_end in TEOBResumS: required to kill bad features after merger if mode == (2,2): t_end = 5.2e-4 #estimated maximum time for ringdown: WF will be killed after that time elif mode == (2,1) or mode == (3,3): #special treatment for 21 and 33 t_end = 1e-6 else: t_end = 3e-5 #for other modes t_end_list.append(t_end) else: for mode in modes: t_end_list.append(5.2e-4) print("Generating modes: "+str(modes)) #creating time_grid for i,mode in enumerate(modes): time_grid = np.linspace(-np.power(np.abs(t_coal), alpha), np.power(t_end_list[i], alpha), N_grid) time_grid = np.multiply( np.sign(time_grid) , np.power(np.abs(time_grid), 1./alpha)) #adding 0 to time grid index_0 = np.argmin(np.abs(time_grid)) time_grid[index_0] = 0. #0 is alway set in the grid time_grid_list.append(time_grid) #setting t_coal_freq for generating a waves if np.abs(t_coal) < 0.05: t_coal_freq = 0.05 else: t_coal_freq = np.abs(t_coal) #####create a list of buffer to save the WFs buff_list = [] for i, mode in enumerate(modes): filename = basefilename+'.'+str(mode[0])+str(mode[1]) if not os.path.isfile(filename): #file doesn't exist: must be created with proper header filebuff = open(filename,'w') print("New file ", filename, " created") time_header = np.concatenate((np.zeros((3,)), time_grid_list[i], time_grid_list[i]) )[None,:] np.savetxt(filebuff, time_header, header = "#Mode:"+ str(mode[0])+str(mode[1]) +"\n# row: theta "+str(D_theta)+" | amp (None,"+str(N_grid)+")| ph (None,"+str(N_grid)+")\n# N_grid = "+str(N_grid)+" | t_coal ="+str(t_coal)+" | t_step ="+str(t_step)+" | q_range = "+str(q_range)+" | m2_range = "+str(m2_range)+" | s1_range = "+str(s1_range)+" | s2_range = "+str(s2_range), newline = '\n') else: filebuff = open(filename,'a') buff_list.append(filebuff) #####creating WFs for n_WF in range(N_data): #setting value for data if isinstance(m2_range, tuple): m2 = np.random.uniform(m2_range[0],m2_range[1]) elif m2_range is not None: m2 = float(m2_range) if isinstance(q_range, tuple): q = np.random.uniform(q_range[0],q_range[1]) else: q = float(q_range) if isinstance(s1_range, tuple): spin1z = np.random.uniform(s1_range[0],s1_range[1]) else: spin1z = float(s1_range) if isinstance(s2_range, tuple): spin2z = np.random.uniform(s2_range[0],s2_range[1]) else: spin2z = float(s2_range) if m2_range is None: m2 = 20. / (1+q) m1 = q * m2 else: m1 = q* m2 nu = np.divide(q, np.square(1+q)) #symmetric mass ratio #computing f_min f_min = .9* ((151*(t_coal_freq)**(-3./8.) * (((1+q)**2)/q)**(3./8.))/(m1+m2)) #in () there is the right scaling formula for frequency in order to get always the right reduced time #this should be multiplied by a prefactor (~1) for dealing with some small variation due to spins if isinstance(m2_range, tuple): temp_theta = [m1, m2, spin1z, spin2z] else: temp_theta = [m1/m2, spin1z, spin2z] #getting the wave #output of the if: #amp_list, ph_list (same order as in modes) #time_full, argpeak amp_list, ph_list = [None for i in range(len(modes))],[None for i in range(len(modes))] if approximant == "TEOBResumS": #using TEOBResumS pars = { 'M' : m1+m2, 'q' : m1/m2, 'Lambda1' : 0., 'Lambda2' : 0., 'chi1' : spin1z, 'chi2' : spin2z, 'domain' : 0, # TD 'arg_out' : 1, # Output hlm/hflm. Default = 0 'use_mode_lm' : list(set(k_modes + [1])), # List of modes to use/output through EOBRunPy (added 22 mode in case there isn't) #'srate_interp' : 1./t_step, # srate at which to interpolate. Default = 4096. 'use_geometric_units': 0, # Output quantities in geometric units. Default = 1 'initial_frequency' : f_min, # in Hz if use_geometric_units = 0, else in geometric units 'interp_uniform_grid': 0, # Interpolate mode by mode on a uniform grid. Default = 0 (no interpolation) 'distance': 1., 'inclination':0., } time_full, h_p, h_c, hlm = EOBRun_module.EOBRunPy(pars) for i, k_mode in enumerate(k_modes): temp_amp = hlm[str(k_mode)][0]*nu #TEOBResumS has weird conventions on the modes temp_ph = hlm[str(k_mode)][1] amp_list[i] = temp_amp ph_list[i] = temp_ph argpeak = locate_peak(hlm['1'][0]*nu) #aligned at the peak of the 22 elif approximant == "SEOBNRv4HM": #using SEOBNRv4HM nqcCoeffsInput=lal.CreateREAL8Vector(10) sp, dyn, dynHi = lalsim.SimIMRSpinAlignedEOBModes(t_step, m1*lal.MSUN_SI, m2*lal.MSUN_SI, f_min, 1e6*lal.PC_SI, spin1z, spin2z,41, 0., 0., 0.,0.,0.,0.,0.,0.,1.,1.,nqcCoeffsInput, 0) amp_prefactor = prefactor*(m1+m2)/1. # G/c^2 (M / d_L) while sp is not None: lm = (sp.l, sp.m) if lm not in modes: #skipping a non-necessary mode continue else: #computing index and saving the mode i = modes.index(lm) hlm = sp.mode.data.data #complex mode vector temp_amp = np.abs(hlm)/ amp_prefactor / nu #scaling with the convention of SEOB temp_ph = np.unwrap(np.angle(hlm)) amp_list[i] = temp_amp ph_list[i] = temp_ph if (sp.l, sp.m) == (2,2): #get grid amp_22 = np.abs(sp.mode.data.data) #amp of 22 mode (for time grid alignment) time_full = np.linspace(0.0, sp.mode.data.length*t_step, sp.mode.data.length) #time grid at which wave is computed argpeak = locate_peak(amp_22) #aligned at the peak of the 22 sp = sp.next else: #another lal approximant (only 22 mode) hp, hc = lalsim.SimInspiralChooseTDWaveform( #where is its definition and documentation???? m1*lalsim.lal.MSUN_SI, #m1 m2*lalsim.lal.MSUN_SI, #m2 0., 0., spin1z, #spin vector 1 0., 0., spin2z, #spin vector 2 1e6*lalsim.lal.PC_SI, #distance to source 0., #inclination 0., #phi 0., #longAscNodes 0., #eccentricity 0., #meanPerAno t_step, # time incremental step f_min, # lowest value of freq f_min, #some reference value of freq (??) LALpars, #some lal dictionary approx #approx method for the model ) h_p, h_c = hp.data.data, hc.data.data time_full = np.linspace(0.0, hp.data.length*t_step, hp.data.length) #time grid at which wave is computed amp_prefactor = prefactor*(m1+m2)/1. # G/c^2 (M / d_L) temp_amp = np.sqrt(np.square(h_p)+np.square(h_c)) / amp_prefactor / (4*np.sqrt(5/(64*np.pi))) temp_ph = np.unwrap(np.arctan2(h_c,h_p)) amp_list = [temp_amp] ph_list = [temp_ph] argpeak = locate_peak(temp_amp) #aligned at the peak of the 22 #setting time grid t_peak = time_full[argpeak] time_full = (time_full - t_peak)/(m1+m2) #grid is scaled to standard grid #computing waves to the chosen std grid and saving to file for i in range(len(amp_list)): temp_amp, temp_ph = amp_list[i], ph_list[i] #print(temp_amp.shape, time_full.shape, time_grid_list[i].shape) temp_amp = np.interp(time_grid_list[i], time_full, temp_amp) temp_ph = np.interp(time_grid_list[i], time_full, temp_ph) temp_ph = temp_ph - temp_ph[0] #all phases are shifted by a constant to make sure every wave has 0 phase at beginning of grid to_save = np.concatenate((temp_theta, temp_amp, temp_ph))[None,:] #(1,D) np.savetxt(buff_list[i], to_save) #user communication if n_WF%100 == 0 and n_WF != 0: #if n_WF%1 == 0 and n_WF != 0: #debug print("Generated WF ", n_WF) if filename is None: return theta_vector, amp_dataset.real, ph_dataset.real, time_grid else: filebuff.close() return None
t_step = 5e-5 f_min = 20.0 for inclination in np.linspace(-np.pi / 2, np.pi / 2, 10): hptilde, hctilde = lalsim.SimInspiralChooseTDWaveform( #where is its definition and documentation???? m1 * lalsim.lal.MSUN_SI, #m1 m2 * lalsim.lal.MSUN_SI, #m2 0., 0., spin1z, #spin vector 1 0., 0., spin2z, #spin vector 2 d * 1e6 * lalsim.lal.PC_SI, #distance to source inclination, #inclination 0., #phi ref 0., #longAscNodes 0., #eccentricity 0., #meanPerAno t_step, # time incremental step f_min, # lowest value of time f_min, #some reference value of time (??) lal.CreateDict(), #some lal dictionary lalsim.GetApproximantFromString( 'SEOBNRv2_opt') #approx method for the model ) times = t_step * np.linspace(0.0, len(hptilde.data.data), len(hptilde.data.data)) times -= times[np.argmax(hptilde.data.data**2 + hctilde.data.data**2)] theta = np.column_stack((m1 / m2, spin1z, spin2z))
def lalsim_td_waveform(long_asc_nodes=0.0, eccentricity=0.0, mean_per_ano=0.0, phi_ref=0.0, f_ref=None, phase_order=-1, amplitude_order=-1, spin_order=-1, tidal_order=-1, **p): """Wrapper for lalsimulation.SimInspiralChooseTDWaveform. Simplified version of pycbc.waveform.get_td_waveform wrapper. Parameters ---------- f_ref : Reference frequency (?For setting phi_ref? Not sure.) Defaults to f_min. phi_ref : Reference phase (?at f_ref?). Returns ------- h : Waveform """ if f_ref == None: f_ref = p['f_min'] # Set extra arguments in the lal Dict structure lal_pars = lal.CreateDict() if phase_order != -1: lalsimulation.SimInspiralWaveformParamsInsertPNPhaseOrder( lal_pars, int(phase_order)) if amplitude_order != -1: lalsimulation.SimInspiralWaveformParamsInsertPNAmplitudeOrder( lal_pars, int(amplitude_order)) if spin_order != -1: lalsimulation.SimInspiralWaveformParamsInsertPNSpinOrder( lal_pars, int(spin_order)) if tidal_order != -1: lalsimulation.SimInspiralWaveformParamsInsertPNTidalOrder( lal_pars, int(tidal_order)) if p['lambda1']: lalsimulation.SimInspiralWaveformParamsInsertTidalLambda1( lal_pars, p['lambda1']) if p['lambda2']: lalsimulation.SimInspiralWaveformParamsInsertTidalLambda2( lal_pars, p['lambda2']) # Set Approximant (C enum structure) corresponding to approximant string lal_approx = lalsimulation.GetApproximantFromString(p['approximant']) hp, hc = lalsimulation.SimInspiralChooseTDWaveform( float(MSUN_SI * p['mass1']), float(MSUN_SI * p['mass2']), float(p['spin1x']), float(p['spin1y']), float(p['spin1z']), float(p['spin2x']), float(p['spin2y']), float(p['spin2z']), float(MPC_SI * p['distance']), float(p['inclination']), float(phi_ref), float(long_asc_nodes), float(eccentricity), float(mean_per_ano), float(p['delta_t']), float(p['f_min']), float(f_ref), lal_pars, lal_approx) # Extract data from lalsimulation's structures tstart = hp.epoch.gpsSeconds + hp.epoch.gpsNanoSeconds * 1.0e-9 xs = tstart + hp.deltaT * np.arange(hp.data.length) return wave.Waveform.from_hp_hc(xs, hp.data.data, hc.data.data)
def gen_bbh(fs,T_obs,psds,isnr=1.0,dets=['H1']): """ generates a BBH timedomain signal """ N = T_obs * fs # the total number of time samples dt = 1 / fs # the sampling time (sec) f_low = 12.0 # lowest frequency of waveform (Hz) amplitude_order = 0 phase_order = 7 approximant = lalsimulation.IMRPhenomD ndet = len(dets) # number of detectors # define distribution params m_min = 5.0 # rest frame component masses M_max = 100.0 # rest frame total mass log_m_max = np.log(M_max - m_min) dist = 1e6*lal.PC_SI # put it as 1 MPc flag = False while not flag: m12 = np.exp(np.log(m_min) + np.random.uniform(0,1,2)*(log_m_max-np.log(m_min))) flag = True if (np.sum(m12)<M_max) and (np.all(m12>m_min)) and (m12[0]>=m12[1]) else False eta = m12[0]*m12[1]/(m12[0]+m12[1])**2 mc = np.sum(m12)*eta**(3.0/5.0) print '{}: selected bbh masses = {},{} (chirp mass = {})'.format(time.asctime(),m12[0],m12[1],mc) # generate iota iota = np.arccos(-1.0 + 2.0*np.random.rand()) print '{}: selected bbh cos(inclination) = {}'.format(time.asctime(),np.cos(iota)) # generate polarisation angle psi = 2.0*np.pi*np.random.rand() print '{}: selected bbh polarisation = {}'.format(time.asctime(),psi) # make waveform # loop until we have a long enough waveform - slowly reduce flow is needed flag = False while not flag: hp, hc = lalsimulation.SimInspiralChooseTDWaveform( m12[0] * lal.MSUN_SI, m12[1] * lal.MSUN_SI, 0, 0, 0, 0, 0, 0, dist, iota, 0, 0, 0, 0, 1 / fs, f_low,f_low, lal.CreateDict(), approximant) flag = True if hp.data.length>2*N else False f_low -= 1 # decrease by 1 Hz each time hp = hp.data.data hc = hc.data.data # pick sky position - uniform on the 2-sphere ra = 2.0*np.pi*np.random.rand() dec = np.arcsin(-1.0 + 2.0*np.random.rand()) print '{}: selected bbh sky position = {},{}'.format(time.asctime(),ra,dec) # pick new random max amplitude sample location - within mid 20% region # and slide waveform to that location idx = int(np.random.randint(int(4.0*N/10.0),int(6.0*N/10.0),1)[0]) print '{}: selected bbh peak amplitude time = {}'.format(time.asctime(),dt*idx) # define point of max amplitude ref_idx = int(np.argmax(hp**2 + hc**2)) # loop over detectors ts = np.zeros((ndet,N)) intsnr = [] j = 0 for det,psd in zip(dets,psds): # make signal - apply antenna and shifts ht_temp = make_bbh(hp,hc,fs,ra,dec,psi,det) # place signal into timeseries - including shift x_temp = np.zeros(N) temp = ht_temp[int(ref_idx-idx):] if len(temp)<N: x_temp[:len(temp)] = temp else: x_temp = temp[:N] # compute SNR of pre-whitened data intsnr.append(get_snr(x_temp,T_obs,fs,psd.data.data)) # don't whiten the data ts[j,:] = x_temp j += 1 hpc_temp = np.zeros((2,N)) temp_hp = hp[int(ref_idx-idx):] temp_hc = hc[int(ref_idx-idx):] if len(temp_hp)<N: hpc_temp[0,:len(temp)] = temp_hp hpc_temp[1,:len(temp)] = temp_hc else: hpc_temp[0,:] = temp_hp[:N] hpc_temp[1,:] = temp_hc[:N] # normalise the waveform using either integrated or peak SNR intsnr = np.array(intsnr) scale = isnr/np.sqrt(np.sum(intsnr**2)) ts = scale*ts intsnr *= scale SNR = np.sqrt(np.sum(intsnr**2)) print '{}: computed the network SNR = {}'.format(time.asctime(),SNR) # store params par = bbhparams(mc,m12[0],m12[1],ra,dec,np.cos(iota),psi,idx*dt,intsnr,SNR) return ts, par, hpc_temp
def make_tidal_waveform(approx='TaylorT4', rate=4096, Lambda1=None, Lambda2=None, mass1=1.4, mass2=1.3, inclination=0, distance=100, eccentricity=0, meanPerAno=0, phiRef=0, f_min=30, f_ref=0, longAscNodes=0, s1x=0, s1y=0, s1z=0, s2x=0, s2y=0, s2z=0, eos=None, save=False): # Sanity check if (Lambda1 is None) and (Lambda2 is None) and (eos is None): # Assuming Lambdas to be zero is not provided print("Assuming tidal deformability is zero") print( "Use arguments Lambda1=, and Lambda2= to provide deformabilities") Lambda1 = 0.0 Lambda2 = 0.0 if eos: if Lambda1 or Lambda2: print( "Warning: Both eos and Lambda1 and/or Lambda2 has been provided" ) print("Ignoring Lambdas in favor of the eos") e = lalsim.SimNeutronStarEOSByName(eos) fam = lalsim.CreateSimNeutronStarFamily(e) max_mass = lalsim.SimNeutronStarMaximumMass(fam) / lal.MSUN_SI assert mass1 < max_mass, "mass1 greater than maximum mass allowed for the neutron star" assert mass2 < max_mass, "mass2 greater than the maximum mass allowed for the neutron star" r1 = lalsim.SimNeutronStarRadius(mass1 * lal.MSUN_SI, fam) k1 = lalsim.SimNeutronStarLoveNumberK2(mass1 * lal.MSUN_SI, fam) r2 = lalsim.SimNeutronStarRadius(mass2 * lal.MSUN_SI, fam) k2 = lalsim.SimNeutronStarLoveNumberK2(mass2 * lal.MSUN_SI, fam) c2 = mass2 * lal.MRSUN_SI / r2 c1 = mass1 * lal.MRSUN_SI / r1 Lambda1 = (2 / 3) * k1 / (c1**5) Lambda2 = (2 / 3) * k2 / (c2**5) mass1 = mass1 * lal.MSUN_SI mass2 = mass2 * lal.MSUN_SI distance = distance * 1e6 * lal.PC_SI deltaT = 1.0 / rate approximant = lalsim.GetApproximantFromString(approx) lal_pars = lal.CreateDict() lalsim.SimInspiralWaveformParamsInsertTidalLambda1(lal_pars, Lambda1) lalsim.SimInspiralWaveformParamsInsertTidalLambda2(lal_pars, Lambda2) hp, hc = lalsim.SimInspiralChooseTDWaveform(mass1, mass2, s1x=s1x, s1y=s1y, s1z=s1z, s2x=s2x, s2y=s2y, s2z=s2z, distance=distance, inclination=inclination, phiRef=phiRef, longAscNodes=longAscNodes, eccentricity=eccentricity, meanPerAno=meanPerAno, deltaT=deltaT, f_min=f_min, f_ref=f_ref, params=lal_pars, approximant=approximant) if save: plus_data = hp.data.data cross_data = hc.data.data tstart_p = hp.epoch.gpsSeconds + hp.epoch.gpsNanoSeconds * 1e-9 tstart_c = hc.epoch.gpsSeconds + hc.epoch.gpsNanoSeconds * 1e-9 tp = np.arange(tstart_p, 0, hp.deltaT) tp = tp[:len(hp.data.data)] tc = np.arange(tstart_c, 0, hc.deltaT) tc = tc[:len(hc.data.data)] output_plus = np.vstack((tp, plus_data)).T output_cross = np.vstack((tc, cross_data)).T np.savetxt("plus_polarization_data.txt", output_plus, fmt="%f\t%e") np.savetxt("cross_polarization_data.txt", output_cross, fmt="%f\t%e") return (hp, hc)
dt = 1. / sampling_rate flow = 20 fref = 20 LALpars = lal.CreateDict() approx = lalsim.SimInspiralGetApproximantFromString('SEOBNRv2') hp, hc = lalsim.SimInspiralChooseTDWaveform( m1 * lalsim.lal.MSUN_SI, m2 * lalsim.lal.MSUN_SI, spin1x, spin1y, spin1z, spin2x, spin2y, spin2z, d * 1e6 * lalsim.lal.PC_SI, inclination, phi0, 0, #longAscNodes 0, #eccentricity 0, #meanPerAno dt, flow, fref, LALpars, approx) times = dt * np.array(range(len(hp.data.data))) plt.figure() plt.plot(times, hp.data.data, label='Plus polarisation') plt.plot(times, hc.data.data, label='Cross polarisation') plt.xlabel('time (s)')