B
    d                 @   s  d Z ddlZddlZddlmZmZmZ ddlmZm	Z	 e	
dZdd Zdd	d
Zdd Zdd Zdd Zdd Zdd ZdddZdd Zdd Zdd Zdd  Zd!d" Zd#d$ Zd%d& Zd'd( Zd)d* Zd+d, Zd-d. Zd/d0 Zd1d2 Z d3d4 Z!d5d6 Z"d7d8 Z#d9d: Z$d;d< Z%d=d> Z&d?d@ Z'e(e'Z)dAdB Z*dCdD Z+e(e+Z,dEdF Z-dGdH dIdH dJdH dKdH dLdH dMdH dNdH dOdH dPdH dQdH dRdH dSdH dTdH dUdH dVdH dWdH dXdH dYdH dZdH d[Z.d\d] Z/dd_d`Z0e(e0Z1ddddeZ2dfdg Z3dhdi Z4djdk Z5e(e5Z6dldm Z7dndo Z8ddqdrZ9ddsdtZ:ddudvZ;dwdx Z<dydz Z=e4Z>e6Z?d{d| Z@d}d~ ZAdd ZBdddZCdddZDdddZEdddZFdS )ziThis module contains convenience pN functions. This includes calculating conversions
between quantities.
    N)bisectbrentqminimize)conversionslibutilslalsimulationc             C   s   t dtt|  S )z= Return the nearest binary number larger than input_len.
       )intnumpyceillog2)Z	input_len r   Z/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/pycbc/pnutils.pynearest_larger_binary_number$   s    r   ffffff?c             C   s   t j| ||dS )N)ref_mass)r   chirp_distance)distmchirpr   r   r   r   r   )   s    r   c             C   s    t | |}t | |}||fS )N)r   Zmtotal_from_mass1_mass2eta_from_mass1_mass2)mass1mass2m_totaletar   r   r   mass1_mass2_to_mtotal_eta,   s    r   c             C   s    t | |}t | |}||fS )N)r   mass1_from_mtotal_etamass2_from_mtotal_eta)r   r   r   r   r   r   r   mtotal_eta_to_mass1_mass21   s    r   c             C   s    t | |}t | |}||fS )N)r   Zmchirp_from_mass1_mass2r   )r   r   m_chirpr   r   r   r   mass1_mass2_to_mchirp_eta6   s    r   c             C   s,   t | |}t ||}t ||}||fS )N)r   Zmtotal_from_mchirp_etar   r   )r   r   mtotalr   r   r   r   r   mchirp_eta_to_mass1_mass2;   s    r!   c             C   s   t | |S )ai  
    This function takes a value of mchirp and one component mass and returns
    the second component mass. As this is a cubic equation this requires
    finding the roots and returning the one that is real.
    Basically it can be shown that:

    m2^3 - a(m2 + m1) = 0

    where

    a = Mc^5 / m1^3

    this has 3 solutions but only one will be real.
    )r   Zmass2_from_mchirp_mass1)r   r   r   r   r   mchirp_mass1_to_mass2A   s    r"   FTc             C   s   t j|| ||dS )a  
    This function takes values for eta and one component mass and returns the
    second component mass. Similar to mchirp_mass1_to_mass2 this requires
    finding the roots of a quadratic equation. Basically:

    eta m2^2 + (2 eta - 1)m1 m2 + \eta m1^2 = 0

    This has two solutions which correspond to mass1 being the heavier mass
    or it being the lighter mass. By default the value corresponding to
    mass1 > mass2 is returned. Use the return_mass_heavier kwarg to invert this
    behaviour.
    )Zknown_is_secondary
force_real)r   Zmass_from_knownmass_eta)r   r   Zreturn_mass_heavierr#   r   r   r   eta_mass1_to_mass2R   s    r$   c             C   s*   t |}t | |}t | |}||fS )a   This function takes a value of mchirp and the mass ratio
    mass1/mass2 and returns the two component masses.

    The map from q to eta is

        eta = (mass1*mass2)/(mass1+mass2)**2 = (q)/(1+q)**2

    Then we can map from (mchirp,eta) to (mass1,mass2).
    )r   Z
eta_from_qZmass1_from_mchirp_etaZmass2_from_mchirp_eta)r   qr   r   r   r   r   r   mchirp_q_to_mass1_mass2b   s    

