def hplus_of_f(m1, m2, s1, s2, f_min, f_max, delta_f): farr = numpy.linspace(0, f_max, f_max / delta_f + delta_f) spin1 = [0., 0., s1] spin2 = [0., 0., s2] hp, hc = lalsim.SimInspiralFD( m1 * lal.MSUN_SI, m2 * lal.MSUN_SI, spin1[0], spin1[1], spin1[2], spin2[0], spin2[1], spin2[2], 1.0, # distance (m) 0.0, 0.0, # reference orbital phase (rad) 0.0, # longitude of ascending nodes (rad) 0.0, 0.0, # mean anomaly of periastron delta_f, f_min, f_max + delta_f, 100., # reference frequency (Hz) None, # LAL dictionary containing accessory parameters lalsim.GetApproximantFromString("IMRPhenomD")) assert hp.data.length > 0, "huh!? h+ has zero length!" return hp.data.data[:len(farr)]
def spin_tidal_IMRPhenomD_FD(m1, m2, s1z, s2z, lambda1, lambda2, f_min, f_max, deltaF=1.0/128.0, delta_t=1.0/16384.0, distance=1.0, inclination=0.0, approximant='IMRPhenomD_NRTidal', verbose=True): # 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. lal_approx = LS.GetApproximantFromString(approximant) # Insert matter parameters lal_params = lal.CreateDict() LS.SimInspiralWaveformParamsInsertTidalLambda1(lal_params, lambda1) LS.SimInspiralWaveformParamsInsertTidalLambda2(lal_params, lambda2) # Evaluate FD waveform Hp, Hc = LS.SimInspiralFD( m1*lal.MSUN_SI, m2*lal.MSUN_SI, s1x, s1y, s1z, s2x, s2y, s2z, distance*lal.PC_SI, inclination, phiRef, longAscNodes, eccentricity, meanPerAno, deltaF, f_min, f_max, f_ref, lal_params, lal_approx) f = deltaF * np.arange(Hp.data.length) return f, Hp, Hc
def gen_waveform(event_params, flow=10.0, deltaf=0.125, fhigh=2048., fref=10., approximant="IMRPhenomPv2"): """ Generate the h_+ and h_x polarizations for an event, as well as an associated frequency array. """ eprm = _defaults.copy() eprm.update(event_params) freq_ar = numpy.arange(0, fhigh + deltaf, deltaf) params = None hp, hx = lalsimulation.SimInspiralFD( # Masses eprm["m1"] * lal.MSUN_SI, eprm["m2"] * lal.MSUN_SI, \ # Spins eprm["spin1x"], eprm["spin1y"], eprm["spin1z"], \ eprm["spin1x"], eprm["spin1y"], eprm["spin1z"], \ # distance and inclination eprm["distance"] * 1e6 * lal.PC_SI, eprm["inclination"], # These are eccentricity and other orbital parameters 0.0, 0.0, 0.0, 0.0, # frequency binning params deltaf, flow, fhigh, fref, \ # Other extraneous options params, lalsimulation.SimInspiralGetApproximantFromString(approximant)) return freq_ar, hp.data.data, hx.data.data
def lalsim_SimInspiralFD(mass_1, mass_2, spin_1x, spin_1y, spin_1z, spin_2x, spin_2y, spin_2z, luminosity_distance, iota, phase, longitude_ascending_nodes, eccentricity, mean_per_ano, delta_frequency, minimum_frequency, maximum_frequency, reference_frequency, waveform_dictionary, approximant): """ Safely call lalsimulation.SimInspiralFD Parameters ---------- phase: float, int mass_1: float, int mass_2: float, int spin_1x: float, int spin_1y: float, int spin_1z: float, int spin_2x: float, int spin_2y: float, int spin_2z: float, int reference_frequency: float, int luminosity_distance: float, int iota: float, int longitude_ascending_nodes: float, int eccentricity: float, int mean_per_ano: float, int delta_frequency: float, int minimum_frequency: float, int maximum_frequency: float, int waveform_dictionary: None, lal.Dict approximant: int, str """ [ mass_1, mass_2, spin_1x, spin_1y, spin_1z, spin_2x, spin_2y, spin_2z, luminosity_distance, iota, phase, longitude_ascending_nodes, eccentricity, mean_per_ano, delta_frequency, minimum_frequency, maximum_frequency, reference_frequency ] = convert_args_list_to_float( mass_1, mass_2, spin_1x, spin_1y, spin_1z, spin_2x, spin_2y, spin_2z, luminosity_distance, iota, phase, longitude_ascending_nodes, eccentricity, mean_per_ano, delta_frequency, minimum_frequency, maximum_frequency, reference_frequency) if isinstance(approximant, int): pass elif isinstance(approximant, str): approximant = lalsim_GetApproximantFromString(approximant) else: raise ValueError("approximant not an int") return lalsim.SimInspiralFD(mass_1, mass_2, spin_1x, spin_1y, spin_1z, spin_2x, spin_2y, spin_2z, luminosity_distance, iota, phase, longitude_ascending_nodes, eccentricity, mean_per_ano, delta_frequency, minimum_frequency, maximum_frequency, reference_frequency, waveform_dictionary, approximant)
def _compute_waveform_comps(self, df, f_final): approx = lalsim.GetApproximantFromString(self.approximant) lmbda1 = lmbda2 = 0 # No tidal terms here ampO = -1 # Are these the correct values?? phaseO = -1 # Are these the correct values?? if lalsim.SimInspiralImplementedFDApproximants(approx): hplus_fd, hcross_fd = lalsim.SimInspiralChooseFDWaveform( self.orb_phase, df, self.m1 * MSUN_SI, self.m2 * MSUN_SI, self.spin1x, self.spin1y, self.spin1z, self.spin2x, self.spin2y, self.spin2z, self.bank.flow, f_final, self.bank.flow, 1e6 * PC_SI, self.iota, lmbda1, lmbda2, # irrelevant parameters for BBH None, None, # non-GR parameters ampO, phaseO, approx) else: hplus_fd, hcross_fd = lalsim.SimInspiralFD( self.orb_phase, df, self.m1 * MSUN_SI, self.m2 * MSUN_SI, self.spin1x, self.spin1y, self.spin1z, self.spin2x, self.spin2y, self.spin2z, self.bank.flow, f_final, self.bank.flow, 1e6 * PC_SI, 0, self.iota, lmbda1, lmbda2, # irrelevant parameters for BBH None, None, # non-GR parameters ampO, phaseO, approx) return hplus_fd, hcross_fd
def sngl_inspiral_psd(sngl, waveform, f_min=10, f_max=2048, f_ref=0): # FIXME: uberbank mass criterion. Should find a way to get this from # pipeline output metadata. if waveform == 'o1-uberbank': log.warn('Template is unspecified; using ER8/O1 uberbank criterion') if sngl.mass1 + sngl.mass2 < 4: waveform = 'TaylorF2threePointFivePN' else: waveform = 'SEOBNRv2_ROM_DoubleSpin' approx, ampo, phaseo = get_approximant_and_orders_from_string(waveform) log.info('Selected template: %s', waveform) # Generate conditioned template. params = lal.CreateDict() lalsimulation.SimInspiralWaveformParamsInsertPNPhaseOrder(params, phaseo) lalsimulation.SimInspiralWaveformParamsInsertPNAmplitudeOrder(params, ampo) hplus, hcross = lalsimulation.SimInspiralFD( m1=sngl.mass1*lal.MSUN_SI, m2=sngl.mass2*lal.MSUN_SI, S1x=getattr(sngl, 'spin1x', 0) or 0, S1y=getattr(sngl, 'spin1y', 0) or 0, S1z=getattr(sngl, 'spin1z', 0) or 0, S2x=getattr(sngl, 'spin2x', 0) or 0, S2y=getattr(sngl, 'spin2y', 0) or 0, S2z=getattr(sngl, 'spin2z', 0) or 0, distance=1e6*lal.PC_SI, inclination=0, phiRef=0, longAscNodes=0, eccentricity=0, meanPerAno=0, deltaF=0, f_min=f_min, f_max=f_max, f_ref=f_ref, LALparams=params, approximant=approx) # Force `plus' and `cross' waveform to be in quadrature. h = 0.5 * (hplus.data.data + 1j * hcross.data.data) # For inspiral-only waveforms, nullify frequencies beyond ISCO. # FIXME: the waveform generation functions pick the end frequency # automatically. Shouldn't SimInspiralFD? inspiral_only_waveforms = ( lalsimulation.TaylorF2, lalsimulation.SpinTaylorF2, lalsimulation.TaylorF2RedSpin, lalsimulation.TaylorF2RedSpinTidal, lalsimulation.SpinTaylorT4Fourier) if approx in inspiral_only_waveforms: h[abscissa(hplus) >= get_f_lso(sngl.mass1, sngl.mass2)] = 0 # Drop Nyquist frequency. if len(h) % 2: h = h[:-1] # Create output frequency series. psd = lal.CreateREAL8FrequencySeries( 'signal PSD', 0, hplus.f0, hcross.deltaF, hplus.sampleUnits**2, len(h)) psd.data.data = abs2(h) # Done! return psd
def FD_waveform_test(Mtot, x, approximant, fLow=20.0, fHigh=16384.0, deltaF=0): q = 1.0 / x[0] chi1 = x[1] chi2 = x[2] lambda1 = x[3] lambda2 = x[4] phiRef, fRef = 0.0, fLow distance, inclination = 1.0, 0.0 m1 = q / (1.0 + q) * Mtot m2 = 1.0 / (1.0 + q) * Mtot m1SI, m2SI, chi1, chi2, lambda1, lambda2, nk_max = m1 * lal.MSUN_SI, m2 * lal.MSUN_SI, chi1, chi2, lambda1, lambda2, -1 longAscNodes, eccentricity, meanPerAno = 0, 0, 0 LALpars = lal.CreateDict() LS.SimInspiralWaveformParamsInsertTidalLambda1(LALpars, lambda1) LS.SimInspiralWaveformParamsInsertTidalLambda2(LALpars, lambda2) # Nyquist frequency is set by fHigh # Can set deltaF = 0 to figure out required frequency spacing; the chosen deltaF depends on fLow # Documentation from LALSimInspiral.c # # * This routine can generate TD approximants and transform them into the frequency domain. # * Waveforms are generated beginning at a slightly lower starting frequency and tapers # * are put in this early region so that the waveform smoothly turns on. # * # * If an FD approximant is used, this routine applies tapers in the frequency domain # * between the slightly-lower frequency and the requested f_min. Also, the phase of the # * waveform is adjusted to introduce a time shift. This time shift should allow the # * resulting waveform to be Fourier transformed into the time domain without wrapping # * the end of the waveform to the beginning. # * # * This routine assumes that f_max is the Nyquist frequency of a corresponding time-domain # * waveform, so that deltaT = 0.5 / f_max. If deltaF is set to 0 then this routine computes # * a deltaF that is small enough to represent the Fourier transform of a time-domain waveform. # * If deltaF is specified but f_max / deltaF is not a power of 2, and the waveform approximant # * is a time-domain approximant, then f_max is increased so that f_max / deltaF is the next # * power of 2. (If the user wishes to discard the extra high frequency content, this must # * be done separately.) hp, hc = LS.SimInspiralFD(m1SI, m2SI, 0.0, 0.0, chi1, 0.0, 0.0, chi2, distance, inclination, phiRef, longAscNodes, eccentricity, meanPerAno, deltaF, fLow, fHigh, fRef, LALpars, approximant) fHz = np.arange(hp.data.length) * hp.deltaF h = hp.data.data + 1j * hc.data.data return hp.deltaF
def get_snr_at_z_lalsimulation(cosmo, z, mass1, mass2, f_low, f_high, psd): """Calculate optimal SNR the LALSimulation way.""" params = lal.CreateDict() lalsimulation.SimInspiralWaveformParamsInsertRedshift(params, z) # "Signal" waveform with requested inclination angle. # Take (arbitrarily) only the plus polarization. h, _ = lalsimulation.SimInspiralFD( mass1 * lal.MSUN_SI, mass2 * lal.MSUN_SI, 0, 0, 0, 0, 0, 0, cosmo.comoving_distance(z).to_value(u.m), 0, 0, 0, 0, 0, 1e-3 * (f_high - f_low), f_low, f_high, f_low, params, lalsimulation.IMRPhenomPv2) return lalsimulation.MeasureSNRFD(h, psd, f_low, f_high)
def _compute_waveform_comps(self, df, f_final): approx = lalsim.GetApproximantFromString(self.approximant) if lalsim.SimInspiralImplementedFDApproximants(approx): hplus_fd, hcross_fd = lalsim.SimInspiralChooseFDWaveform( self.m1 * MSUN_SI, self.m2 * MSUN_SI, self.spin1x, self.spin1y, self.spin1z, self.spin2x, self.spin2y, self.spin2z, 1.e6 * PC_SI, self.iota, self.orb_phase, 0., 0., 0., df, self.flow, f_final, self.flow, None, approx) else: hplus_fd, hcross_fd = lalsim.SimInspiralFD( self.m1 * MSUN_SI, self.m2 * MSUN_SI, self.spin1x, self.spin1y, self.spin1z, self.spin2x, self.spin2y, self.spin2z, 1.e6 * PC_SI, self.iota, self.orb_phase, 0., 0., 0., df, self.flow, f_final, self.flow, None, approx) return hplus_fd, hcross_fd
def _compute_waveform(self, df, f_final): approx = lalsim.GetApproximantFromString(self.approximant) if lalsim.SimInspiralImplementedFDApproximants(approx): hplus_fd, hcross_fd = lalsim.SimInspiralChooseFDWaveform( self.m1 * MSUN_SI, self.m2 * MSUN_SI, 0., 0., self.spin1z, 0., 0., self.spin2z, 1e6 * PC_SI, 0., 0., 0., 0., 0., df, self.bank.flow, f_final, self.bank.flow, None, approx) else: hplus_fd, hcross_fd = lalsim.SimInspiralFD( phi0, df, self.m1 * MSUN_SI, self.m2 * MSUN_SI, 0, 0, self.spin1z, 0, 0, self.spin2z, 1.e6 * PC_SI, 0., 0., 0., 0., 0., df, self.bank.flow, f_final, 40., None, approx) return hplus_fd
def _compute_waveform(self, df, f_final): phi0 = 0 # This is a reference phase, and not an intrinsic parameter approx = lalsim.GetApproximantFromString(self.approximant) if lalsim.SimInspiralImplementedFDApproximants(approx): hplus_fd, hcross_fd = lalsim.SimInspiralChooseFDWaveform( self.m1 * MSUN_SI, self.m2 * MSUN_SI, 0., 0., self.spin1z, 0., 0., self.spin2z, 1e6 * PC_SI, 0., 0., 0., 0., 0., df, self.flow, f_final, self.flow, None, approx) else: hplus_fd, hcross_fd = lalsim.SimInspiralFD( phi0, df, self.m1 * MSUN_SI, self.m2 * MSUN_SI, 0, 0, self.spin1z, 0, 0, self.spin2z, 1.e6 * PC_SI, 0., 0., 0., 0., 0., df, self.flow, f_final, 40., None, approx) return hplus_fd
def _compute_waveform(self, df, f_final): flags = lalsim.SimInspiralCreateWaveformFlags() phi0 = 0 # This is a reference phase, and not an intrinsic parameter lmbda1 = lmbda2 = 0 # No tidal terms here ampO = -1 # Are these the correct values?? phaseO = -1 # Are these the correct values?? approx = lalsim.GetApproximantFromString(self.approximant) if lalsim.SimInspiralImplementedFDApproximants(approx): hplus_fd, hcross_fd = lalsim.SimInspiralChooseFDWaveform( 0, df, self.m1 * MSUN_SI, self.m2 * MSUN_SI, 0., 0., self.spin1z, 0., 0., self.spin2z, self.bank.flow, f_final, self.bank.flow, 1e6 * PC_SI, 0., 0., 0., flags, None, ampO, phaseO, approx) else: hplus_fd, hcross_fd = lalsim.SimInspiralFD( phi0, df, self.m1 * MSUN_SI, self.m2 * MSUN_SI, 0, 0, self.spin1z, 0, 0, self.spin2z, self.bank.flow, f_final, 40.0, 1e6 * PC_SI, 0, 0, lmbda1, lmbda2, # irrelevant parameters for BBH None, None, # non-GR parameters ampO, phaseO, approx) return hplus_fd
def lalsim_SimInspiralFD( mass_1, mass_2, spin_1x, spin_1y, spin_1z, spin_2x, spin_2y, spin_2z, luminosity_distance, iota, phase, longitude_ascending_nodes, eccentricity, mean_per_ano, delta_frequency, minimum_frequency, maximum_frequency, reference_frequency, waveform_dictionary, approximant): """ Safely call lalsimulation.SimInspiralFD Parameters ---------- phase: float, int mass_1: float, int mass_2: float, int spin_1x: float, int spin_1y: float, int spin_1z: float, int spin_2x: float, int spin_2y: float, int spin_2z: float, int reference_frequency: float, int luminosity_distance: float, int iota: float, int longitude_ascending_nodes: float, int eccentricity: float, int mean_per_ano: float, int delta_frequency: float, int minimum_frequency: float, int maximum_frequency: float, int waveform_dictionary: None, lal.Dict approximant: int, str """ args = convert_args_list_to_float( mass_1, mass_2, spin_1x, spin_1y, spin_1z, spin_2x, spin_2y, spin_2z, luminosity_distance, iota, phase, longitude_ascending_nodes, eccentricity, mean_per_ano, delta_frequency, minimum_frequency, maximum_frequency, reference_frequency) approximant = _get_lalsim_approximant(approximant) return lalsim.SimInspiralFD(*args, waveform_dictionary, approximant)
def generate_template(template_bank_row, approximant, sample_rate, duration, f_low, f_high, amporder=0, order=7, fwdplan=None, fworkspace=None): """ Generate a single frequency-domain template, which 1. is band-limited between f_low and f_high, 2. has an IFFT which is duration seconds long and 3. has an IFFT which is sampled at sample_rate Hz """ if approximant not in templates.gstlal_approximants: raise ValueError("Unsupported approximant given %s" % approximant) assert f_high <= sample_rate // 2 # FIXME use hcross somday? # We don't here because it is not guaranteed to be orthogonal # and we add orthogonal phase later parameters = {} parameters['m1'] = lal.MSUN_SI * template_bank_row.mass1 parameters['m2'] = lal.MSUN_SI * template_bank_row.mass2 parameters['S1x'] = template_bank_row.spin1x parameters['S1y'] = template_bank_row.spin1y parameters['S1z'] = template_bank_row.spin1z parameters['S2x'] = template_bank_row.spin2x parameters['S2y'] = template_bank_row.spin2y parameters['S2z'] = template_bank_row.spin2z parameters['distance'] = 1.e6 * lal.PC_SI parameters['inclination'] = 0. parameters['phiRef'] = 0. parameters['longAscNodes'] = 0. parameters['eccentricity'] = 0. parameters['meanPerAno'] = 0. parameters['deltaF'] = 1.0 / duration parameters['f_min'] = f_low parameters['f_max'] = f_high parameters['f_ref'] = 0. parameters['LALparams'] = None parameters['approximant'] = lalsim.GetApproximantFromString( str(approximant)) hplus, hcross = lalsim.SimInspiralFD(**parameters) assert len(hplus.data.data) == int(round(f_high * duration)) + 1 # pad the output vector if the sample rate was higher than the # requested final frequency if f_high < sample_rate / 2: fseries = lal.CreateCOMPLEX16FrequencySeries( name=hplus.name, epoch=hplus.epoch, f0=hplus.f0, deltaF=hplus.deltaF, length=int(round(sample_rate * duration)) // 2 + 1, sampleUnits=hplus.sampleUnits) fseries.data.data = numpy.zeros(fseries.data.length) fseries.data.data[:hplus.data.length] = hplus.data.data[:] hplus = fseries return hplus
def FD_waveform(m1, m2, s1z, s2z, lambda1, lambda2, f_min, f_max=2048.0, deltaF=0.0, distance=1.0, inclination=0.0, approximant='SEOBNRv4T', verbose=True): """Compute waveform in the Fourier domain using SimInspiralFD deltaF=0 selects required frequency resolution (the inverse of the selected deltaF will be a power of 2) Returns frequency in Hz and h = hp + 1j*hc """ phiRef, fRef = 0.0, f_min m1SI, m2SI = m1 * lal.MSUN_SI, m2 * lal.MSUN_SI longAscNodes, eccentricity, meanPerAno = 0, 0, 0 LALpars = lal.CreateDict() LS.SimInspiralWaveformParamsInsertTidalLambda1(LALpars, lambda1) LS.SimInspiralWaveformParamsInsertTidalLambda2(LALpars, lambda2) lal_approx = LS.GetApproximantFromString(approximant) # Nyquist frequency is set by fHigh # Can set deltaF = 0 to figure out required frequency spacing; the chosen deltaF depends on fLow # Documentation from LALSimInspiral.c # # * This routine can generate TD approximants and transform them into the frequency domain. # * Waveforms are generated beginning at a slightly lower starting frequency and tapers # * are put in this early region so that the waveform smoothly turns on. # * # * If an FD approximant is used, this routine applies tapers in the frequency domain # * between the slightly-lower frequency and the requested f_min. Also, the phase of the # * waveform is adjusted to introduce a time shift. This time shift should allow the # * resulting waveform to be Fourier transformed into the time domain without wrapping # * the end of the waveform to the beginning. # * # * This routine assumes that f_max is the Nyquist frequency of a corresponding time-domain # * waveform, so that deltaT = 0.5 / f_max. If deltaF is set to 0 then this routine computes # * a deltaF that is small enough to represent the Fourier transform of a time-domain waveform. # * If deltaF is specified but f_max / deltaF is not a power of 2, and the waveform approximant # * is a time-domain approximant, then f_max is increased so that f_max / deltaF is the next # * power of 2. (If the user wishes to discard the extra high frequency content, this must # * be done separately.) hp, hc = LS.SimInspiralFD(m1SI, m2SI, 0.0, 0.0, s1z, 0.0, 0.0, s2z, distance, inclination, phiRef, longAscNodes, eccentricity, meanPerAno, deltaF, f_min, f_max, fRef, LALpars, lal_approx) fHz = np.arange(hp.data.length) * hp.deltaF h = hp.data.data + 1j * hc.data.data return fHz, h
def spin_tidal_eob_FD(m1, m2, s1z, s2z, lambda1, lambda2, f_min, f_max, deltaF=1.0/128.0, delta_t=1.0/16384.0, distance=1.0, inclination=0.0, approximant='TEOBv4', 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', 'SEOBNRv4_ROM_NRTidal' 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', 'SEOBNRv4_ROM_NRTidal']): raise Exception, "Approximant must be 'TEOBv2', 'TEOBv4' or 'SEOBNRv4_ROM_NRTidal'." lal_approx = LS.GetApproximantFromString(approximant) if (approximant in ['TEOBv2', 'TEOBv4']): # Calculate higher order matter effects from universal relations # lambda3 given in terms of lambda2 lambda31_ur = LS.SimUniversalRelationlambda3TidalVSlambda2Tidal(lambda1) lambda32_ur = LS.SimUniversalRelationlambda3TidalVSlambda2Tidal(lambda2) # Omega2 given in terms of lambda2 omega21_ur = LS.SimUniversalRelationomega02TidalVSlambda2Tidal(lambda1) omega22_ur = LS.SimUniversalRelationomega02TidalVSlambda2Tidal(lambda2) # Omega3 given in terms of lambda3 (not lambda2) omega31_ur = LS.SimUniversalRelationomega03TidalVSlambda3Tidal(lambda31_ur) omega32_ur = LS.SimUniversalRelationomega03TidalVSlambda3Tidal(lambda32_ur) # Insert matter parameters lal_params = lal.CreateDict() LS.SimInspiralWaveformParamsInsertTidalLambda1(lal_params, lambda1) LS.SimInspiralWaveformParamsInsertTidalLambda2(lal_params, lambda2) if (approximant in ['TEOBv2', 'TEOBv4']): LS.SimInspiralWaveformParamsInsertTidalOctupolarLambda1(lal_params, lambda31_ur) LS.SimInspiralWaveformParamsInsertTidalOctupolarLambda2(lal_params, lambda32_ur) LS.SimInspiralWaveformParamsInsertTidalQuadrupolarFMode1(lal_params, omega21_ur) LS.SimInspiralWaveformParamsInsertTidalQuadrupolarFMode2(lal_params, omega22_ur) LS.SimInspiralWaveformParamsInsertTidalOctupolarFMode1(lal_params, omega31_ur) LS.SimInspiralWaveformParamsInsertTidalOctupolarFMode2(lal_params, omega32_ur) # Evaluate FD waveform Hp, Hc = LS.SimInspiralFD( m1*lal.MSUN_SI, m2*lal.MSUN_SI, s1x, s1y, s1z, s2x, s2y, s2z, distance*lal.PC_SI, inclination, phiRef, longAscNodes, eccentricity, meanPerAno, deltaF, f_min, f_max, f_ref, lal_params, lal_approx) f = deltaF * np.arange(Hp.data.length) return f, Hp, Hc
def test_bayestar_signal_amplitude_model(ra, dec, inclination, polarization, epoch, instrument): """Test BAYESTAR signal amplitude model against LAL injection code.""" detector = lalsimulation.DetectorPrefixToLALDetector(instrument) epoch = lal.LIGOTimeGPS(epoch) gmst = lal.GreenwichMeanSiderealTime(epoch) exp_i_twopsi = np.exp(2j * polarization) u = np.cos(inclination) u2 = np.square(u) F = get_complex_antenna(detector.response, ra, dec, gmst) result = signal_amplitude_model(F, exp_i_twopsi, u, u2) abs_expected = 1 / get_eff_dist(detector, ra, dec, inclination, polarization, epoch, gmst) # This is the *really* slow way of working out the signal amplitude: # generate a frequency-domain waveform and inject it. params = lal.CreateDict() lalsimulation.SimInspiralWaveformParamsInsertPNPhaseOrder( params, lalsimulation.PNORDER_NEWTONIAN) lalsimulation.SimInspiralWaveformParamsInsertPNAmplitudeOrder( params, lalsimulation.PNORDER_NEWTONIAN) # Calculate antenna factors Fplus, Fcross = lal.ComputeDetAMResponse(detector.response, ra, dec, polarization, gmst) # Check that the way I compute the antenna factors matches F = get_complex_antenna(detector.response, ra, dec, gmst) F *= np.exp(-2j * polarization) assert F.real == approx(Fplus, abs=4 * np.finfo(np.float64).eps) assert F.imag == approx(Fcross, abs=4 * np.finfo(np.float64).eps) # "Template" waveform with inclination angle of zero Htemplate, Hcross = lalsimulation.SimInspiralFD(1.4 * lal.MSUN_SI, 1.4 * lal.MSUN_SI, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 100, 101, 100, params, lalsimulation.TaylorF2) # Discard any non-quadrature phase component of "template" Htemplate.data.data += 1j * Hcross.data.data # Normalize "template" h = np.sum( np.square(Htemplate.data.data.real) + np.square(Htemplate.data.data.imag)) h = 2 / h Htemplate.data.data *= h # "Signal" waveform with requested inclination angle Hsignal, Hcross = lalsimulation.SimInspiralFD( 1.4 * lal.MSUN_SI, 1.4 * lal.MSUN_SI, 0, 0, 0, 0, 0, 0, 1, inclination, 0, 0, 0, 0, 1, 100, 101, 100, params, lalsimulation.TaylorF2) # Project "signal" using antenna factors Hsignal.data.data = Fplus * Hsignal.data.data + Fcross * Hcross.data.data # Work out complex amplitude by comparing with "template" waveform expected = np.sum(Htemplate.data.data.conj() * Hsignal.data.data) assert abs(expected) == approx(abs_expected, abs=1.5 * np.finfo(np.float32).eps) assert abs(result) == approx(abs_expected, abs=1.5 * np.finfo(np.float32).eps) assert result.real == approx(expected.real, abs=4 * np.finfo(np.float32).eps) assert result.imag == approx(expected.imag, abs=4 * np.finfo(np.float32).eps)
def sngl_inspiral_psd(waveform, mass1, mass2, f_min=10, f_final=None, f_ref=None, **kwargs): # FIXME: uberbank mass criterion. Should find a way to get this from # pipeline output metadata. if waveform == 'o1-uberbank': log.warning('Template is unspecified; ' 'using ER8/O1 uberbank criterion') if mass1 + mass2 < 4: waveform = 'TaylorF2threePointFivePN' else: waveform = 'SEOBNRv2_ROM_DoubleSpin' elif waveform == 'o2-uberbank': log.warning('Template is unspecified; ' 'using ER10/O2 uberbank criterion') if mass1 + mass2 < 4: waveform = 'TaylorF2threePointFivePN' else: waveform = 'SEOBNRv4_ROM' approx, ampo, phaseo = get_approximant_and_orders_from_string(waveform) log.info('Selected template: %s', waveform) # Generate conditioned template. params = lal.CreateDict() lalsimulation.SimInspiralWaveformParamsInsertPNPhaseOrder(params, phaseo) lalsimulation.SimInspiralWaveformParamsInsertPNAmplitudeOrder(params, ampo) hplus, hcross = lalsimulation.SimInspiralFD( m1=float(mass1) * lal.MSUN_SI, m2=float(mass2) * lal.MSUN_SI, S1x=float(kwargs.get('spin1x') or 0), S1y=float(kwargs.get('spin1y') or 0), S1z=float(kwargs.get('spin1z') or 0), S2x=float(kwargs.get('spin2x') or 0), S2y=float(kwargs.get('spin2y') or 0), S2z=float(kwargs.get('spin2z') or 0), distance=1e6 * lal.PC_SI, inclination=0, phiRef=0, longAscNodes=0, eccentricity=0, meanPerAno=0, deltaF=0, f_min=f_min, # Note: code elsewhere ensures that the sample rate is at least two # times f_final; the factor of 2 below is just a safety factor to make # sure that the sample rate is 2-4 times f_final. f_max=ceil_pow_2(2 * (f_final or 2048)), f_ref=float(f_ref or 0), LALparams=params, approximant=approx) # Force `plus' and `cross' waveform to be in quadrature. h = 0.5 * (hplus.data.data + 1j * hcross.data.data) # For inspiral-only waveforms, nullify frequencies beyond ISCO. # FIXME: the waveform generation functions pick the end frequency # automatically. Shouldn't SimInspiralFD? inspiral_only_waveforms = (lalsimulation.TaylorF2, lalsimulation.SpinTaylorF2, lalsimulation.TaylorF2RedSpin, lalsimulation.TaylorF2RedSpinTidal, lalsimulation.SpinTaylorT4Fourier) if approx in inspiral_only_waveforms: h[abscissa(hplus) >= get_f_lso(mass1, mass2)] = 0 # Throw away any frequencies above high frequency cutoff h[abscissa(hplus) >= (f_final or 2048)] = 0 # Drop Nyquist frequency. if len(h) % 2: h = h[:-1] # Create output frequency series. psd = lal.CreateREAL8FrequencySeries('signal PSD', 0, hplus.f0, hcross.deltaF, hplus.sampleUnits**2, len(h)) psd.data.data = abs2(h) # Done! return psd
from lal import LIGOTimeGPS, GreenwichMeanSiderealTime, ComputeDetAMResponse import lal detectors = dict([(d.frDetector.prefix, d) for d in lal.CachedDetectors]) import lalsimulation """ _ref_h, _ = lalsimulation.SimInspiralFD( 1.4 * lal.MSUN_SI, 1.4 * lal.MSUN_SI, 0., 0., 0., 0., 0., 0., 100e6 * lal.PC_SI, 0.0, 0.0, 0.0, 0.0, 0.0, 0.125, 10.0, 2048., None, lalsimulation.SimInspiralGetApproximantFromString("IMRPhenomPv2")) """ _ref_h_bns, _ = lalsimulation.SimInspiralFD( 0.0, 0.125, 1.4 * lal.MSUN_SI, 1.4 * lal.MSUN_SI, 0., 0., 0., 0., 0., 0., 10., 2048., 10., 100e6 * lal.PC_SI, 0.0, 0.0, 0.0, 0.0, None, None, -1, -1, lalsimulation.SimInspiralGetApproximantFromString("IMRPhenomPv2")) _ref_h_nsbh, _ = lalsimulation.SimInspiralFD( 0.0, 0.125, 1.4 * lal.MSUN_SI, 10. * lal.MSUN_SI, 0., 0., 0., 0., 0., 0., 10., 2048., 10., 100e6 * lal.PC_SI, 0.0, 0.0, 0.0, 0.0, None, None, -1, -1, lalsimulation.SimInspiralGetApproximantFromString("IMRPhenomPv2")) _ref_h_nsbh_ms, _ = lalsimulation.SimInspiralFD( 0.0, 0.125, 1.4 * lal.MSUN_SI, 10. * lal.MSUN_SI, 0., 0., 0., 0., 0., 0.9, 10., 2048., 10., 100e6 * lal.PC_SI, 0.0, 0.0, 0.0, 0.0, None, None, -1, -1, lalsimulation.SimInspiralGetApproximantFromString("IMRPhenomPv2")) _default_psds = { "H1": lalsimulation.SimNoisePSDaLIGOZeroDetHighPower, "I1": lalsimulation.SimNoisePSDaLIGOZeroDetHighPower,