Пример #1
0
def generate_LAL_modes(approximant, q, chiA0, chiB0, dt, M, \
    dist_mpc, f_low, f_ref, phi_ref, ellMax=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)

    dictParams = lal.CreateDict()
    if ellMax is not None:
        ma = lalsim.SimInspiralCreateModeArray()
        for ell in range(2, ellMax + 1):
            lalsim.SimInspiralModeArrayActivateAllModesAtL(ma, ell)
        lalsim.SimInspiralWaveformParamsInsertModeArray(dictParams, ma)

    lmax = 5  # This in unused
    hmodes = lalsim.SimInspiralChooseTDModes(phi_ref, dt, m1_kg, m2_kg, \
        chiA0[0], chiA0[1], chiA0[2], chiB0[0], chiB0[1], chiB0[2], \
        f_low, f_ref, distance, dictParams, lmax, approxTag)

    t = np.arange(len(hmodes.mode.data.data)) * dt
    mode_dict = {}
    while hmodes is not None:
        mode_dict['h_l%dm%d' % (hmodes.l, hmodes.m)] = hmodes.mode.data.data
        hmodes = hmodes.next
    return t, mode_dict
Пример #2
0
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
Пример #3
0
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
Пример #4
0
    def _get_surrogate_dynamics(self, q, chiA0, chiB0, init_quat, \
            init_orbphase, omega_ref, unlimited_extrapolation):
        """ A wrapper for NRSur7dq4 dynamics.

        Inputs:
            q:          Mass ratio, mA/mB >= 1.
            chiA0:      Dimless spin of BhA in the coorbital frame at omega_ref.
            chiB0:      Dimless spin of BhB in the coorbital frame at omega_ref.
            init_quat:  Coprecessing frame quaternion at omega_ref.
            init_orbphase:
                        Orbital phase in the coprecessing frame at omega_ref.
            omega_ref:  Orbital frequency in the coprecessing frame at the
                        reference epoch where the input spins are given. Note:
                        This is total-mass times the angular orbital frequency.
            unlimited_extrapolation:
                        If True, allows unlimited extrapolation to regions well
                        outside the surrogate's training region. Else, raises
                        an error.

        Outputs:
            t_dyn:      Time values at which the dynamics are returned. These
                        are nonuniform and sparse.
            copr_quat:  Time series of coprecessing frame quaternions.
            orbphase:   Orbital phase time series in the coprecessing frame.
            chiA_copr:  Time series of spin of BhA in the coprecessing frame.
            chiB_copr:  Time series of spin of BhB in the coprecessing frame.
        """

        approxTag = lalsim.SimInspiralGetApproximantFromString("NRSur7dq4")
        LALParams = lal.CreateDict()
        if unlimited_extrapolation:
            lal.DictInsertUINT4Value(LALParams, "unlimited_extrapolation", 1)

        t_dyn, quat0, quat1, quat2, quat3, orbphase, chiAx, chiAy, chiAz, \
            chiBx, chiBy, chiBz = lalsim.PrecessingNRSurDynamics(q, \
            chiA0[0], chiA0[1], chiA0[2], chiB0[0], chiB0[1], chiB0[2], \
            omega_ref, init_quat[0], init_quat[1], init_quat[2], init_quat[3], \
            init_orbphase, LALParams, approxTag)

        t_dyn = t_dyn.data
        orbphase = orbphase.data
        copr_quat = np.array([quat0.data, quat1.data, quat2.data, quat3.data])
        chiA_copr = np.array([chiAx.data, chiAy.data, chiAz.data]).T
        chiB_copr = np.array([chiBx.data, chiBy.data, chiBz.data]).T

        return t_dyn, copr_quat, orbphase, chiA_copr, chiB_copr