r&   c             C   s
   t | S )zused in calculating chirp times: see Cokelaer, arxiv.org:0706.4437
       appendix 1, also lalinspiral/python/sbank/tau0tau3.py
    )r   Z_a0)f_lowerr   r   r   A0q   s    r(   c             C   s
   t | S )z&another parameter used for chirp times)r   Z_a3)r'   r   r   r   A3w   s    r)   c             C   s$   t | ||}t | ||}||fS )N)r   Ztau0_from_mass1_mass2Ztau3_from_mass1_mass2)r   r   r'   tau0tau3r   r   r   mass1_mass2_to_tau0_tau3{   s    r,   c             C   s$   t | ||}t | ||}||fS )N)r   Zmtotal_from_tau0_tau3Zeta_from_tau0_tau3)r*   r+   r'   r    r   r   r   r   tau0_tau3_to_mtotal_eta   s    r-   c             C   s   t | ||\}}t||S )N)r-   r   )r*   r+   r'   r   r   r   r   r   tau0_tau3_to_mass1_mass2   s    r.   c             C   sN   t | |\}}t|| k||}t|| k||}t|||\}}	}
||	|
fS )N)r   r
   where!get_beta_sigma_from_aligned_spins)r   r   spin1zspin2z_r   Z
heavy_spinZ
light_spinbetasigmagammar   r   r   -mass1_mass2_spin1z_spin2z_to_beta_sigma_gamma   s    r7   c       
      C   s   d||  }d||  }dd|   d }|| }dd|   | }|d| | 7 }| d d|  }|dd|   d	|| ||    7 }||d
||   7 }dd|   d|  |   | }	|	dd|   | | 7 }	|||	fS )a  
    Calculate the various PN spin combinations from the masses and spins.
    See <http://arxiv.org/pdf/0810.5336v3.pdf>.

    Parameters
    -----------
    eta : float or numpy.array
        Symmetric mass ratio of the input system(s)
    spin1z : float or numpy.array
        Spin(s) parallel to the orbit of the heaviest body(ies)
    spin2z : float or numpy.array
        Spin(s) parallel to the orbit of the smallest body(ies)

    Returns
    --------
    beta : float or numpy.array
        The 1.5PN spin combination
    sigma : float or numpy.array
        The 2PN spin combination
    gamma : float or numpy.array
        The 2.5PN spin combination
    chis : float or numpy.array
        (spin1z + spin2z) / 2.
    g      ?      gUUUUU"@gUUUUUU@g      H@i  r   g     @@g     @$@gjS2t@gHr@g98B@gqq/@r   )
r   r1   r2   ZchiSZchiAdeltaZspinspinr4   r5   r6   r   r   r   r0      s    $
r0   c             C   s
   | t j S )N)lalMSUN_SI)Zsolar_massesr   r   r   solar_mass_to_kg   s    r=   c             C   s
   | t j S )N)r;   ZPC_SI)distancer   r   r   parsecs_to_meters   s    r?   c             C   s   t | d S )Ng    .A)r?   )r>   r   r   r   megaparsecs_to_meters   s    r@   c             C   s   t | |S )N)r   velocity_to_frequency)vMr   r   r   rA      s    rA   c             C   s   t | |S )N)r   frequency_to_velocity)frC   r   r   r   rD      s    rD   c             C   s
   t | S )a  
    Innermost stable circular orbit (ISCO) for a test particle
    orbiting a Schwarzschild black hole

    Parameters
    ----------
    M : float or numpy.array
        Total mass in solar mass units

    Returns
    -------
    f : float or numpy.array
        Frequency in Hz
    )r   Zf_schwarzchild_isco)rC   r   r   r   f_SchwarzISCO   s    rF   c             C   sH   t | | ||  }t| | dd|  d| |  d| | |   S )a  
    Mass ratio dependent ISCO derived from estimates of the final spin
    of a merged black hole in a paper by Buonanno, Kidder, Lehner
    (arXiv:0709.3839).  See also arxiv:0801.4297v2 eq.(5)

    Parameters
    ----------
    m1 : float or numpy.array
        First component mass in solar mass units
    m2 : float or numpy.array
        Second component mass in solar mass units

    Returns
    -------
    f : float or numpy.array
        Frequency in Hz
    r8   gffffff@g@g?)r
   minimumrF   )m1m2r%   r   r   r   	f_BKLISCO   s    rJ   c             C   s   ddt j |  t j  S )a<  
    Gravitational wave frequency corresponding to the light-ring orbit,
    equal to 1/(3**(3/2) pi M) : see InspiralBankGeneration.c

    Parameters
    ----------
    M : float or numpy.array
        Total mass in solar mass units

    Returns
    -------
    f : float or numpy.array
        Frequency in Hz
    g      ?g9B.@)r;   PIMTSUN_SI)rC   r   r   r   f_LightRing   s    rM   c             C   s   ddt j d |  t j  S )a  
    Effective RingDown frequency studied in Pan et al. (arXiv:0704.1964)
    found to give good fit between stationary-phase templates and
    numerical relativity waveforms [NB equal-mass & nonspinning!]
    Equal to 1.07*omega_220/2*pi

    Parameters
    ----------
    M : float or numpy.array
        Total mass in solar mass units

    Returns
    -------
    f : float or numpy.array
        Frequency in Hz
    g-y<?r   g(\?)r;   rK   rL   )rC   r   r   r   f_ERD  s    rN   c             C   sb   t | |\}}dddd|  d|d   d   dd|  d|d    }|d	tj | tj  S )
