예제 #1
0
def get_SEOBNRv4PHM_modes(q, M, chi1, chi2, f_start, distance, deltaT):
    """Generate SEOBNRv4PHM modes"""

    m1SI = lal.MSUN_SI * q * M / (1.0 + q)
    m2SI = lal.MSUN_SI * M / (1.0 + q)
    approx = ls.SEOBNRv4PHM
    hlm = ls.SimInspiralChooseTDModes(
        0.,
        deltaT,
        m1SI,
        m2SI,
        chi1[0],
        chi1[1],
        chi1[2],
        chi2[0],
        chi2[1],
        chi2[2],
        f_start,
        f_start,
        distance,
        None,
        5,
        approx,
    )
    hI = {}
    modes = [(2, 2), (2, 1), (3, 3), (4, 4), (5, 5)]
    for lm in modes:
        hI[lm] = ls.SphHarmTimeSeriesGetMode(hlm, lm[0], lm[1]).data.data

    return hI
예제 #2
0
파일: tools.py 프로젝트: Yoshinta/pyrex
def lal_waves(q, total_mass, approximant, f_lower, distance, inclination,
              coa_phase, **kwargs):
    """
        Compute time-domain waveform from LAL simulation with a given set of paramater.
    """
    m1, m2 = masses_from_q(q, total_mass)
    spin1x = spin1y = spin1z = spin2x = spin2y = spin2z = 0.
    long_asc_nodes = 0.
    eccentricity = 0.
    mean_per_ano = 0.
    f_ref = f_lower
    f_max = 4096.
    lal_pars = None
    l = 2
    m = 2
    aprox = eval('ls.' + str(approximant))
    if 'delta_t' and 'delta_f' in kwargs:
        error("Please provide delta_t or delta_f.")
    elif 'delta_t' in kwargs and 'delta_f' not in kwargs:
        generateTD = ls.SimInspiralTDModesFromPolarizations(
            m1 * lal.MSUN_SI, m2 * lal.MSUN_SI, spin1x, spin1y, spin1z, spin2x,
            spin2y, spin2z, distance * 1e6 * lal.PC_SI, coa_phase,
            long_asc_nodes, eccentricity, mean_per_ano, kwargs['delta_t'],
            f_lower, f_ref, lal_pars, aprox)
        h22lal = ls.SphHarmTimeSeriesGetMode(generateTD, l, m)

        h22 = h22lal.data.data / NR_amp_scale(m1 + m2, distance)
        h2_2 = ((-1)**l) * conj(h22)

        Ttot = h22lal.data.length * h22lal.deltaT
        t1 = arange(h22lal.data.length, dtype=float) * h22lal.deltaT
        t1 = t1 + h22lal.epoch
        x = t1 - t1[argmax(abs(h22))]

    elif 'delta_f' in kwargs and 'delta_t' not in kwargs:
        hp1, hc1 = ls.SimInspiralChooseFDWaveform(
            lal.MSUN_SI * m1, lal.MSUN_SI * m2, spin1x, spin1y, spin1z, spin2x,
            spin2y, spin2z, lal.PC_SI * distance * 1e6, inclination, coa_phase,
            long_asc_nodes, eccentricity, mean_per_ano, kwargs['delta_f'],
            f_lower, f_max, f_ref, lal_pars, aprox)
        hp = hp1.data.data
        hc = hc1.data.data
        #TODO: change with FD get modes
        h22 = 0
        h2_2 = 0.
        Ftot = hp1.data.length * hp1.deltaF
        t1 = arange(hp1.data.length, dtype=float) * hp1.deltaF
        t1 = t1 + hp1.epoch
        x = t1
    else:
        error("Please provide delta_t or delta_f.")
    return x, h22, h2_2