Пример #5
0
def get_SEOBNRv4PHM_modes(q, M, chi1, chi2, f_start, deltaT=1. / (4096 * 4.)):
    #See the paper: https://arxiv.org/pdf/2004.09442.pdf
    """Generate SEOBNRv4PHM modes"""
    prefactor = 4.7864188273360336e-20  # G/c^2*(M_sun/Mpc)
    distance = 1. * 1e6 * lal.PC_SI  # 1 Mpc in m
    amp_prefactor = prefactor * M / 1.  # G/c^2 (M / d_L)
    nu = q / (1 + q)**2

    m1SI = lal.MSUN_SI * q * M / (1.0 + q)
    m2SI = lal.MSUN_SI * M / (1.0 + q)
    #approx = lalsim.SEOBNRv4PHM
    approx = lalsim.SimInspiralGetApproximantFromString('SEOBNRv4PHM')
    hlm = lalsim.SimInspiralChooseTDModes(
        0.,
        deltaT,
        m1SI,
        m2SI,
        chi1[0],
        chi1[1],
        chi1[2],
        chi2[0],
        chi2[1],
        chi2[2],
        f_start,  #/**< starting GW frequency (Hz) */ #what is this f_start?? 
        f_start,  #/**< reference GW frequency (Hz) */
        distance,
        None,
        5,
        approx,
    )
    hI = {}
    modes = [(2, 2), (2, 1), (2, -1), (3, 3), (4, 4), (5, 5)]
    for lm in modes:
        hI[lm] = lalsim.SphHarmTimeSeriesGetMode(
            hlm, lm[0], lm[1]).data.data / amp_prefactor / nu

    times = np.linspace(0, len(hI[(2, 2)]) * deltaT, len(hI[(2, 2)]))
    h_22 = hI[(2, 2)]
    ph = np.unwrap(np.angle(np.conj(h_22)))
    omega_22 = (ph[2] - ph[0]) / (2 * deltaT)
    print("FREQUENCY of THE WF: ", omega_22, omega_22 / (2 * np.pi))
    t_max = times[np.argmax(np.abs(h_22))]
    times = times - t_max
    return times, hI