a+  
    Fundamental RingDown frequency calculated from the Berti, Cardoso and
    Will (gr-qc/0512160) value for the omega_220 QNM frequency using
    mass-ratio dependent fits to the final BH mass and spin from Buonanno
    et al. (arXiv:0706.3732) : see also InspiralBankGeneration.c

    Parameters
    ----------
    m1 : float or numpy.array
        First component mass in solar mass units
    m2 : float or numpy.array
        Second component mass in solar mass units

    Returns
    -------
    f : float or numpy.array
        Frequency in Hz
    g      ?g)\(?g+Pz@g333333@r   g333333?gAF@#H?gZd;?g       @)r   r;   rK   rL   )rH   rI   r   r   tmpr   r   r   f_FRD  s    "rP   c             C   s   dt | | S )a  
    Lorentzian RingDown frequency = 1.2*FRD which captures part of
    the Lorentzian tail from the decay of the QNMs

    Parameters
    ----------
    m1 : float or numpy.array
        First component mass in solar mass units
    m2 : float or numpy.array
        Second component mass in solar mass units

    Returns
    -------
    f : float or numpy.array
        Frequency in Hz
    g333333?)rP   )rH   rI   r   r   r   f_LRD-  s    rQ   c             C   sB   t |tj }t |tj }t||ddt |ddt |t| 	S )a  
    Wrapper of the LALSimulation function returning the frequency
    for a given frequency function and template parameters.

    Parameters
    ----------
    freqfunc : lalsimulation FrequencyFunction wrapped object e.g.
        lalsimulation.fEOBNRv2RD
    m1 : float-ish, i.e. castable to float
        First component mass in solar masses
    m2 : float-ish
        Second component mass in solar masses
    s1z : float-ish
        First component dimensionless spin S_1/m_1^2 projected onto L
    s2z : float-ish
        Second component dimensionless spin S_2/m_2^2 projected onto L

    Returns
    -------
    f : float
        Frequency in Hz
    r   )floatr;   r<   r   ZSimInspiralGetFrequencyr	   )freqfuncrH   rI   s1zs2zm1kgm2kgr   r   r   	_get_freq@  s    rX   c             C   s   t t| }t|||||S )a  
    Returns the LALSimulation function which evaluates the frequency
    for the given frequency function and template parameters.

    Parameters
    ----------
    freqfunc : string
        Name of the frequency function to use, e.g., 'fEOBNRv2RD'
    m1 : float or numpy.array
        First component mass in solar masses
    m2 : float or numpy.array
        Second component mass in solar masses
    s1z : float or numpy.array
        First component dimensionless spin S_1/m_1^2 projected onto L
    s2z : float or numpy.array
        Second component dimensionless spin S_2/m_2^2 projected onto L

    Returns
    -------
    f : float or numpy.array
        Frequency in Hz
    )getattrr   _vec_get_freq)rS   rH   rI   rT   rU   Zlalsim_ffuncr   r   r   get_freq`  s    
r[   c             C   sB   t |tj }t |tj }t||ddt |ddt |t| 	S )a  
    Wrapper of the LALSimulation function returning the final (highest)
    frequency for a given approximant an template parameters

    Parameters
    ----------
    approx : lalsimulation approximant wrapped object e.g.
        lalsimulation.EOBNRv2
    m1 : float-ish, i.e. castable to float
        First component mass in solar masses
    m2 : float-ish
        Second component mass in solar masses
    s1z : float-ish
        First component dimensionless spin S_1/m_1^2 projected onto L
    s2z : float-ish
        Second component dimensionless spin S_2/m_2^2 projected onto L

    Returns
    -------
    f : float
        Frequency in Hz
    r   )rR   r;   r<   r   ZSimInspiralGetFinalFreqr	   )approxrH   rI   rT   rU   rV   rW   r   r   r   _get_final_freqz  s    r]   c             C   s   t | }t|||||S )a  
    Returns the LALSimulation function which evaluates the final
    (highest) frequency for a given approximant using given template
    parameters.
    NOTE: TaylorTx and TaylorFx are currently all given an ISCO cutoff !!

    Parameters
    ----------
    approx : string
        Name of the approximant e.g. 'EOBNRv2'
    m1 : float or numpy.array
        First component mass in solar masses
    m2 : float or numpy.array
        Second component mass in solar masses
    s1z : float or numpy.array
        First component dimensionless spin S_1/m_1^2 projected onto L
    s2z : float or numpy.array
        Second component dimensionless spin S_2/m_2^2 projected onto L

    Returns
    -------
    f : float or numpy.array
        Frequency in Hz
    )r   ZGetApproximantFromString_vec_get_final_freq)r\   rH   rI   rT   rU   Zlalsim_approxr   r   r   get_final_freq  s    
r_   c             C   s   t | d | d  S )Nr   r   )rF   )pr   r   r   <lambda>      ra   c             C   s   t | d | d  S )Nr   r   )rM   )r`   r   r   r   ra     rb   c             C   s   t | d | d  S )Nr   r   )rN   )r`   r   r   r   ra     rb   c             C   s   t | d | d S )Nr   r   )rJ   )r`   r   r   r   ra     rb   c             C   s   t | d | d S )Nr   r   )rP   )r`   r   r   r   ra     rb   c             C   s   t | d | d S )Nr   r   )rQ   )r`   r   r   r   ra     rb   c             C   s   t | d | d | d | d S )Nr   r   r1   r2   )meco_frequency)r`   r   r   r   ra     s   c             C   s$   t | d | d | d | d d d dS )Nr   r   r1   r2   )qm1qm2)hybrid_meco_frequency)r`   r   r   r   ra     s   c             C   s    t d| d | d | d | d S )NZfIMRPhenomBFinalr   r   r1   r2   )r[   )r`   r   r   r   ra     s   c             C   s    t d| d | d | d | d S )NZfIMRPhenomCFinalr   r   r1   r2   )r[   )r`   r   r   r   ra     s   c             C   s    t d| d | d | d | d S )NZfIMRPhenomDPeakr   r   r1   r2   )r[   )r`   r   r   r   ra     s   c             C   s    t d| d | d | d | d S )NZ
fEOBNRv2RDr   r   r1   r2   )r[   )r`   r   r   r   ra     s   c             C   s    t d| d | d | d | d S )NZfEOBNRv2HMRDr   r   r1   r2   )r[   )r`   r   r   r   ra     s   c             C   s    t d| d | d | d | d S )NZfSEOBNRv1RDr   r   r1   r2   )r[   )r`   r   r   r   ra     s   c             C   s    t d| d | d | d | d S )NZfSEOBNRv1Peakr   r   r1   r2   )r[   )r`   r   r   r   ra     s   c             C   s    t d| d | d | d | d S )NZfSEOBNRv2RDr   r   r1   r2   )r[   )r`   r   r   r   ra     s   c             C   s    t d| d | d | d | d S )NZfSEOBNRv2Peakr   r   r1   r2   )r[   )r`   r   r   r   ra     s   c             C   s    t d| d | d | d | d S )NZfSEOBNRv4RDr   r   r1   r2   )r[   )r`   r   r   r   ra     s   c             C   s    t d| d | d | d | d S )NZfSEOBNRv4Peakr   r   r1   r2   )r[   )r`   r   r   r   ra     s   )ZSchwarzISCOZ	LightRingZERDZBKLISCOZFRDZLRDZMECOZ
HybridMECOZIMRPhenomBFinalZIMRPhenomCFinalZIMRPhenomDPeakZ	EOBNRv2RDZEOBNRv2HMRDZ
SEOBNRv1RDZSEOBNRv1PeakZ
SEOBNRv2RDZSEOBNRv2PeakZ
SEOBNRv4RDZSEOBNRv4Peakc             C   s   ||||d}t |  |S )a  
    Returns the result of evaluating the frequency cutoff function
    specified by 'name' on a template with given parameters.

    Parameters
    ----------
    name : string
        Name of the cutoff function
    m1 : float or numpy.array
        First component mass in solar masses
    m2 : float or numpy.array
        Second component mass in solar masses
    s1z : float or numpy.array
        First component dimensionless spin S_1/m_1^2 projected onto L
    s2z : float or numpy.array
        Second component dimensionless spin S_2/m_2^2 projected onto L

    Returns
    -------
    f : float or numpy.array
        Frequency in Hz
    )r   r   r1   r2   )named_frequency_cutoffs)namerH   rI   rT   rU   paramsr   r   r   frequency_cutoff_from_name  s    rj   SEOBNRv4c             C   s  t | t |t |t |t |f\} }}}}|dkrbt| |||}t| tj |tj ||}n|dkrt| tj |tj |||}nt|dkrt|| tj |tj ||}nL|dks|dkrt| |||}t	|| tj |tj |d}nt
d| |d S )	z>Wrapper of lalsimulation template duration approximate formulaSEOBNRv2Z
IMRPhenomDrk   SPAtmpltTaylorF2z#I can't calculate a duration for %sg?)rR   r   ZSimIMRPhenomBComputeChiZ!SimIMRSEOBNRv2ChirpTimeSingleSpinr;   r<   ZSimIMRPhenomDChirpTime SimIMRSEOBNRv4ROMTimeOfFrequencyZ(SimInspiralTaylorF2ReducedSpinComputeChiZ'SimInspiralTaylorF2ReducedSpinChirpTimeRuntimeError)rH   rI   rT   rU   f_lowapproximantchiZtime_lengthr   r   r   _get_imr_duration  s&    ru   d      rn   c	          	      s  G dd d}	|	 }
|
_ |
_|
_|
_yt|ddit|
d}W n ttfk
r^   Y nX |dkrddlm	  t
 }tt|t||}t fd	d
|D }n|dkrtd}tt|t||}tfdd
|D }nh|dkrftd}tt|td| |}tfdd
|D }ntd| d | | |fS )zCompute the time-frequency evolution of an inspiral signal.

    Return a tuple of time and frequency vectors tracking the evolution of an
    inspiral signal in the time-frequency plane.
    c               @   s   e Zd ZdS )zget_inspiral_tf.<locals>.ParamsN)__name__
__module____qualname__r   r   r   r   Params!  s   r{   __builtins__N)ri   )rn   rm   r   )findchirp_chirptimec                s&   g | ]} t t t |qS r   )rR   ).0rE   )r}   r   r   	pn_2orderr   r   
<listcomp>5  s   z#get_inspiral_tf.<locals>.<listcomp>)rl   ZSEOBNRv2_ROM_DoubleSpinZSEOBNRv2_ROM_DoubleSpin_HIrl   c          
      s.   g | ]&}t |t tttqS r   )r   Z,SimIMRSEOBNRv2ROMDoubleSpinHITimeOfFrequencyr=   rR   )r~   rE   )r   r   spin1spin2r   r   r   >  s   )rk   ZSEOBNRv4_ROMrk   g+?c          
      s.   g | ]&}t |t tttqS r   )r   rp   r=   rR   )r~   rE   )r   r   r   r   r   r   r   G  s   zApproximant z not supported)r   r   r1   r2   evaldict	NameError	TypeErrorZpycbc.waveform.spa_tmpltr}   rF   r
   Zlogspacelog10arrayr_   
ValueError)Ztcr   r   r   r   rr   Zn_pointsr   rs   r{   ri   Zf_highZtrack_fZtrack_tr   )r}   r   r   r   r   r   r   get_inspiral_tf  sD    


r   c             C   s  | | }| | ||  }| | ||  | }|| d }d| d| |  d }d| | | d }	d|  |  | | d| |  d| | | | d| |   }
d	| }d
|d  }d}dd| d  t |dd  }d}ddt |d d  dt |d d  |ddt tjd d    }|d| d d| | d  7 }|d|	 d d|
 d  7 }|d| d d| d d| d  |  d | t |d d  7 }||||||fS )!zL Return the center-of-mass energy coefficients up to 3.0pN (2.5pN spin)
    g       @g     @\@g      S@g      (@g     S@g       @g     @T@g      0@g      g      g        g         r   g      8@g     %   g      X@#      g     @@gqqM@       4   i   `   ig     0u@i
  i  )powr;   rK   )rH   rI   chi1chi2mtotr   rt   chisymr4   sigma12sigmaqmZenergy0energy2energy3energy4energy5energy6r   r   r   _energy_coeffsR  s&    "D @r   c                s:   t | |||\}  fdd}t|ddS )a  
    Returns the velocity of the minimum energy cutoff for 3.5pN (2.5pN spin)

    Parameters
    ----------
    m1 : float
        First component mass in solar masses
    m2 : float
        Second component mass in solar masses
    chi1 : float
        First component dimensionless spin S_1/m_1^2 projected onto L
    chi2 : float
        Second component dimensionless spin S_2/m_2^2 projected onto L

    Returns
    -------
    v : float
        Velocity (dimensionless)
    c                sD   d| |  d  | d | d | d d |           S )Ng       @g      @g      @g      @g      @g       @r   )rB   )r   r   r   r   r   r   r   eprime  s    zmeco_velocity.<locals>.eprimeg?g      ?)r   r   )rH   rI   r   r   r3   r   r   )r   r   r   r   r   r   meco_velocityn  s    r   c             C   s   t t| |||| | S )zNReturns the frequency of the minimum energy cutoff for 3.5pN (2.5pN spin)
    )rA   r   )rH   rI   r   r   r   r   r   _meco_frequency  s    r   c             C   s  | | }| | ||  }| | ||  | }|| d }d| d| |  d }d| | | d }	d|  |  | | d| |  d| | | | d| |   }