예제 #3
0
def get_SEOBNRv4HM_modes(q, M, chi1, chi2, f_start, deltaT):
    """Generate SEOBNRv4HM modes"""
    m1SI = lal.MSUN_SI * q * M / (1.0 + q)
    m2SI = lal.MSUN_SI * M / (1.0 + q)
    nqcCoeffsInput = lal.CreateREAL8Vector(10)

    prefactor = 4.7864188273360336e-20  # G/c^2*(M_sun/Mpc)
    amp_prefactor = prefactor * M / 1.  # G/c^2 (M / d_L)
    nu = np.divide(q, np.square(1 + q))
    distance = 1. * 1e6 * lal.PC_SI

    sphtseries, dyn, dynHI = ls.SimIMRSpinAlignedEOBModes(
        deltaT,
        m1SI,
        m2SI,
        f_start,
        distance,
        chi1,
        chi2,
        41,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        1.0,
        1.0,
        nqcCoeffsInput,
        0,
    )

    # The minus sign in front of the modes takes into account the fact that the polarization basis in EOB
    # conventions is different wrt the one in LAL
    hI = {}
    modes = [(2, 2), (2, 1), (3, 3), (4, 4), (5, 5)]
    for lm in modes:
        hI[lm] = np.trim_zeros(
            -1 *
            ls.SphHarmTimeSeriesGetMode(sphtseries, lm[0], lm[1]).data.data,
            "b") / (amp_prefactor * nu)

    t = np.linspace(0, deltaT * len(hI[(2, 2)]), len(hI[(2, 2)]))
    t = t - t[np.argmax(np.abs(hI[(2, 2)]))]

    return t, hI
예제 #4
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
예제 #5
0
def get_SEOBNRv4HM_modes(q, M, chi1, chi2, f_start, distance, deltaT):
    """Generate SEOBNRv4HM modes"""
    m1SI = lal.MSUN_SI * q * M / (1.0 + q)
    m2SI = lal.MSUN_SI * M / (1.0 + q)
    nqcCoeffsInput = lal.CreateREAL8Vector(10)
    sphtseries, dyn, dynHI = ls.SimIMRSpinAlignedEOBModes(
        deltaT,
        m1SI,
        m2SI,
        f_start,
        distance,
        chi1,
        chi2,
        41,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        1.0,
        1.0,
        nqcCoeffsInput,
        0,
    )

    # The minus sign in front of the modes takes into account the fact that the polarization basis in EOB
    # conventions is different wrt the one in LAL
    hI = {}
    modes = [(2, 2), (2, 1), (3, 3), (4, 4), (5, 5)]
    for lm in modes:
        hI[lm] = np.trim_zeros(
            -1 *
            ls.SphHarmTimeSeriesGetMode(sphtseries, lm[0], lm[1]).data.data,
            "b")

    return hI
예제 #6
0
def get_SEOBNRv4PHM_modes(q, M, chi1, chi2, f_start, deltaT):
    """Generate SEOBNRv4PHM modes"""
    m1SI = lal.MSUN_SI * q * M / (1.0 + q)
    m2SI = lal.MSUN_SI * M / (1.0 + q)
    approx = ls.SEOBNRv4PHM

    prefactor = 4.7864188273360336e-20  # G/c^2*(M_sun/Mpc)
    amp_prefactor = prefactor * M / 1.  # G/c^2 (M / d_L)
    nu = np.divide(q, np.square(1 + q))
    distance = 1. * 1e6 * lal.PC_SI

    hlm = ls.SimInspiralChooseTDModes(0., deltaT, m1SI, m2SI, chi1[0], chi1[1],
                                      chi1[2], chi2[0], chi2[1], chi2[2],
                                      f_start, f_start, distance, None, 5,
                                      approx)
    hI = {}
    modes = [(2, 2), (2, 1), (3, 3), (4, 4), (5, 5)]
    for lm in modes:
        hI[lm] = ls.SphHarmTimeSeriesGetMode(
            hlm, lm[0], lm[1]).data.data / (amp_prefactor * nu)

    t = np.linspace(0, deltaT * len(hI[(2, 2)]), len(hI[(2, 2)]))
    t = t - t[np.argmax(np.abs(hI[(2, 2)]))]
    return t, hI