Пример #6
0
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
Пример #7
0
def create_dataset_FD(N_data,
                      N_grid=None,
                      filename=None,
                      q_range=(1., 5.),
                      m2_range=20.,
                      s1_range=(-0.8, 0.8),
                      s2_range=(-0.8, 0.8),
                      log_space=True,
                      f_high=2000,
                      f_step=1e-2,
                      f_max=None,
                      f_min=None,
                      approximant="IMRPhenomPv2"):
    """
	Create a dataset for training a ML model to fit GW waveforms in frequency 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 are drawn randomly in the range given by the user: it holds m1 = q *m2 M_sun.
	The waveforms are computed from f_low = 15 to f_high with a step f_step and then evaluated at some N_grid grid points equally spaced in range [f_min, f_max]
	Dataset can be loaded with load_dataset
	Input:
		N_data			size of dataset
		N_grid			number of points to be sampled in the grid (if None every point generated is saved)
		filename		name of the file to save dataset in (If is None, nothing is saved on a file)
		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
		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
		log_space		whether grid should be computed in logspace
		f_high			highest frequency to compute
		f_step			step considered for computation of waveforms
		f_max			maximum frequency returned to the user (if None is the same as f_max)
		f_min			minimum frequency returned to the user (if None is the same as f_low = 15)
		approximant	string for the approximant model to be used (in lal convention)
	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
			frequencies (N_grid,)		vector holding frequencies at which waves are evaluated
	"""
    if f_max is None:
        f_max = f_high
    if f_min is None:
        f_min = 1.
    f_low = f_min
    K = int(
        (f_max - f_min) /
        f_step)  #number of data points to be taken from the returned vector
    if N_grid is None:
        N_grid = K
    full_freq = np.arange(f_low, f_max,
                          f_step)  #full frequency vector as returned by lal
    d = 1.
    LALpars = lal.CreateDict()
    approx = lalsim.SimInspiralGetApproximantFromString(approximant)

    #allocating storage for temp vectors to save a single WF
    temp_amp = np.zeros((N_grid, ))
    temp_ph = np.zeros((N_grid, ))
    temp_theta = np.zeros((3, ))

    #setting frequencies to be returned to user
    if log_space:
        frequencies = np.logspace(np.log10(f_min), np.log10(f_max), N_grid)
    else:
        frequencies = np.linspace(f_min, f_max, N_grid)
        #freq_to_choose = np.arange(0, K, K/N_grid).astype(int) #choosing proper indices s.t. dataset holds N_grid points
        #frequencies = full_freq[freq_to_choose] #setting only frequencies to be chosen

    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, )), frequencies, frequencies))
            freq_header = np.reshape(freq_header, (1, len(freq_header)))
            np.savetxt(
                filebuff,
                freq_header,
                header="# row: theta 3 | amp " + str(frequencies.shape[0]) +
                "| ph " + str(frequencies.shape[0]) + "\n# N_grid = " +
                str(N_grid) + " | f_step =" + str(f_step) + " | q_range = " +
                str(q_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, 3))

    for i in range(N_data):  #loop on data to be created
        if i % 100 == 0 and i != 0:
            print("Generated WF ", i)

            #setting value for data
        if isinstance(m2_range, tuple):
            m2 = np.random.uniform(m2_range[0], m2_range[1])
        else:
            m2 = m2_range
        if isinstance(q_range, tuple):
            m1 = np.random.uniform(q_range[0], q_range[1]) * m2
        else:
            m1 = q_range * m2
        if isinstance(s1_range, tuple):
            spin1z = np.random.uniform(s1_range[0], s1_range[1])
        else:
            spin1z = s1_range
        if isinstance(s2_range, tuple):
            spin2z = np.random.uniform(s2_range[0], s2_range[1])
        else:
            spin2z = s2_range

            #debug!!!
        if m1 / m2 > 4.6 and (np.abs(spin1z) > 0.8 or np.abs(spin2z) > 0.8):
            continue

            #getting the wave
        hptilde, hctilde = lalsim.SimInspiralChooseFDWaveform(  #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
            0.,  #inclination
            0.,  #phi ref
            0.,  #longAscNodes (for precession)
            0.,  #eccentricity
            0.,  #meanPerAno (for precession)
            f_step,  # frequency incremental step
            f_low,  # lowest value of frequency
            f_high,  # highest value of frequency
            f_low,  #some reference value of frequency (??)
            LALpars,  #some lal dictionary
            approx  #approx method for the model
        )
        h = np.array(hptilde.data.data) + 1j * np.array(
            hctilde.data.data)  #complex waveform
        temp_theta = [m1 / m2, spin1z, spin2z]
        temp_amp = (np.abs(h)[int(f_min / f_step):int(f_max / f_step)].real)
        temp_ph = (np.unwrap(
            np.angle(h))[int(f_min / f_step):int(f_max / f_step)].real)

        #bringing waves on the chosen grid
        temp_amp = np.interp(frequencies, full_freq, temp_amp)
        temp_ph = np.interp(frequencies, full_freq, temp_ph)
        #temp_ph = temp_ph[freq_to_choose]; temp_amp = temp_amp[freq_to_choose] #old version of code

        temp_ph = temp_ph - temp_ph[
            0]  #all frequencies are shifted by a constant to make the wave start at zero phase!!!! IMPORTANT

        #removing spourious gaps (if present)
        (index, ) = np.where(
            temp_amp / temp_amp[0] <
            5e-3)  #there should be a way to choose right threshold...
        if len(index) > 0:
            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, frequencies
    else:
        filebuff.close()
        return None
Пример #8
0
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
Пример #9
0
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,
    "K1": lalsimulation.SimNoisePSDaLIGOZeroDetHighPower,