d	}d
dd|   }dt j | }dd|  d| |  d |	 |
 }dt j dd|   d| d d| | d  d| | d  d| | | d   }dd|  d| |  d| | |  }d}t jd d d!|  d"| |   }||||||||fS )#z= Returns the dt/dv coefficients up to 3.5pN (2.5pN spin)
    g       @g     @\@g      S@g      (@g     S@g       @g     @T@g      0@g      ?gaah?g     8@g     @g      g   UGAg    ,TAg    PAg     /AgaaX?g     1g     @g    (Ag     @g      E@g    lxAg     @g     @l@gq=
ף6@gZd;Od@g{Nz@gG`@g[[@g   hmg    BhAg    4RA)r;   rK   )rH   rI   r   r   r   r   rt   r   r4   r   r   Zdtdv0dtdv2dtdv3dtdv4dtdv5dtdv6dtdv6logdtdv7r   r   r   _dtdv_coeffs  s"    "$V("r   c                sV   t | |||\}  fdd}|ddk rNt|ddS dS d S )Nc                sb   }| |  d t |   }| |  }| |  }| |  }| |   }| |  | d S )Ng      @g      ?)r
   log)rB   x)r   r   r   r   r   r   r   r   r   	dtdv_func  s    z(_dtdv_cutoff_velocity.<locals>.dtdv_funcg      ?g        g?)r   r   )rH   rI   r   r   r3   r   r   )r   r   r   r   r   r   r   r   _dtdv_cutoff_velocity  s
    	r   ro   c             C   sz  d}d}||krt dn|dkr&|}||kr8t dn|dkrD|}d}d}	| | }
| | |
 }| |
 }||
 }|| | }|| | }t| |\}}t|d }|dkrd|d< |dkrd|d< |dkrdd	|  |d< |d
krd|d
< |dkrdd|  ||  d |d< |dkr$d|d< |dkrfdddtj tj  |  d| |  d| |  |d< dd| |   }dd|  |  }d| }|d | | }| d d | | }|	 d d | | }dd| d	  || dd| d    }dd| d	  || dd| d    }dd| d  d | | d!  || d"d#|  d$| | d    }dd| d  d | | d!  || d"d#|  d$| | d    }|d
kr|d
  || ||  7  < |dkr2|d  ||| d| |   7  < |d  || | || |  || |  || |  7  < |dkrP|| ||  |d< |dkrv|d  || ||  7  < |S )%zZ Return the energy coefficients. This assumes that the system has aligned spins only.
    rw   z8pN coeffiecients of that order have not been implementedro   g      ?r8   r   r   gUUUUUUg      "@r   r9   g     @Tg     L@g      8@      g     %gqqM@gUUUUU@gUUUUU?g{?gUUUUUU@g       @g      @g      &@g     N@g      g      $@g     @@g     v@g      @g      =@g      (@g      g     C@g      @)r   r   r
   Zzerosr;   rK   )rH   rI   rT   rU   phase_order
spin_orderZimplemented_phase_orderZimplemented_spin_orderZqmdef1Zqmdef2rC   dmZm1MZm2Mr3   r   ecofZESO15s1ZESO15s2ZESS2ZEQM2s1ZEQM2s1LZEQM2s2LZESO25s1ZESO25s2ZESO35s1ZESO35s2r   r   r   energy_coefficients  sl    




8((DD

$<

r   c             C   sh   t ||||||}t||\}}	d|	 }
d}x2tdt|dD ]}|| |d  ||  7 }q@W ||
 S )Ng      g        r   r8   g       @)r   r   r
   arangelen)rB   r   r   rT   rU   r   r   r   r3   r   ampeir   r   r   energy  s    r   c                s*   t | |||||  fdd}t|ddS )Nc                sD   d}x:t dt dD ]$}|| |d   |  |d  7 }qW |S )Nr   r8   g      ?r   )r
   r   r   )rB   der   )r   r   r   test  s    $zmeco2.<locals>.testgMbP?g      ?)r   r   )rH   rI   rT   rU   r   r   r   r   )r   r   meco2  s    r   c             C   s   t t| |||t| |||S )N)minr   r   )rH   rI   r   r   r   r   r   t2_cutoff_velocity  s    r   c             C   s   t t| |||| | S )N)rA   r   )rH   rI   r   r   r   r   r   t2_cutoff_frequency  s    r   c             C   s0   d|| d   d| d  d|| d   d   S )z@Return the function whose first root defines the Kerr light ringr8   r   r   gUUUUUU?r   )rB   rt   r   r   r   kerr_lightring(  s    r   c             C   s,   | dkrt tddddS t tdd| dS dS )z*Return the velocity at the Kerr light ringgx#?r   g?)argsN)r   r   )rt   r   r   r   kerr_lightring_velocity-  s    r   c             C   s~  t jd }| d | d | d | d | d | d f\}}	}
}}}|d |d f\}}t|t|f\}}t|| }|d |d f\}}|| | }|d |d f\}}|d |d f\}}|d |d f\}}|| ||  | }ddd	| d||	  d
   t d||	  d||	  d| d||	  d
      }||d	 | | d d||  | |	 d  d| d |d  || d|  |  || d|  |  |
  dd||  | d| d|  | | |  d| d|  | | |   |  d| d d| | d  d| d  d| d  dd| d|  | | d| d|  | |  |dd|   d | |  | | |  |dd|   d | |  | | |  |d!d"|   d#| |  |d!d"|    |    |  |d dd$| d%|   | | dd%| d$|   | |  d&d'| d(|   | | |  d&d(| d'|   | | |  d)| ||    |    }|S )*a  Return hybrid MECO energy.

    Return the hybrid energy [eq. (6)] whose minimum defines the hybrid MECO
    up to 3.5PN (including the 3PN spin-spin)

    Parameters
    ----------
    m1 : float
        Mass of the primary object in solar masses.
    m2 : float
        Mass of the secondary object in solar masses.
    chi1: float
        Dimensionless spin of the primary object.
    chi2: float
        Dimensionless spin of the secondary object.
    qm1: float
        Quadrupole-monopole term of the primary object (1 for black holes).
    qm2: float
        Quadrupole-monopole term of the secondary object (1 for black holes).

    Returns
    -------
    h_E: float
        The hybrid energy as a function of v
    r   r   r9   r   r   rw   g      g      ?g       @gUUUUUU?g      @r8   g      (@g      3@g       @g      8@gqq?g      ^@g      S@g     F@g    @g      @g     i@g      X@g     `c@g     A@g     @@grq?g      5@g      L@g      ;@g      4@g      ?@g      "@g      C@g     @r@g     @T@g      @g     @g     v@g     @)r
   pirR   sqrt)rB   rH   rI   r   r   rd   re   Zpi_sqZv2Zv3Zv4Zv5Zv6Zv7Zchi1_sqZchi2_sqrC   ZM_2ZM_4r   Zeta2Zeta3Zm1_2Zm1_4Zm2_2Zm2_4rt   ZKerrZh_Er   r   r   hybridEnergy6  s&    
4: r   c          	   C   sd   |dkrd}|dkrd}||  ||  | |  }t |d }ttd| |||||fd|fgdj S )a  Return the velocity of the hybrid MECO

    Parameters
    ----------
    m1 : float
        Mass of the primary object in solar masses.
    m2 : float
        Mass of the secondary object in solar masses.
    chi1: float
        Dimensionless spin of the primary object.
    chi2: float
        Dimensionless spin of the secondary object.
    qm1: {None, float}, optional
        Quadrupole-monopole term of the primary object (1 for black holes).
        If None, will be set to qm1 = 1.
    qm2: {None, float}, optional
        Quadrupole-monopole term of the secondary object (1 for black holes).
        If None, will be set to qm2 = 1.

    Returns
    -------
    v: float
        The velocity (dimensionless) of the hybrid MECO
    Nr8   g{Gz?g?g?)r   Zbounds)r   r   r   r   item)rH   rI   r   r   rd   re   rt   Zvmaxr   r   r   hybrid_meco_velocityz  s    r   c             C   s4   |dkrd}|dkrd}t t| |||||| | S )a  Return the frequency of the hybrid MECO

    Parameters
    ----------
    m1 : float
        Mass of the primary object in solar masses.
    m2 : float
        Mass of the secondary object in solar masses.
    chi1: float
        Dimensionless spin of the primary object.
    chi2: float
        Dimensionless spin of the secondary object.
    qm1: {None, float}, optional
        Quadrupole-monopole term of the primary object (1 for black holes).
        If None, will be set to qm1 = 1.
    qm2: {None, float}, optional
        Quadrupole-monopole term of the secondary object (1 for black holes).
        If None, will be set to qm2 = 1.

    Returns
    -------
    f: float
        The frequency (in Hz) of the hybrid MECO
    Nr8   )rA   r   )rH   rI   r   r   rd   re   r   r   r   rf     s
    rf           c             C   sP   t ||||	|
