def multimode_base(input_params): """Return a superposition of damped sinusoids in either time or frequency domains with parameters set by input_params. """ input_params['lmns'] = format_lmns(input_params['lmns']) amps, phis = lm_amps_phases(**input_params) if 'final_mass' in input_params.keys(): freqs, taus = get_lm_f0tau_allmodes(input_params['final_mass'], input_params['final_spin'], input_params['lmns']) norm = Kerr_factor(input_params['final_mass'], input_params['distance']) if 'distance' in input_params.keys() \ else 1. else: freqs, taus = lm_freqs_taus(**input_params) norm = 1. if 'delta_t' in input_params.keys(): outplus, outcross = td_output_vector(freqs, taus, input_params['taper'], input_params['delta_t'], input_params['t_final']) for lmn in freqs: hplus, hcross = td_damped_sinusoid(freqs[lmn], taus[lmn], amps[lmn], phis[lmn], outplus.delta_t, outplus.sample_times[-1], int(lmn[0]), int(lmn[1]), input_params['inclination']) if input_params['taper'] and outplus.delta_t < taus[lmn]: taper_hp, taper_hc = apply_taper(taus[lmn], amps[lmn], phis[lmn], outplus.delta_t, int(lmn[0]), int(lmn[1]), input_params['inclination']) t0 = -int(outplus.start_time * outplus.sample_rate) outplus[t0 - len(taper_hp):t0].data += taper_hp outplus[t0:].data += hplus outcross[t0 - len(taper_hc):t0].data += taper_hc outcross[t0:].data += hcross elif input_params['taper'] and outplus.delta_t > taus[lmn]: # This mode has taper duration < delta_t, do not apply taper t0 = -int(outplus.start_time * outplus.sample_rate) outplus[t0:].data += hplus outcross[t0:].data += hcross else: outplus.data += hplus outcross.data += hcross elif 'delta_f' in input_params.keys(): outplus, outcross = fd_output_vector(freqs, taus, input_params['delta_f'], input_params['f_final']) for lmn in freqs: hplus, hcross = fd_damped_sinusoid( freqs[lmn], taus[lmn], amps[lmn], phis[lmn], outplus.delta_f, input_params['f_lower'], outplus.sample_frequencies[-1], int(lmn[0]), int(lmn[1]), input_params['inclination']) outplus.data += hplus.data outcross.data += hcross.data return norm * outplus, norm * outcross
def get_fd_from_final_mass_spin(template=None, distance=None, **kwargs): """Return frequency domain ringdown with all the modes specified. Parameters ---------- template: object An object that has attached properties. This can be used to substitute for keyword arguments. A common example would be a row in an xml table. distance : {None, float}, optional Luminosity distance of the system. If specified, the returned ringdown will contain the factor (final_mass/distance). final_mass : float Mass of the final black hole. final_spin : float Spin of the final black hole. lmns : list Desired lmn modes as strings (lm modes available: 22, 21, 33, 44, 55). The n specifies the number of overtones desired for the corresponding lm pair (maximum n=8). Example: lmns = ['223','331'] are the modes 220, 221, 222, and 330 amp220 : float Amplitude of the fundamental 220 mode. Note that if distance is given, this parameter will have a completely different order of magnitude. See table II in https://arxiv.org/abs/1107.0854 for an estimate. amplmn : float Fraction of the amplitude of the lmn overtone relative to the fundamental mode, as many as the number of subdominant modes. philmn : float Phase of the lmn overtone, as many as the number of modes. Should also include the information from the azimuthal angle (phi + m*Phi). inclination : float Inclination of the system in radians. delta_f : {None, float}, optional The frequency step used to generate the ringdown. If None, it will be set to the inverse of the time at which the amplitude is 1/1000 of the peak amplitude (the minimum of all modes). f_lower: {None, float}, optional The starting frequency of the output frequency series. If None, it will be set to delta_f. f_final : {None, float}, optional The ending frequency of the output frequency series. If None, it will be set to the frequency at which the amplitude is 1/1000 of the peak amplitude (the maximum of all modes). Returns ------- hplustilde: FrequencySeries The plus phase of a ringdown with the lm modes specified and n overtones in frequency domain. hcrosstilde: FrequencySeries The cross phase of a ringdown with the lm modes specified and n overtones in frequency domain. """ input_params = props(template, mass_spin_required_args, **kwargs) # Get required args final_mass = input_params['final_mass'] final_spin = input_params['final_spin'] lmns = input_params['lmns'] for lmn in lmns: if int(lmn[2]) == 0: raise ValueError('Number of overtones (nmodes) must be greater ' 'than zero.') # The following may not be in input_params delta_f = input_params.pop('delta_f', None) f_lower = input_params.pop('f_lower', None) f_final = input_params.pop('f_final', None) f_0, tau = get_lm_f0tau_allmodes(final_mass, final_spin, lmns) if not delta_f: delta_f = lm_deltaf(tau, lmns) if not f_final: f_final = lm_ffinal(f_0, tau, lmns) if not f_lower: f_lower = delta_f kmax = int(f_final / delta_f) + 1 outplustilde = FrequencySeries(zeros(kmax, dtype=complex128), delta_f=delta_f) outcrosstilde = FrequencySeries(zeros(kmax, dtype=complex128), delta_f=delta_f) for lmn in lmns: l, m, nmodes = int(lmn[0]), int(lmn[1]), int(lmn[2]) hplustilde, hcrosstilde = get_fd_lm(freqs=f_0, taus=tau, l=l, m=m, nmodes=nmodes, delta_f=delta_f, f_lower=f_lower, f_final=f_final, **input_params) outplustilde.data += hplustilde.data outcrosstilde.data += hcrosstilde.data norm = Kerr_factor(final_mass, distance) if distance else 1. return norm*outplustilde, norm*outcrosstilde
def get_td_from_final_mass_spin(template=None, taper=None, distance=None, **kwargs): """Return time domain ringdown with all the modes specified. Parameters ---------- template: object An object that has attached properties. This can be used to substitute for keyword arguments. A common example would be a row in an xml table. taper: {None, float}, optional Tapering at the beginning of the waveform with duration taper * tau. This option is recommended with timescales taper=1./2 or 1. for time-domain ringdown-only injections. The abrupt turn on of the ringdown can cause issues on the waveform when doing the fourier transform to the frequency domain. Setting taper will add a rapid ringup with timescale tau/10. Each mode and overtone will have a different taper depending on its tau, the final taper being the superposition of all the tapers. distance : {None, float}, optional Luminosity distance of the system. If specified, the returned ringdown will contain the factor (final_mass/distance). final_mass : float Mass of the final black hole. final_spin : float Spin of the final black hole. lmns : list Desired lmn modes as strings (lm modes available: 22, 21, 33, 44, 55). The n specifies the number of overtones desired for the corresponding lm pair (maximum n=8). Example: lmns = ['223','331'] are the modes 220, 221, 222, and 330 amp220 : float Amplitude of the fundamental 220 mode. Note that if distance is given, this parameter will have a completely different order of magnitude. See table II in https://arxiv.org/abs/1107.0854 for an estimate. amplmn : float Fraction of the amplitude of the lmn overtone relative to the fundamental mode, as many as the number of subdominant modes. philmn : float Phase of the lmn overtone, as many as the number of modes. Should also include the information from the azimuthal angle (phi + m*Phi). inclination : float Inclination of the system in radians. delta_t : {None, float}, optional The time step used to generate the ringdown. If None, it will be set to the inverse of the frequency at which the amplitude is 1/1000 of the peak amplitude (the minimum of all modes). t_final : {None, float}, optional The ending time of the output frequency series. If None, it will be set to the time at which the amplitude is 1/1000 of the peak amplitude (the maximum of all modes). Returns ------- hplus: TimeSeries The plus phase of a ringdown with the lm modes specified and n overtones in time domain. hcross: TimeSeries The cross phase of a ringdown with the lm modes specified and n overtones in time domain. """ input_params = props(template, mass_spin_required_args, **kwargs) # Get required args final_mass = input_params['final_mass'] final_spin = input_params['final_spin'] lmns = input_params['lmns'] for lmn in lmns: if int(lmn[2]) == 0: raise ValueError('Number of overtones (nmodes) must be greater ' 'than zero.') # following may not be in input_params delta_t = input_params.pop('delta_t', None) t_final = input_params.pop('t_final', None) f_0, tau = get_lm_f0tau_allmodes(final_mass, final_spin, lmns) if not delta_t: delta_t = lm_deltat(f_0, tau, lmns) if not t_final: t_final = lm_tfinal(tau, lmns) kmax = int(t_final / delta_t) + 1 # Different overtones will have different tapering window-size # Find maximum window size to create long enough output vector if taper: taper_window = int(taper*max(tau.values())/delta_t) kmax += taper_window outplus = TimeSeries(zeros(kmax, dtype=float64), delta_t=delta_t) outcross = TimeSeries(zeros(kmax, dtype=float64), delta_t=delta_t) if taper: start = - taper * max(tau.values()) outplus._epoch, outcross._epoch = start, start for lmn in lmns: l, m, nmodes = int(lmn[0]), int(lmn[1]), int(lmn[2]) hplus, hcross = get_td_lm(taper=taper, freqs=f_0, taus=tau, l=l, m=m, nmodes=nmodes, delta_t=delta_t, t_final=t_final, **input_params) if not taper: outplus.data += hplus.data outcross.data += hcross.data else: outplus = taper_shift(hplus, outplus) outcross = taper_shift(hcross, outcross) norm = Kerr_factor(final_mass, distance) if distance else 1. return norm*outplus, norm*outcross
def multimode_base(input_params, domain, freq_tau_approximant=False): """Return a superposition of damped sinusoids in either time or frequency domains with parameters set by input_params. Parameters ---------- domain : string Choose domain of the waveform, either 'td' for time domain or 'fd' for frequency domain. freq_tau_approximant : {False, bool}, optional Choose choose the waveform approximant to use. Either based on mass/spin (set to False, default), or on frequencies/damping times of the modes (set to True). Returns ------- hplus : TimeSeries The plus phase of a ringdown with the lm modes specified and n overtones in the chosen domain (time or frequency). hcross : TimeSeries The cross phase of a ringdown with the lm modes specified and n overtones in the chosen domain (time or frequency). """ input_params['lmns'] = format_lmns(input_params['lmns']) amps, phis = lm_amps_phases(**input_params) if freq_tau_approximant: freqs, taus = lm_freqs_taus(**input_params) norm = 1. else: freqs, taus = get_lm_f0tau_allmodes(input_params['final_mass'], input_params['final_spin'], input_params['lmns']) norm = Kerr_factor(input_params['final_mass'], input_params['distance']) if 'distance' in input_params.keys() \ else 1. for mode in freqs: if 'delta_f{}'.format(mode) in input_params: freqs[mode] += input_params['delta_f{}'.format(mode)] * freqs[mode] for mode in taus: if 'delta_tau{}'.format(mode) in input_params: taus[mode] += input_params['delta_tau{}'.format(mode)] * taus[mode] if domain == 'td': outplus, outcross = td_output_vector(freqs, taus, input_params['taper'], input_params['delta_t'], input_params['t_final']) for lmn in freqs: hplus, hcross = td_damped_sinusoid(freqs[lmn], taus[lmn], amps[lmn], phis[lmn], outplus.delta_t, outplus.sample_times[-1], int(lmn[0]), int(lmn[1]), input_params['inclination']) if input_params['taper'] and outplus.delta_t < taus[lmn]: taper_hp, taper_hc = apply_taper(taus[lmn], amps[lmn], phis[lmn], outplus.delta_t, int(lmn[0]), int(lmn[1]), input_params['inclination']) t0 = -int(outplus.start_time * outplus.sample_rate) outplus[t0-len(taper_hp):t0].data += taper_hp outplus[t0:].data += hplus outcross[t0-len(taper_hc):t0].data += taper_hc outcross[t0:].data += hcross elif input_params['taper'] and outplus.delta_t > taus[lmn]: # This mode has taper duration < delta_t, do not apply taper t0 = -int(outplus.start_time * outplus.sample_rate) outplus[t0:].data += hplus outcross[t0:].data += hcross else: outplus.data += hplus outcross.data += hcross elif domain == 'fd': outplus, outcross = fd_output_vector(freqs, taus, input_params['delta_f'], input_params['f_final']) for lmn in freqs: hplus, hcross = fd_damped_sinusoid(freqs[lmn], taus[lmn], amps[lmn], phis[lmn], outplus.delta_f, input_params['f_lower'], input_params['f_final'], l=int(lmn[0]), m=int(lmn[1]), inclination=input_params['inclination']) outplus.data += hplus.data outcross.data += hcross.data else: raise ValueError('unrecognised domain argument {}; ' 'must be either fd or td'.format(domain)) return norm * outplus, norm * outcross
def get_fd_from_final_mass_spin(template=None, distance=None, **kwargs): """Return frequency domain ringdown with all the modes specified. Parameters ---------- template: object An object that has attached properties. This can be used to substitute for keyword arguments. A common example would be a row in an xml table. distance : {None, float}, optional Luminosity distance of the system. If specified, the returned ringdown will contain the factor (final_mass/distance). final_mass : float Mass of the final black hole. final_spin : float Spin of the final black hole. lmns : list Desired lmn modes as strings (lm modes available: 22, 21, 33, 44, 55). The n specifies the number of overtones desired for the corresponding lm pair (maximum n=8). Example: lmns = ['223','331'] are the modes 220, 221, 222, and 330 amp220 : float Amplitude of the fundamental 220 mode. Note that if distance is given, this parameter will have a completely different order of magnitude. See table II in https://arxiv.org/abs/1107.0854 for an estimate. amplmn : float Fraction of the amplitude of the lmn overtone relative to the fundamental mode, as many as the number of subdominant modes. philmn : float Phase of the lmn overtone, as many as the number of modes. Should also include the information from the azimuthal angle (phi + m*Phi). inclination : float Inclination of the system in radians. delta_f : {None, float}, optional The frequency step used to generate the ringdown. If None, it will be set to the inverse of the time at which the amplitude is 1/1000 of the peak amplitude (the minimum of all modes). f_lower: {None, float}, optional The starting frequency of the output frequency series. If None, it will be set to delta_f. f_final : {None, float}, optional The ending frequency of the output frequency series. If None, it will be set to the frequency at which the amplitude is 1/1000 of the peak amplitude (the maximum of all modes). Returns ------- hplustilde: FrequencySeries The plus phase of a ringdown with the lm modes specified and n overtones in frequency domain. hcrosstilde: FrequencySeries The cross phase of a ringdown with the lm modes specified and n overtones in frequency domain. """ input_params = props(template, mass_spin_required_args, **kwargs) # Get required args final_mass = input_params['final_mass'] final_spin = input_params['final_spin'] lmns = input_params['lmns'] for lmn in lmns: if int(lmn[2]) == 0: raise ValueError('Number of overtones (nmodes) must be greater ' 'than zero.') # The following may not be in input_params delta_f = input_params.pop('delta_f', None) f_lower = input_params.pop('f_lower', None) f_final = input_params.pop('f_final', None) f_0, tau = get_lm_f0tau_allmodes(final_mass, final_spin, lmns) if not delta_f: delta_f = lm_deltaf(tau, lmns) if not f_final: f_final = lm_ffinal(f_0, tau, lmns) if not f_lower: f_lower = delta_f kmax = int(f_final / delta_f) + 1 outplustilde = FrequencySeries(zeros(kmax, dtype=complex128), delta_f=delta_f) outcrosstilde = FrequencySeries(zeros(kmax, dtype=complex128), delta_f=delta_f) for lmn in lmns: l, m, nmodes = int(lmn[0]), int(lmn[1]), int(lmn[2]) hplustilde, hcrosstilde = get_fd_lm(freqs=f_0, taus=tau, l=l, m=m, nmodes=nmodes, delta_f=delta_f, f_lower=f_lower, f_final=f_final, **input_params) outplustilde.data += hplustilde.data outcrosstilde.data += hcrosstilde.data norm = Kerr_factor(final_mass, distance) if distance else 1. return norm * outplustilde, norm * outcrosstilde
def get_td_from_final_mass_spin(template=None, taper=None, distance=None, **kwargs): """Return time domain ringdown with all the modes specified. Parameters ---------- template: object An object that has attached properties. This can be used to substitute for keyword arguments. A common example would be a row in an xml table. taper: {None, float}, optional Tapering at the beginning of the waveform with duration taper * tau. This option is recommended with timescales taper=1./2 or 1. for time-domain ringdown-only injections. The abrupt turn on of the ringdown can cause issues on the waveform when doing the fourier transform to the frequency domain. Setting taper will add a rapid ringup with timescale tau/10. Each mode and overtone will have a different taper depending on its tau, the final taper being the superposition of all the tapers. distance : {None, float}, optional Luminosity distance of the system. If specified, the returned ringdown will contain the factor (final_mass/distance). final_mass : float Mass of the final black hole. final_spin : float Spin of the final black hole. lmns : list Desired lmn modes as strings (lm modes available: 22, 21, 33, 44, 55). The n specifies the number of overtones desired for the corresponding lm pair (maximum n=8). Example: lmns = ['223','331'] are the modes 220, 221, 222, and 330 amp220 : float Amplitude of the fundamental 220 mode. Note that if distance is given, this parameter will have a completely different order of magnitude. See table II in https://arxiv.org/abs/1107.0854 for an estimate. amplmn : float Fraction of the amplitude of the lmn overtone relative to the fundamental mode, as many as the number of subdominant modes. philmn : float Phase of the lmn overtone, as many as the number of modes. Should also include the information from the azimuthal angle (phi + m*Phi). inclination : float Inclination of the system in radians. delta_t : {None, float}, optional The time step used to generate the ringdown. If None, it will be set to the inverse of the frequency at which the amplitude is 1/1000 of the peak amplitude (the minimum of all modes). t_final : {None, float}, optional The ending time of the output frequency series. If None, it will be set to the time at which the amplitude is 1/1000 of the peak amplitude (the maximum of all modes). Returns ------- hplus: TimeSeries The plus phase of a ringdown with the lm modes specified and n overtones in time domain. hcross: TimeSeries The cross phase of a ringdown with the lm modes specified and n overtones in time domain. """ input_params = props(template, mass_spin_required_args, **kwargs) # Get required args final_mass = input_params['final_mass'] final_spin = input_params['final_spin'] lmns = input_params['lmns'] for lmn in lmns: if int(lmn[2]) == 0: raise ValueError('Number of overtones (nmodes) must be greater ' 'than zero.') # following may not be in input_params delta_t = input_params.pop('delta_t', None) t_final = input_params.pop('t_final', None) f_0, tau = get_lm_f0tau_allmodes(final_mass, final_spin, lmns) if not delta_t: delta_t = lm_deltat(f_0, tau, lmns) if not t_final: t_final = lm_tfinal(tau, lmns) kmax = int(t_final / delta_t) + 1 # Different overtones will have different tapering window-size # Find maximum window size to create long enough output vector if taper: taper_window = int(taper * max(tau.values()) / delta_t) kmax += taper_window outplus = TimeSeries(zeros(kmax, dtype=float64), delta_t=delta_t) outcross = TimeSeries(zeros(kmax, dtype=float64), delta_t=delta_t) if taper: start = -taper * max(tau.values()) outplus._epoch, outcross._epoch = start, start for lmn in lmns: l, m, nmodes = int(lmn[0]), int(lmn[1]), int(lmn[2]) hplus, hcross = get_td_lm(taper=taper, freqs=f_0, taus=tau, l=l, m=m, nmodes=nmodes, delta_t=delta_t, t_final=t_final, **input_params) if not taper: outplus.data += hplus.data outcross.data += hcross.data else: outplus = taper_shift(hplus, outplus) outcross = taper_shift(hcross, outcross) norm = Kerr_factor(final_mass, distance) if distance else 1. return norm * outplus, norm * outcross