Пример #10
0
def lal_spin_evloution_wrapper(approximant, q, omega0, chiA0, chiB0, dt, spinO,
                               phaseO):
    """
    Inputs:
        approximant:    'SpinTaylorT1/T2/T4'
        q:              Mass ratio (q>=1)
        omega0:         Initial orbital frequency in dimless units.
        chiA0:          Dimless spin of BhA at initial freq.
        chiB0:          Dimless spin of BhB at initial freq.
        dt:             Dimless step time for evolution.
        spinO:          Twice PN order of spin effects.
        phaseO:         Twice PN order in phase.

    Outputs (all are time series):
        Omega:    Dimensionless orbital frequency.
        Phi:            Orbital phase (radians)
        ChiA:           Dimensionless spin of BhA
        ChiB:           Dimensionless spin of BhB
        LNhat:          Orbital angular momentum direction
        E1:             Orbital plane basis vector

    The frame is defined at the initial frequency, as follows:
        z-axis is set by the orbital angular momentum direction.
        x-axis is the separation vector from BhB to BhA.
        y-axis completes the triad by right-hand rule.
        All quantities are defined in this fixed frame, including initial spins,
        returned spins, other vectors like LNhat, etc.
    """

    approxTag = lalsim.SimInspiralGetApproximantFromString(approximant)

    # Total mass in solar masses
    M = 100  # This does not affect the returned values as they are
    # dimension less

    # time step and initial GW freq in SI units
    MT = M * MTSUN_SI
    deltaT = dt * MT
    fStart = omega0 / np.pi / MT

    # component masses of the binary
    m1_SI = M * MSUN_SI * q / (1. + q)
    m2_SI = M * MSUN_SI / (1. + q)

    # spins at fStart
    s1x, s1y, s1z = chiA0
    s2x, s2y, s2z = chiB0

    # integrate as far forward as possible
    fEnd = 0

    # initial value of orbital angular momentum unit vector, i.e at fStart
    lnhatx, lnhaty, lnhatz = 0, 0, 1

    # initial value of orbital plane basis vector, i.e at fStart
    e1x, e1y, e1z = 1, 0, 0

    # tidal deformability parameters
    lambda1, lambda2 = 0, 0
    quadparam1, quadparam2 = 1, 1

    # twice PN order of tidal effects
    tideO = 0

    # include some L-S terms
    lscorr = 1

    ### This function evolves the orbital equations for a precessing binary
    ### using the "TaylorT1/T2/T4" approximant for solving the orbital dynamics
    ### (see arXiv:0907.0700 for a review of the various PN approximants).
    ###
    ### It returns time series of the "orbital velocity", orbital phase,
    ### and components for both individual spin vectors, the "Newtonian"
    ### orbital angular momentum (which defines the instantaneous plane)
    ### and "E1", a basis vector in the instantaneous orbital plane. Note that
    ### LNhat and E1 completely specify the instantaneous orbital plane.
    ### It also returns the time and phase of the final time step
    ###
    ### For input, the function takes the two masses, the initial orbital phase,
    ### Values of S1, S2, LNhat, E1 vectors at starting time,
    ### the desired time step size, the starting GW frequency,
    ### and PN order at which to evolve the phase,
    ###
    ### NOTE: All vectors are given in the frame
    ### where the z-axis is set by the angular momentum at reference frequency,
    ### the x-axis is chosen orthogonal to it, and the y-axis is given by the
    ### RH rule. Initial values must be passed in this frame, and the time
    ### series of the vector components will also be returned in this frame.
    ###
    ###
    ### V,            post-Newtonian parameter [returned]
    ### Phi,          orbital phase            [returned]
    ### S1x,          Spin1 vector x component [returned]
    ### S1y,          "    "    "  y component [returned]
    ### S1z,          "    "    "  z component [returned]
    ### S2x,          Spin2 vector x component [returned]
    ### S2y,          "    "    "  y component [returned]
    ### S2z,          "    "    "  z component [returned]
    ### LNhatx,       unit orbital ang. mom. x [returned]
    ### LNhaty,       "    "    "  y component [returned]
    ### LNhatz,       "    "    "  z component [returned]
    ### E1x,          orb. plane basis vector x[returned]
    ### E1y,          "    "    "  y component [returned]
    ### E1z,          "    "    "  z component [returned]
    ###
    ###
    ### deltaT,       sampling interval (s)
    ### m1_SI,        mass of companion 1 (kg)
    ### m2_SI,        mass of companion 2 (kg)
    ### fStart,       starting GW frequency
    ### fEnd,         ending GW frequency, fEnd=0 means integrate as far
    ###                 forward as possible
    ### s1x,          initial value of S1x
    ### s1y,          initial value of S1y
    ### s1z,          initial value of S1z
    ### s2x,          initial value of S2x
    ### s2y,          initial value of S2y
    ### s2z,          initial value of S2z
    ### lnhatx,       initial value of LNhatx
    ### lnhaty,       initial value of LNhaty
    ### lnhatz,       initial value of LNhatz
    ### e1x,          initial value of E1x
    ### e1y,          initial value of E1y
    ### e1z,          initial value of E1z
    ### lambda1,      tidal deformability of mass 1
    ### lambda2,      tidal deformability of mass 2
    ### quadparam1,   phenom. parameter describing induced quad.
    ###                 moment of body 1 (=1 for BHs, ~2-12 for NSs)
    ### quadparam2,   phenom. parameter describing induced quad.
    ###                 moment of body 2 (=1 for BHs, ~2-12 for NSs)
    ### spinO,        twice PN order of spin effects
    ### tideO,        twice PN order of tidal effects
    ### phaseO,       twice post-Newtonian order
    ### lscorr,       Flag to include L-S correction terms
    ### approx        PN approximant (SpinTaylorT1/T2/T4)
    V, Phi, S1x, S1y, S1z, S2x, S2y, S2z, LNhatx, LNhaty, LNhatz, \
        E1x, E1y, E1z = lalsim.SimInspiralSpinTaylorPNEvolveOrbit(deltaT, \
        m1_SI, m2_SI, fStart, fEnd, s1x, s1y, s1z, s2x, s2y, s2z, \
        lnhatx, lnhaty, lnhatz, e1x, e1y, e1z, lambda1, lambda2, \
        quadparam1, quadparam2, spinO, tideO, phaseO, lscorr, approxTag)

    V = np.array(V.data.data)
    Phi = np.array(Phi.data.data)
    ChiA = np.array([S1x.data.data, S1y.data.data, S1z.data.data]).T
    ChiB = np.array([S2x.data.data, S2y.data.data, S2z.data.data]).T
    LNhat = np.array([LNhatx.data.data, LNhaty.data.data, LNhatz.data.data]).T
    E1 = np.array([E1x.data.data, E1y.data.data, E1z.data.data]).T

    Omega = V**3
    return Omega, Phi, ChiA, ChiB, LNhat, E1