||| tj |tj ||\}}}}}}}|||||||d}|S )a  Converts J-frame parameters into L0 frame.

    Parameters
    ----------
    mass1 : float
        The mass of the first component object in the
        binary (in solar masses)
    mass2 : float
        The mass of the second component object in the
        binary (in solar masses)
    f_ref : float
        The reference frequency.
    thetajn : float
        Angle between the line of sight and the total angular momentume J.
    phijl : float
        Azimuthal angle of L on its cone about J.
    spin1_a : float
        The dimensionless spin magnitude :math:`|\vec{{s}}_1/m^2_1|`.
    spin2_a : float
        The dimensionless spin magnitude :math:`|\vec{{s}}_2/m^2_2|`.
    spin1_polar : float
        Angle between L and the spin magnitude of the larger object.
    spin2_polar : float
        Angle betwen L and the spin magnitude of the smaller object.
    spin12_deltaphi : float
        Difference between the azimuthal angles of the spin of the larger
        object (S1) and the spin of the smaller object (S2).

    Returns
    -------
    dict :
        Dictionary of:

        * inclination : float
            Inclination (rad), defined as the angle between
            the orbital angular momentum L and the
            line-of-sight at the reference frequency.
        * spin1x : float
            The x component of the first binary component's
            dimensionless spin.
        * spin1y : float
            The y component of the first binary component's
            dimensionless spin.
        * spin1z : float
            The z component of the first binary component's
            dimensionless spin.
        * spin2x : float
            The x component of the second binary component's
            dimensionless spin.
        * spin2y : float
            The y component of the second binary component's
            dimensionless spin.
        * spin2z : float
            The z component of the second binary component's
            dimensionless spin.
    )inclinationspin1xspin1yr1   spin2xspin2yr2   )r   Z2SimInspiralTransformPrecessingNewInitialConditionsr;   r<   )r   r   f_refphirefthetajnphijlspin1_aspin2_aspin1_polarspin2_polarspin12_deltaphir   r   r   r1   r   r   r2   outr   r   r   jframe_to_l0frame  s    =