예제 #7
0
    theta[0, 3],
    theta[0, 4],
    theta[0, 5],
    0.,
    theta[0, 7],
    f_min,
    f_min,
    1e6 * lalsim.lal.PC_SI,
    lal.CreateDict(),
    5,  #lmax
    lalsim.IMRPhenomTPHM)
prefactor = 4.7864188273360336e-20
m1, m2 = theta[0, 0], theta[0, 1]
nu = np.divide(m1 / m2, np.square(1 + m1 / m2))
amp_prefactor = prefactor * (m1 + m2) / 1. * nu
h_22_P_lal = lalsim.SphHarmTimeSeriesGetMode(hlm, 2,
                                             2).data.data / amp_prefactor
h_21_P_lal = lalsim.SphHarmTimeSeriesGetMode(hlm, 2,
                                             1).data.data / amp_prefactor
t_grid_lal = np.linspace(0, len(h_22_P_lal) * t_step, len(h_22_P_lal))
t_grid_lal = t_grid_lal - t_grid_lal[np.argmax(h_22_P_lal)]

print("Mismatch NP WFs: 22, 21",
      compute_optimal_mismatch(h_NP_mlgw[0, :, 0], h_22_NP)[0][0],
      compute_optimal_mismatch(h_NP_mlgw[0, :, 1], h_21_NP)[0][0])
print("Mismatch P WFs: 22, 21",
      compute_optimal_mismatch(h_P_mlgw[0, :, 0], h_22)[0][0],
      compute_optimal_mismatch(h_P_mlgw[0, :, 1], h_21)[0][0])

#plotting
#ignoring annoying real/imag warnings in plots
import warnings
예제 #8
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' (has effect only if approximant is "TEOBResumS")
	"""
    #TODO: create a function get modes, wrapper to ChooseTDModes: you can call it from here to get the modes
    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
        if not isinstance(path_TEOBResumS, str):
            raise ValueError("Missing path to TEOBResumS: unable to continue")
        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 lal and 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"
                    )
        elif approximant != "IMRPhenomTPHM":
            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:old":  #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
        elif approximant == "IMRPhenomTPHM" or approximant == "SEOBNRv4HM":
            #https://lscsoft.docs.ligo.org/lalsuite/lalsimulation/test___s_e_o_b_n_rv4_p_h_m__vs__4_h_m__ringdown_8py_source.html
            #approx = lalsim.SEOBNRv4PHM #DEBUG
            hlm = lalsim.SimInspiralChooseTDModes(
                0.,
                t_step,
                m1 * lalsim.lal.MSUN_SI,
                m2 * lalsim.lal.MSUN_SI,
                0.,
                0.,
                spin1z,
                0.,
                0.,
                spin2z,
                f_min,
                f_min,
                1e6 * lalsim.lal.PC_SI,
                LALpars,
                5,  #lmax
                lalsim.IMRPhenomTPHM)
            amp_prefactor = prefactor * (m1 + m2) / 1.
            for i, lm in enumerate(modes):
                temp_hlm = lalsim.SphHarmTimeSeriesGetMode(hlm, lm[0],
                                                           lm[1]).data.data
                temp_amp = np.abs(
                    temp_hlm
                ) / amp_prefactor / nu  #check that this conventions are for every lal part
                temp_ph = np.unwrap(np.angle(temp_hlm))
                amp_list[i] = temp_amp
                ph_list[i] = temp_ph
                if (lm[0], lm[1]) == (2, 2):  #get grid
                    argpeak = locate_peak(
                        temp_amp)  #aligned at the peak of the 22
            time_full = np.linspace(
                0.0,
                len(temp_amp) * t_step,
                len(temp_amp))  #time grid at which wave is computed

        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]
            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

            if False:
                #TODO: remove this shit!!
                plt.figure()
                plt.plot(time_grid_list[i], temp_amp_, 'o', ms=2)
                plt.plot(time_full, temp_amp)
                plt.xlim([-0.00015, 0.00015])
                plt.show()

            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 % 50 == 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