Пример #11
0
def spin_evolution(q,
                   chiA0,
                   chiB0,
                   omega0,
                   approximant='SpinTaylorT4',
                   dt=0.1,
                   spinO=7,
                   phaseO=7):
    """
    Wrapper for PN spin and dynamics evolution in LAL.
    Inputs:
        - q:              Mass ratio (q>=1)
        - chiA0:          Dimensionless spin of BhA at initial freq.
        - chiB0:          Dimensionless spin of BhB at initial freq.
        - omega0:         Initial orbital frequency in dimensionless units.
        - approximant:    'SpinTaylorT1/T4/T5'. Default: SpinTaylorT4.
        - dt:             Dimensionless step time for evolution. Default: 0.1
        - spinO:          Twice PN order of spin effects. Default: 7.
        - phaseO:         Twice PN order in phase. Default: 7.

    Outputs (all are time series):
        - Omega:          Dimensionless orbital frequency.
        - Phi:            Orbital phase (radians)
        - ChiA:           Dimensionless spin of BhA
        - ChiB:           Dimensionless spin of BhB
        - LNhat:          Orbital angular momentum direction
        - E1:             Orbital plane basis vector

    The frame is defined at the initial frequency omega0, as follows: \n
        - z-axis is set by the orbital angular momentum direction.
        - x-axis is the separation vector from the lighter BH to the heavier BH.
        - y-axis completes the triad by right-hand rule. \n
        All quantities are defined in this fixed frame, including initial spins,
        returned spins, other vectors like LNhat, etc.
    """

    approxTag = lalsim.SimInspiralGetApproximantFromString(approximant)

    # Total mass in solar masses
    M = 100  # This does not affect the returned values as they are
    # dimensionless

    # time step and initial GW freq in SI units
    MT = M * MTSUN_SI
    deltaT = dt * MT
    fStart = omega0 / np.pi / MT

    # component masses of the binary
    m1_SI = M * MSUN_SI * q / (1. + q)
    m2_SI = M * MSUN_SI / (1. + q)

    # spins at fStart
    s1x, s1y, s1z = chiA0
    s2x, s2y, s2z = chiB0

    # integrate as far forward as possible
    fEnd = 0

    # initial value of orbital angular momentum unit vector, i.e at fStart
    lnhatx, lnhaty, lnhatz = 0, 0, 1

    # initial value of orbital plane basis vector, i.e at fStart
    e1x, e1y, e1z = 1, 0, 0

    # tidal deformability parameters
    lambda1, lambda2 = 0, 0

    # spin-induced quadrupole moments
    quadparam1, quadparam2 = 1, 1

    # twice PN order of tidal effects
    tideO = 0

    # include some known L-S terms
    lscorr = 1

    # evolve spins and collect data into a nice format. The input values start
    # with lower-case letters, while output values start with upper-case
    # letters.
    V, Phi, S1x, S1y, S1z, S2x, S2y, S2z, LNhatx, LNhaty, LNhatz, \
        E1x, E1y, E1z = lalsim.SimInspiralSpinTaylorPNEvolveOrbit(deltaT, \
        m1_SI, m2_SI, fStart, fEnd, s1x, s1y, s1z, s2x, s2y, s2z, \
        lnhatx, lnhaty, lnhatz, e1x, e1y, e1z, lambda1, lambda2, \
        quadparam1, quadparam2, spinO, tideO, phaseO, lscorr, approxTag)
    V = np.array(V.data.data)
    Phi = np.array(Phi.data.data)
    ChiA = np.array([S1x.data.data, S1y.data.data, S1z.data.data]).T
    ChiB = np.array([S2x.data.data, S2y.data.data, S2z.data.data]).T
    LNhat = np.array([LNhatx.data.data, LNhaty.data.data, LNhatz.data.data]).T
    E1 = np.array([E1x.data.data, E1y.data.data, E1z.data.data]).T

    # orbital frequency
    Omega = V**3
    return Omega, Phi, ChiA, ChiB, LNhat