r   c             C   sD   t ||||||	|
| |||\}}}}}}}|||||||d}|S )a  Converts L0-frame parameters to J-frame.

    Parameters
    ----------
    mass1 : float
        The mass of the first component object in the
        binary (in solar masses)
    mass2 : float
        The mass of the second component object in the
        binary (in solar masses)
    f_ref : float
        The reference frequency.
    phiref : float
        The orbital phase at ``f_ref``.
    inclination : float
        Inclination (rad), defined as the angle between
        the orbital angular momentum L and the
        line-of-sight at the reference frequency.
    spin1x : float
        The x component of the first binary component's
        dimensionless spin.
    spin1y : float
        The y component of the first binary component's
        dimensionless spin.
    spin1z : float
        The z component of the first binary component's
        dimensionless spin.
    spin2x : float
        The x component of the second binary component's
        dimensionless spin.
    spin2y : float
        The y component of the second binary component's
        dimensionless spin.
    spin2z : float
        The z component of the second binary component's
        dimensionless spin.

    Returns
    -------
    dict :
        Dictionary of:

        * thetajn : float
            Angle between the line of sight and the total angular momentume J.
        * phijl : float
            Azimuthal angle of L on its cone about J.
        * spin1_a : float
            The dimensionless spin magnitude :math:`|\vec{{s}}_1/m^2_1|`.
        * spin2_a : float
            The dimensionless spin magnitude :math:`|\vec{{s}}_2/m^2_2|`.
        * spin1_polar : float
            Angle between L and the spin magnitude of the larger object.
        * spin2_polar : float
            Angle betwen L and the spin magnitude of the smaller object.
        * spin12_deltaphi : float
            Difference between the azimuthal angles of the spin of the larger
            object (S1) and the spin of the smaller object (S2).
    )r   r   r   r   r   r   r   )r   Z$SimInspiralTransformPrecessingWvf2PE)r   r   r   r   r   r   r   r1   r   r   r2   r   r   Zs1polZs2polZs12_deltaphir   r   r   r   r   r   l0frame_to_jframe  s    @r   )r   )FT)rk   )rv   rw   rn   )r   r   ro   ro   )r   r   ro   ro   )r   r   ro   ro   )NN)NN)r   r   r   r   r   r   r   r   )r   r   r   r   r   r   r   r   )G__doc__r;   r
   Zscipy.optimizer   r   r   Zpycbcr   r   Zimport_optionalr   r   r   r   r   r   r!   r"   r$   r&   r(   r)   r,   r-   r.   r7   r0   r=   r?   r@   rA   rD   rF   rJ   rM   rN   rP   rQ   rX   Z	vectorizerZ   r[   r]   r^   r_   rg   rj   ru   Zget_imr_durationr   r   r   r   rc   r   r   r   r   r   r   r   Zt4_cutoff_velocityZt4_cutoff_frequencyr   r   r   r   rf   r   r   r   r   r   r   <module>   s   


'

 

 
8

K


	D
'
!   
G  