Пример #12
0
def gen_waveform(freq, z=0, omega=OMEGA, **params):
    """Generate frequency-domain inspiral waveform

    `freq` should be an array of frequency points at which the
    waveform should be interpolated.  Returns a tuple of
    (h_tilde^plus, h_tilde^cross) real-valued (amplitude only) arrays.

    The waveform is generated with
    lalsimulation.SimInspiralChooseFDWaveform().  Keyword arguments
    are used to update the default waveform parameters (1.4/1.4
    Msolar, optimally-oriented, 100 Mpc, (see DEFAULT_PARAMS macro)).
    The mass parameters ('m1' and 'm2') should be specified in solar
    masses and the 'distance' parameter should be specified in
    parsecs**.  Waveform approximants may be given as string names
    (see `lalsimulation` documentation for more info).  If the
    approximant is not specified explicitly, DEFAULT_APPROXIMANT_BNS
    waveform will be used if either mass is less than 5 Msolar and
    DEFAULT_APPROXIMANT_BBH waveform will be used otherwise.

    If a redshift `z` is specified (with optional `omega`), it's
    equivalent distance will be used (ignoring any `distance`
    parameter provided) and the masses will be redshift-corrected
    appropriately.  Otherwise no mass redshift correction will be
    applied.

    For example, to generate a 20/20 Msolar BBH waveform:

    >>> hp,hc = waveform.gen_waveform(freq, 'm1'=20, 'm2'=20)

    **NOTE: The requirement that masses are specified in solar masses
    and distances are specified in parsecs is different than that of
    the underlying lalsimulation method which expects mass and
    distance parameters to be in SI units.

    """
    iparams = _get_waveform_params(**params)

    # if redshift specified use that as distance and correct
    # appropriately, ignoring any distance specified in params.
    if z != 0:
        iparams['distance'] = lal.LuminosityDistance(omega, z) * 1e6
        iparams['m1'] *= 1.0 + z
        iparams['m2'] *= 1.0 + z

    # convert to SI units
    iparams['distance'] *= lal.PC_SI
    iparams['m1'] *= lal.MSUN_SI
    iparams['m2'] *= lal.MSUN_SI
    iparams['approximant'] = lalsimulation.SimInspiralGetApproximantFromString(
        iparams['approximant'])

    iparams['deltaF'] = freq[1] - freq[0]
    iparams['f_min'] = freq[0]
    # FIXME: the max frequency in the generated waveform is not always
    # greater than f_max, so as a workaround we generate over the full
    # band.  Probably room for speedup here
    # iparams['f_max'] = freq[-1]
    iparams['f_max'] = 10000
    # print(iparams)

    # logging.debug('waveform params = {}'.format(iparams))

    # generate waveform
    h = lalsimulation.SimInspiralChooseFDWaveform(**iparams)
    # print(h)

    freq_h = h[0].f0 + np.arange(len(h[0].data.data)) * h[0].deltaF

    def interph(h):
        "interpolate amplitude of h array"
        # FIXME: this only interpolates/returns the amplitude, and not
        # the full complex data (throws out phase), because this was
        # not working:
        # hir = scipy.interpolate.interp1d(freq_h, np.real(h.data.data))(freq)
        # hii = scipy.interpolate.interp1d(freq_h, np.imag(h.data.data))(freq)
        # return hir + 1j * hii
        return scipy.interpolate.interp1d(freq_h,
                                          np.absolute(h.data.data))(freq)

    hi = map(interph, h)

    return hi
Пример #13
0
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
Пример #14
0
def getApprox(type,
              name,
              m1=10.0,
              m2=10.0,
              f_ref=0.0,
              f_low=50.0,
              distance=1,
              delta_t=1.0 / 4096.0,
              s1x=0,
              s1y=0,
              s1z=0,
              s2x=0,
              s2y=0,
              s2z=0,
              inclination=0,
              tidal1=0,
              tidal2=0):
    if type == 'pycbc':
        hp, hc = get_td_waveform(approximant=name,
                                 mass1=m1,
                                 mass2=m2,
                                 f_lower=f_low,
                                 f_ref=f_ref,
                                 distance=distance,
                                 delta_t=delta_t,
                                 spin1x=s1x,
                                 spin1y=s1y,
                                 spin1z=s1z,
                                 spin2x=s2x,
                                 spin2y=s2y,
                                 spin2z=s2z,
                                 lambda1=tidal1,
                                 lambda2=tidal2,
                                 inclination=inclination)

        new_hp = np.array(hp)
        new_hc = np.array(hc)
        h = new_hp + new_hc * 1j
        times = np.array(hp.sample_times)
        shift_times = times - times[0]
        return (shift_times, h)
    elif type == 'laltd':
        mpc = 1.0e6 * lal.PC_SI
        m1 = m1 * lal.MSUN_SI
        m2 = m2 * lal.MSUN_SI
        distance = distance * mpc
        tidal_params = lal.CreateDict()
        lalsim.SimInspiralWaveformParamsInsertTidalLambda1(
            tidal_params, tidal1)
        lalsim.SimInspiralWaveformParamsInsertTidalLambda2(
            tidal_params, tidal2)
        hp, hc = lalsim.SimInspiralTD(
            m1, m2, s1x, s1y, s1z, s2x, s2y, s2z, distance, inclination,
            phiRef, 0., 0., 0., delta_t, f_low, f_ref, tidal_params,
            lalsim.SimInspiralGetApproximantFromString(name))
        times = np.arange(len(hp.data.data)) * delta_t + hp.epoch
        shift_times = times - times[0]
        h = np.array(hp.data.data + 1j * hc.data.data)
        return (shift_times, h)
    else:
        print 'Specify pycbc or laltd for approx type'
Пример #15
0
#maggiore gravitational waves vol 1 per cose un po' teoriche...
#leggi nested sampling meglio
#leggi articoli https://arxiv.org/abs/0907.0700 + https://arxiv.org/abs/1801.08009
#studia meglio metodi probabilistici a rete...

M = [5, 100]  #m1>m2
spin = [-.9, .9]

m1 = 10
m2 = 1
spin1z = 0.2
spin2z = 0.4
d = 1
LALpars = lal.CreateDict()
approx = lalsim.SimInspiralGetApproximantFromString('IMRPhenomD')

print(approx)

hptilde, hctilde = lalsim.SimInspiralChooseFDWaveform(
    m1 * lalsim.lal.MSUN_SI,
    m2 * lalsim.lal.MSUN_SI,
    0,
    0,
    spin1z,
    0,
    0,
    spin2z,
    d * 1e6 * lalsim.lal.PC_SI,
    0,
    0,
Пример #16
0
spin1x = 0.0
spin1y = 0.0
spin1z = 0.0
spin2x = 0.0
spin2y = 0.0
spin2z = 0.0
d = 500
phi0 = 2.0
inclination = 0.0

sampling_rate = 2048
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