B
    d"              J   @   s"  d Z ddlZddlZddlZddlmZ ddlZddlm	Z
mZ ddlmZ ejdZej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$d% Z d&d' Z!d(d) Z"d*d+ Z#d,d- Z$e%e$Z&dd/d0Z'e%e'Z(dd1d2Z)dd3d4Z*d5d6 Z+d7d8 Z,d9d: Z-d;d< Z.d=d> Z/d?d@ Z0dAdB Z1dCdD Z2dEdF Z3ddGdHZ4dIdJ Z5dKdL Z6dMdN Z7dOdP Z8ddRdSZ9ddUdVZ:ddWdXZ;dYdZ Z<d[d\ Z=d]d^ Z>d_d` Z?dadb Z@dcdd ZAdedf ZBdgdh ZCdidj ZDdkdl ZEdmdn ZFdodp ZGdqdr ZHdsdt ZIdudv ZJdwdx ZKdydz ZLd{d| ZMd}d~ ZNdd ZOdd ZPdd ZQdd ZRdd ZSdd ZTdd ZUdd ZVdddZWdddZXi ZYdddZZdd Z[dd Z\dd Z]dd Z^dddZ_dd Z`dddZadddZbdddddZcdddddZddddZedddZfdd Zgdd ZhdddZidddZjdddZkddÄ Zlddń ZmddǄ ZnddɄ Zodd˄ Zpdd̈́ ZqddPdSddddddddd!d#d%d'd)d+ddd2d4d6d8d:d@dBdDdFdHdJdLdNdhdjdZd\d^d`dbdldndpdrdtdvdxd~dzd|ddddddddddddddddddddfdddddVdXgJZrdS )z
This module provides a library of functions that calculate waveform parameters
from other parameters. All exposed functions in this module's namespace return
one parameter given a set of inputs.
    N)Detector   )spherical_to_cartesiancartesian_to_spherical)neutron_starspykerrlalsimulationc              G   s*   t dd | D }tj|  } | | | S )a  Apply numpy's broadcast rules to the given arguments.

    This will ensure that all of the arguments are numpy arrays and that they
    all have the same shape. See ``numpy.broadcast_arrays`` for more details.

    It also returns a boolean indicating whether any of the inputs were
    originally arrays.

    Parameters
    ----------
    *args :
        The arguments to check.

    Returns
    -------
    list :
        A list with length ``N+1`` where ``N`` is the number of given
        arguments. The first N values are the input arguments as ``ndarrays``s.
        The last value is a boolean indicating whether any of the
        inputs was an array.
    c             s   s   | ]}t |tjV  qd S )N)
isinstancenumpyZndarray).0arg r   ^/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/pycbc/conversions.py	<genexpr>I   s    zensurearray.<locals>.<genexpr>)anyr
   Zbroadcast_arraysappend)argsinput_is_arrayr   r   r   ensurearray3   s    

r   Fc             C   s   |s| j dkr|  } | S )zTIf the given argument is a numpy array with shape (1,), just returns
    that value.r   )sizeitem)r   r   r   r   r   formatreturnO   s    r   c             C   s
   | t j S )z/ Converts number of seconds to number of years )lalZYRJUL_SI)secr   r   r   sec_to_year^   s    r   c             C   s8   t | |\} }}t| }| |k }|| ||< t||S )z4Returns the larger of mass1 and mass2 (p = primary).)r   copyr   )mass1mass2r   mpmaskr   r   r   primary_massj   s
    
r    c             C   sL   t | |\} }}| j|jkr$tdt|}| |k }| | ||< t||S )z7Returns the smaller of mass1 and mass2 (s = secondary).z$mass1 and mass2 must have same shape)r   shape
ValueErrorr   r   )r   r   r   msr   r   r   r   secondary_masss   s    
r$   c             C   s   | | S )z,Returns the total mass from mass1 and mass2.r   )r   r   r   r   r   mtotal_from_mass1_mass2~   s    r%   c             C   s   t | |t| | S )z-Returns the mass ratio m1/m2, where m1 >= m2.)r    r$   )r   r   r   r   r   q_from_mass1_mass2   s    r&   c             C   s   t | |t| | S )z5Returns the inverse mass ratio m2/m1, where m1 >= m2.)r$   r    )r   r   r   r   r   invq_from_mass1_mass2   s    r'   c             C   s   | | | | d  S )z6Returns the symmetric mass ratio from mass1 and mass2.g       @r   )r   r   r   r   r   eta_from_mass1_mass2   s    r(   c             C   s   t | |d | |  S )z,Returns the chirp mass from mass1 and mass2.g333333?)r(   )r   r   r   r   r   mchirp_from_mass1_mass2   s    r)   c             C   s   ||  d|  S )zReturns a component mass from the given total mass and mass ratio.

    If the mass ratio q is >= 1, the returned mass will be the primary
    (heavier) mass. If q < 1, the returned mass will be the secondary
    (lighter) mass.
    g      ?r   )mtotalqr   r   r   mass1_from_mtotal_q   s    r,   c             C   s   | d|  S )zReturns a component mass from the given total mass and mass ratio.

    If the mass ratio q is >= 1, the returned mass will be the secondary
    (lighter) mass. If q < 1, the returned mass will be the primary (heavier)
    mass.
    g      ?r   )r*   r+   r   r   r   mass2_from_mtotal_q   s    r-   c             C   s   d|  ddd|  d   S )zOReturns the primary mass from the total mass and symmetric mass
    ratio.
    g      ?g      ?g      @r   )r*   etar   r   r   mass1_from_mtotal_eta   s    r/   c             C   s   d|  ddd|  d   S )zQReturns the secondary mass from the total mass and symmetric mass
    ratio.
    g      ?g      ?g      @r   )r*   r.   r   r   r   mass2_from_mtotal_eta   s    r0   c             C   s   | |d  S )zIReturns the total mass from the chirp mass and symmetric mass ratio.
    g333333?r   )mchirpr.   r   r   r   mtotal_from_mchirp_eta   s    r2   c             C   s   t | |}t||S )zKReturns the primary mass from the chirp mass and symmetric mass ratio.
    )r2   r/   )r1   r.   r*   r   r   r   mass1_from_mchirp_eta   s    
r3   c             C   s   t | |}t||S )zKReturns the primary mass from the chirp mass and symmetric mass ratio.
    )r2   r0   )r1   r.   r*   r   r   r   mass2_from_mchirp_eta   s    
r4   c             C   sF   | d |d  }t dd| | | g}|t||j   }|jS )aw  Returns the secondary mass from the chirp mass and primary 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:

    .. math::
        m_2^3 - a(m_2 + m_1) = 0,

    where

    .. math::
        a = \frac{\mathcal{M}^5}{m_1^3}.

    This has 3 solutions but only one will be real.
          r   r   )r
   rootsabsrealargmin)r1   r   ar7   Z	real_rootr   r   r   _mass2_from_mchirp_mass1   s    r<   Tc             C   sR   t |d| d |  || d  g}|r2t |}|rB||  S ||  S dS )aM  Returns the other component mass given one of the component masses
    and the symmetric mass ratio.

    This requires finding the roots of the quadratic equation:

    .. math::
        \eta m_2^2 + (2\eta - 1)m_1 m_2 + \eta m_1^2 = 0.

    This has two solutions which correspond to :math:`m_1` being the heavier
    mass or it being the lighter mass. By default, `known_mass` is assumed to
    be the heavier (primary) mass, and the smaller solution is returned. Use
    the `other_is_secondary` to invert.

    Parameters
    ----------
    known_mass : float
        The known component mass.
    eta : float
        The symmetric mass ratio.
    known_is_secondary : {False, bool}
        Whether the known component mass is the primary or the secondary. If
        True, `known_mass` is assumed to be the secondary (lighter) mass and
        the larger solution is returned. Otherwise, the smaller solution is
        returned. Default is False.
    force_real : {True, bool}
        Force the returned mass to be real.

    Returns
    -------
    float
        The other component mass.
       r   g       @N)r
   r7   r9   Zargmaxr:   )Z
known_massr.   known_is_secondary
force_realr7   r   r   r   _mass_from_knownmass_eta   s    "$
r@   c             C   s   t | |d|dS )zSReturns the secondary mass from the primary mass and symmetric mass
    ratio.
    F)r>   r?   )mass_from_knownmass_eta)r   r.   r?   r   r   r   mass2_from_mass1_eta  s    rB   c             C   s   t | |d|dS )zSReturns the primary mass from the secondary mass and symmetric mass
    ratio.
    T)r>   r?   )rA   )r   r.   r?   r   r   r   mass1_from_mass2_eta  s    rC   c             C   s   | d|  d  S )zReturns the symmetric mass ratio from the given mass ratio.

    This is given by:

    .. math::
        \eta = \frac{q}{(1+q)^2}.

    Note that the mass ratio may be either < 1 or > 1.
    g      ?r=   r   )r+   r   r   r   
eta_from_q#  s    
rD   c             C   s   |d d| d  |  }|S )zBReturns the primary mass from the given chirp mass and mass ratio.g?g      ?g?r   )r1   r+   r   r   r   r   mass1_from_mchirp_q0  s    rE   c             C   s   |d d| d  |  }|S )zDReturns the secondary mass from the given chirp mass and mass ratio.g333333g      ?g?r   )r1   r+   r   r   r   r   mass2_from_mchirp_q5  s    rF   c             C   s   ddt j|  d   S )zUsed in calculating chirp times: see Cokelaer, arxiv.org:0706.4437
       appendix 1, also lalinspiral/python/sbank/tau0tau3.py.
    g      @g      p@gUUUUUU@)r
   pi)f_lowerr   r   r   _a0:  s    rI   c             C   s   t jdt j|  d   S )z&Another parameter used for chirp timesg       @g?)r
   rG   )rH   r   r   r   _a3@  s    rJ   c             C   s   | t j } t|| d |  S )zcReturns :math:`\tau_0` from the total mass, symmetric mass ratio, and
    the given frequency.
    g?)r   MTSUN_SIrI   )r*   r.   rH   r   r   r   tau0_from_mtotal_etaE  s    
rL   c             C   s   | t j } t|| d |  S )zcReturns :math:`\tau_0` from the total mass, symmetric mass ratio, and
    the given frequency.
    gUUUUUU?)r   rK   rJ   )r*   r.   rH   r   r   r   tau3_from_mtotal_etaO  s    
rM   c             C   s   | | }t | |}t|||S )zJReturns :math:`\tau_0` from the component masses and given frequency.
    )r(   rL   )r   r   rH   r*   r.   r   r   r   tau0_from_mass1_mass2Y  s    
rN   c             C   s   | | }t | |}t|||S )zJReturns :math:`\tau_3` from the component masses and given frequency.
    )r(   rM   )r   r   rH   r*   r.   r   r   r   tau3_from_mass1_mass2a  s    
rO   c             C   s*   |t | | t|  }|s&|tj }|S )z/Returns total mass from :math:`\tau_0, \tau_3`.)rJ   rI   r   rK   )tau0tau3rH   
in_secondsr*   r   r   r   mtotal_from_tau0_tau3i  s    
rS   c             C   s(   t | ||dd}|d t||  }|S )z9Returns symmetric mass ratio from :math:`\tau_0, \tau_3`.T)rR   gUUUUUU)rS   rJ   )rP   rQ   rH   r*   r.   r   r   r   eta_from_tau0_tau3s  s    rT   c             C   s"   t | ||}t| ||}t||S )z?Returns the primary mass from the given :math:`\tau_0, \tau_3`.)rS   rT   r/   )rP   rQ   rH   r*   r.   r   r   r   mass1_from_tau0_tau3{  s    rU   c             C   s"   t | ||}t| ||}t||S )zAReturns the secondary mass from the given :math:`\tau_0, \tau_3`.)rS   rT   r0   )rP   rQ   rH   r*   r.   r   r   r   mass2_from_tau0_tau3  s    rV   c             C   s   t | |||\}}}}}|| }t || \}}	||k }
||
  ||
< t||}|dd|  d|d    }dd|  d dd|  d|d    | }td	||  |S )
z The effective lambda parameter

    The mass-weighted dominant effective lambda parameter defined in
    https://journals.aps.org/prd/pdf/10.1103/PhysRevD.91.043002
    r   g      @   g       @   g      ?	      g;;?)r   r(   r   )r   r   Zlambda1Zlambda2m1m2r   ZlsumZldiff_r   r.   p1p2r   r   r   lambda_tilde  s    
,r`           c             C   sP   t |}|dddf }|dddf }| dtj|  }t |||}|S )zReturn the lambda parameter(s) corresponding to the input mass(es)
    interpolating from the mass-Lambda data for a particular EOS read in from
    an ASCII file.
    Nr   r   g      ?)r
   ZloadtxtpycbcZ	cosmologyZredshiftZinterp)massZtov_fileZdistancedataZmass_from_fileZlambda_from_fileZmass_srclambdavr   r   r   lambda_from_mass_tov_file  s    
rf   2Hc       
      C   s   t | |||\} }}}}yt|| kr2|r2tdW n4 tk
rh   || krd|sdtd|  d| Y nX t||\}}t| |}t|||||}	t|	|S )aK  
    Function that determines the remnant disk mass of an NS-BH system
    using the fit to numerical-relativity results discussed in
    Foucart, Hinderer & Nissanke, PRD 98, 081501(R) (2018).
    The BH spin may be misaligned with the orbital angular momentum.
    In such cases the ISSO is approximated following the approach of
    Stone, Loeb & Berger, PRD 87, 084053 (2013), which was originally
    devised for a previous NS-BH remnant mass fit of
    Foucart, PRD 86, 124007 (2012).
    Note: NS spin is assumed to be 0!

    Parameters
    -----------
    mass1 : float
        The mass of the black hole, in solar masses.
    mass2 : float
        The mass of the neutron star, in solar masses.
    spin1a : float, optional
        The dimensionless magnitude of the spin of mass1. Default = 0.
    spin1pol : float, optional
        The tilt angle of the spin of mass1. Default = 0 (aligned w L).
    eos : str, optional
        Name of the equation of state being adopted. Default is '2H'.

    Returns
    ----------
    remnant_mass: float
        The remnant mass in solar masses
    zRequire mass1 >= mass2zRequire mass1 >= mass2. z < )	r   r   r"   	TypeErrornsZinitialize_eosr(   Z	foucart18r   )
r   r   spin1aspin1poleosr   Zns_compactnessZ	ns_b_massr.   Zremnant_massr   r   r   0remnant_mass_from_mass1_mass2_spherical_spin_eos  s    
rm   c       	      C   s$   t |||\}}}t| ||||dS )a  
    Function that determines the remnant disk mass of an NS-BH system
    using the fit to numerical-relativity results discussed in
    Foucart, Hinderer & Nissanke, PRD 98, 081501(R) (2018).
    The BH spin may be misaligned with the orbital angular momentum.
    In such cases the ISSO is approximated following the approach of
    Stone, Loeb & Berger, PRD 87, 084053 (2013), which was originally
    devised for a previous NS-BH remnant mass fit of
    Foucart, PRD 86, 124007 (2012).
    Note: NS spin is assumed to be 0!

    Parameters
    -----------
    mass1 : float
        The mass of the black hole, in solar masses.
    mass2 : float
        The mass of the neutron star, in solar masses.
    spin1x : float, optional
        The dimensionless x-component of the spin of mass1. Default = 0.
    spin1y : float, optional
        The dimensionless y-component of the spin of mass1. Default = 0.
    spin1z : float, optional
        The dimensionless z-component of the spin of mass1. Default = 0.
    eos: str, optional
        Name of the equation of state being adopted. Default is '2H'.

    Returns
    ----------
    remnant_mass: float
        The remnant mass in solar masses
    )rl   )_cartesian_to_sphericalrm   )	r   r   spin1xspin1yspin1zrl   rj   r]   rk   r   r   r   0remnant_mass_from_mass1_mass2_cartesian_spin_eos  s    !rr   c             C   s   ||  ||  | |  S )zAReturns the effective spin from mass1, mass2, spin1z, and spin2z.r   )r   r   rq   spin2zr   r   r   chi_eff  s    rt   c             C   s   || ||   ||   S )zb Returns the aligned mass-weighted spin difference from mass1, mass2,
    spin1z, and spin2z.
    r   )r   r   rq   rs   r   r   r   chi_a	  s    ru   c             C   s.   t | |||||}t| |||||}t||S )zeReturns the effective precession spin from mass1, mass2, spin1x,
    spin1y, spin2x, and spin2y.
    )secondary_xi
primary_xichi_p_from_xi1_xi2)r   r   ro   rp   spin2xspin2yxi1xi2r   r   r   chi_p  s    r}   c             C   sN   t t| |||t| |||}t t| |||t| |||}|| dtj  S )z< Returns the angle between the in-plane perpendicular spins.r=   )phi_from_spinx_spinyprimary_spinsecondary_spinr
   rG   )r   r   ro   rp   ry   rz   phi1phi2r   r   r   phi_a  s
    r   c             C   s&   t | |}t ||}|| dtj  S )z5 Returns the sum of the in-plane perpendicular spins.r=   )r~   r
   rG   )ro   rp   ry   rz   r   r   r   r   r   phi_s"  s    

r   c             C   s*   |t | }|t | }t| |||S )z@Returns the effective spin using spins in spherical coordinates.)r
   cosrt   )r   r   spin1_aspin1_polarspin2_aspin2_polarrq   rs   r   r   r   chi_eff_from_spherical)  s    r   c             C   s6   t |||\}}	}
t |||\}}}
t| |||	||S )zTReturns the effective precession spin using spins in spherical
    coordinates.
    )_spherical_to_cartesianr}   )r   r   r   Zspin1_azimuthalr   r   Zspin2_azimuthalr   ro   rp   r]   ry   rz   r   r   r   chi_p_from_spherical1  s
    r   c             C   s@   t | |||\} }}}}t|}| |k }|| ||< t||S )z3Returns the dimensionless spin of the primary mass.)r   r   r   )r   r   spin1spin2r   spr   r   r   r   r   =  s    
r   c             C   s@   t | |||\} }}}}t|}| |k }|| ||< t||S )z5Returns the dimensionless spin of the secondary mass.)r   r   r   )r   r   r   r   r   ssr   r   r   r   r   G  s    
r   c             C   s&   t | |||}t | |||}t||S )zHReturns the effective precession spin argument for the larger mass.
    )r   chi_perp_from_spinx_spiny)r   r   ro   rp   ry   rz   spinxspinyr   r   r   rw   Q  s    rw   c             C   s*   t | |||}t | |||}t| |||S )zIReturns the effective precession spin argument for the smaller mass.
    )r   "xi2_from_mass1_mass2_spin2x_spin2y)r   r   ro   rp   ry   rz   r   r   r   r   r   rv   Y  s    rv   c             C   s
   t | |S )zReturns the effective precession spin argument for the larger mass.
    This function assumes it's given spins of the primary mass.
    )r   )ro   rp   r   r   r   xi1_from_spin1x_spin1ya  s    r   c             C   sD   t | |}dd| d  }ddd|   }||d |  t|| S )zReturns the effective precession spin argument for the smaller mass.
    This function assumes it's given spins of the secondary mass.
    r=   r6   )r&   r   )r   r   ry   rz   r+   a1a2r   r   r   r   h  s    
r   c             C   s   t | d |d  S )zCReturns the in-plane spin from the x/y components of the spin.
    r=   )r
   sqrt)r   r   r   r   r   r   r  s    r   c             C   s>   t | |}dd| d  }ddd|   }|d | | | S )zUReturns the in-plane spin from mass1, mass2, and xi2 for the
    secondary mass.
    r=   r6   )r&   )r   r   r|   r+   r   r   r   r   r   chi_perp_from_mass1_mass2_xi2x  s    
r   c             C   s8   t | |\} }}t| }| |k }|| ||< t||S )z8Returns effective precession spin from xi1 and xi2.
    )r   r   r   )r{   r|   r   r}   r   r   r   r   rx     s
    
rx   c             C   s   ||  d S )zxReturns the angle between the x-component axis and the in-plane
    spin for the primary mass from phi_s and phi_a.
    g       @r   )r   r   r   r   r   phi1_from_phi_a_phi_s  s    r   c             C   s   ||  d S )zzReturns the angle between the x-component axis and the in-plane
    spin for the secondary mass from phi_s and phi_a.
    g       @r   )r   r   r   r   r   phi2_from_phi_a_phi_s  s    r   c             C   s   t || }|dt j  S )zJReturns the angle between the x-component axis and the in-plane spin.
    r=   )r
   Zarctan2rG   )r   r   phir   r   r   r~     s    r~   c             C   s   | | d|   ||  S )zReturns spin1z.
    g       @r   )r   r   rt   ru   r   r   r   %spin1z_from_mass1_mass2_chi_eff_chi_a  s    r   c             C   s   | | d|  ||  S )zReturns spin2z.
    g       @r   )r   r   rt   ru   r   r   r   %spin2z_from_mass1_mass2_chi_eff_chi_a  s    r   c             C   s   t ||}| t| S )z/Returns x-component spin for primary mass.
    )r   r
   r   )r{   r   r   r   r   r   r   spin1x_from_xi1_phi_a_phi_s  s    
r   c             C   s   t ||}| t| S )z/Returns y-component spin for primary mass.
    )r   r
   sin)r{   r   r   r   r   r   r   spin1y_from_xi1_phi_a_phi_s  s    
r   c             C   s$   t | ||}t||}|t| S )z1Returns x-component spin for secondary mass.
    )r   r   r
   r   )r   r   r|   r   r   chi_perpr   r   r   r   'spin2x_from_mass1_mass2_xi2_phi_a_phi_s  s    
r   c             C   s$   t | ||}t||}|t| S )z1Returns y-component spin for secondary mass.
    )r   r   r
   r   )r   r   r|   r   r   r   r   r   r   r   'spin2y_from_mass1_mass2_xi2_phi_a_phi_s  s    
r   c             C   s\   t | }d}d}d}d}d}|||  ||d   ||d   ||d   }t |d	 S )
aD  Return the quadrupole moment of a neutron star given its lambda

    We use the relations defined here. https://arxiv.org/pdf/1302.4499.pdf.
    Note that the convention we use is that:

    .. math::

        \mathrm{dquadmon} = \bar{Q} - 1.

    Where :math:`\bar{Q}` (dimensionless) is the reduced quadrupole moment.
    gE?ggj+?g0*D?gE>qgFn1 ?g       @g      @g      @r   )r
   logexp)re   llZaiZbiciZdieiZln_quad_momentr   r   r   dquadmon_from_lambda  s    
0r   c             C   sB   dt j | }| tj }d| |d tj d  }|| |d  S )ao  Returns the dimensionless spin of a pulsar.

    Assumes the pulsar is a solid sphere when computing the moment of inertia.

    Parameters
    ----------
    mass : float
        The mass of the pulsar, in solar masses.
    radius : float
        The assumed radius of the pulsar, in kilometers.
    freq : float
        The spin frequency of the pulsar, in Hz.
    r=   g?i  )r
   rG   r   rK   C_SI)rc   ZradiusfreqomegamtZmominertr   r   r   spin_from_pulsar_freq  s    
r   ffffff?c             C   s   | d| | d  S )zMReturns the chirp distance given the luminosity distance and chirp mass.
    g ڌ?g?r   )distr1   ref_massr   r   r   chirp_distance  s    r   c             C   s   | d| | d  S )zKReturns the luminosity distance given a chirp distance and chirp mass.
    g ڌ?gr   )r   r1   r   r   r   r   #distance_from_chirp_distance_mchirp  s    r   
geocentricc       	      C   sn   |}|rd}|| kr|S | t kr,t| t | < t |  }|dkrN||||| S t|}|||||| S dS )a  Returns the coalescence time of a signal in the given detector.

    Parameters
    ----------
    detector_name : string
        The name of the detector, e.g., 'H1'.
    ra : float
        The right ascension of the signal, in radians.
    dec : float
        The declination of the signal, in radians.
    tc : float
        The GPS time of the coalescence of the signal in the `ref_frame`.
    ref_frame : {'geocentric', string}
        The reference frame that the given coalescence time is defined in.
        May specify 'geocentric', or a detector name; default is 'geocentric'.

    Returns
    -------
    float :
        The GPS time of the coalescence in detector `detector_name`.
    r   r   N)_detector_cacher   Ztime_delay_from_earth_centerZtime_delay_from_detector)	detector_nameradectcZ	ref_framerelativeZref_timedetectorotherr   r   r   det_tc	  s    r   c             C   s   t | }||\}}||fS )zb Low-level function to be called from _optimal_dec_from_detector
    and _optimal_ra_from_detector)r   Zoptimal_orientation)r   r   dr   r   r   r   r   !optimal_orientation_from_detector.  s    r   c             C   s   t | |d S )a  For a given detector and GPS time, return the optimal orientation
    (directly overhead of the detector) in declination.


    Parameters
    ----------
    detector_name : string
        The name of the detector, e.g., 'H1'.
    tc : float
        The GPS time of the coalescence of the signal in the `ref_frame`.

    Returns
    -------
    float :
        The declination of the signal, in radians.
    r   )r   )r   r   r   r   r   optimal_dec_from_detector6  s    r   c             C   s   t | |d S )a  For a given detector and GPS time, return the optimal orientation
    (directly overhead of the detector) in right ascension.


    Parameters
    ----------
    detector_name : string
        The name of the detector, e.g., 'H1'.
    tc : float
        The GPS time of the coalescence of the signal in the `ref_frame`.

    Returns
    -------
    float :
        The declination of the signal, in radians.
    r   )r   )r   r   r   r   r   optimal_ra_from_detectorI  s    r   c          	   C   s^   t | t}|rt| g} tjdd td|  }W dQ R X d|t|< |rZ|d }|S )ah  Returns SNR computed from the given log likelihood ratio(s). This is
    defined as `sqrt(2*loglr)`.If the log likelihood ratio is < 0, returns 0.

    Parameters
    ----------
    loglr : array or float
        The log likelihood ratio(s) to evaluate.

    Returns
    -------
    array or float
        The SNRs computed from the log likelihood ratios.
    ignore)invalidr=   Ng        r   )r	   floatr
   arrayZerrstater   isnan)ZloglrZ	singlevalZsnrsr   r   r   snr_from_loglrc  s    
r   bothc             C   s   t | ||||\} }}}}}|dkp*|dk}|dkp:|dk}g }	|rft| ||||}
|	t|
| |rt| ||||}|	t|| |r|s|	d }	|	S )a  Return the f0 and the tau for one or more overtones of an l, m mode.

    Parameters
    ----------
    mass : float or array
        Mass of the black hole (in solar masses).
    spin : float or array
        Dimensionless spin of the final black hole.
    l : int or array
        l-index of the harmonic.
    m : int or array
        m-index of the harmonic.
    n : int or array
        Overtone(s) to generate, where n=0 is the fundamental mode.
        Default is 0.
    which : {'both', 'f0', 'tau'}, optional
        What to return; 'both' returns both frequency and tau, 'f0' just
        frequency, 'tau' just tau. Default is 'both'.

    Returns
    -------
    f0 : float or array
        Returned if ``which`` is 'both' or 'f0'.
        The frequency of the QNM(s), in Hz.
    tau : float or array
        Returned if ``which`` is 'both' or 'tau'.
        The damping time of the QNM(s), in seconds.
    r   f0taur   )r   r   Zqnmfreqr   r   Zqnmtau)rc   spinlmnwhichr   Zgetf0ZgettauoutZf0sZtausr   r   r   get_lm_f0tau  s    r   c          	   C   s   i i  }}x|D ]}d}t |d t |d t |d   }}}	xPt|	D ]D}
t| ||||
\}}||||t||
< ||||t||
< qJW qW ||fS )a  Returns a dictionary of all of the frequencies and damping times for the
    requested modes.

    Parameters
    ----------
    mass : float or array
        Mass of the black hole (in solar masses).
    spin : float or array
        Dimensionless spin of the final black hole.
    modes : list of str
        The modes to get. Each string in the list should be formatted
        'lmN', where l (m) is the l (m) index of the harmonic and N is the
        number of overtones to generate (note, N is not the index of the
        overtone).

    Returns
    -------
    f0 : dict
        Dictionary mapping the modes to the frequencies. The dictionary keys
        are 'lmn' string, where l (m) is the l (m) index of the harmonic and
        n is the index of the overtone. For example, '220' is the l = m = 2
        mode and the 0th overtone.
    tau : dict
        Dictionary mapping the modes to the damping times. The keys are the
        same as ``f0``.
    z{}{}{}r   r   r=   )intranger   formatr8   )rc   r   modesr   r   Zlmnkeyr   r   Znmodesr   Ztmp_f0Ztmp_taur   r   r   get_lm_f0tau_allmodes  s    

(r   r=   c             C   s   t | ||||ddS )ah  Returns QNM frequency for the given mass and spin and mode.

    Parameters
    ----------
    final_mass : float or array
        Mass of the black hole (in solar masses).
    final_spin : float or array
        Dimensionless spin of the final black hole.
    l : int or array, optional
        l-index of the harmonic. Default is 2.
    m : int or array, optional
        m-index of the harmonic. Default is 2.
    n : int or array
        Overtone(s) to generate, where n=0 is the fundamental mode.
        Default is 0.

    Returns
    -------
    float or array
        The frequency of the QNM(s), in Hz.
    r   )r   r   )r   )
final_mass
final_spinr   r   r   r   r   r   freq_from_final_mass_spin  s    r   c             C   s   t | ||||ddS )as  Returns QNM damping time for the given mass and spin and mode.

    Parameters
    ----------
    final_mass : float or array
        Mass of the black hole (in solar masses).
    final_spin : float or array
        Dimensionless spin of the final black hole.
    l : int or array, optional
        l-index of the harmonic. Default is 2.
    m : int or array, optional
        m-index of the harmonic. Default is 2.
    n : int or array
        Overtone(s) to generate, where n=0 is the fundamental mode.
        Default is 0.

    Returns
    -------
    float or array
        The damping time of the QNM(s), in seconds.
    r   )r   r   )r   )r   r   r   r   r   r   r   r   tau_from_final_mass_spin  s    r   )gffffff?g\m?gV-߿)g333333ӿgEJ@g0L
F%Ϳ)g?gX9v@gbX9޿)g_vO?gg@gzG޿))r=   r=   )r=   r   )r6   r6   )rX   rX   )gAf?gn4@gaTR'?)g333333?g8gDioͿgQ?)gd`T?gBig48E?)gffffff@ggw#?c          	   C   s   t | |\} }}t||f \}}}| j}|  } | }t| j}	xht|	jD ]Z}
| |
 ||
  tj }yd|| | d|   }W n t	k
r   tj
}Y nX ||	|
< qPW |	|}	t|	|S )a  Returns the final spin based on the given frequency and damping time.

    .. note::
        Currently, only (l,m) = (2,2), (3,3), (4,4), (2,1) are supported.
        Any other indices will raise a ``KeyError``.

    Parameters
    ----------
    f0 : float or array
        Frequency of the QNM (in Hz).
    tau : float or array
        Damping time of the QNM (in seconds).
    l : int, optional
        l-index of the harmonic. Default is 2.
    m : int, optional
        m-index of the harmonic. Default is 2.

    Returns
    -------
    float or array
        The spin of the final black hole. If the combination of frequency
        and damping times give an unphysical result, ``numpy.nan`` will be
        returned.
    g      ?)r   _berti_spin_constantsr!   ravelr
   zerosr   r   rG   r"   nanreshaper   )r   r   r   r   r   r;   bc	origshapeZspinsiiQsr   r   r   final_spin_from_f0_tau   s    
r   c             C   sJ   t | |||d}t||f \}}}||d| |   dtj |  tj  S )a  Returns the final mass (in solar masses) based on the given frequency
    and damping time.

    .. note::
        Currently, only (l,m) = (2,2), (3,3), (4,4), (2,1) are supported.
        Any other indices will raise a ``KeyError``.

    Parameters
    ----------
    f0 : float or array
        Frequency of the QNM (in Hz).
    tau : float or array
        Damping time of the QNM (in seconds).
    l : int, optional
        l-index of the harmonic. Default is 2.
    m : int, optional
        m-index of the harmonic. Default is 2.

    Returns
    -------
    float or array
        The mass of the final black hole. If the combination of frequency
        and damping times give an unphysical result, ``numpy.nan`` will be
        returned.
    )r   r   r   r=   )r   _berti_mass_constantsr
   rG   r   rK   )r   r   r   r   r   r;   r   r   r   r   r   final_mass_from_f0_tauL  s    r   c       
      C   sl   t | |||d}t| |||d}t||\}}}tj||dk < tj|t|dk< t||||d}	t|	|S )a^  Returns the QNM frequency (in Hz) of a chosen new (l,m) mode from the
    given current (l,m) mode.

    Parameters
    ----------
    f0 : float or array
        Frequency of the current QNM (in Hz).
    tau : float or array
        Damping time of the current QNM (in seconds).
    current_l : int, optional
        l-index of the current QNM.
    current_m : int, optional
        m-index of the current QNM.
    new_l : int, optional
        l-index of the new QNM to convert to.
    new_m : int, optional
        m-index of the new QNM to convert to.

    Returns
    -------
    float or array
        The frequency of the new (l, m) QNM mode. If the combination of
        frequency and damping time provided for the current (l, m) QNM mode
        correspond to an unphysical Kerr black hole mass and/or spin,
        ``numpy.nan`` will be returned.
    )r   r   r   gx#?)r   r   r   r
   r   r8   r   r   )
r   r   	current_l	current_mnew_lnew_mrc   r   r   Znew_f0r   r   r   freqlmn_from_other_lmnk  s    r   c       
      C   sl   t | |||d}t| |||d}t||\}}}tj||dk < tj|t|dk< t||||d}	t|	|S )ah  Returns the QNM damping time (in seconds) of a chosen new (l,m) mode
    from the given current (l,m) mode.

    Parameters
    ----------
    f0 : float or array
        Frequency of the current QNM (in Hz).
    tau : float or array
        Damping time of the current QNM (in seconds).
    current_l : int, optional
        l-index of the current QNM.
    current_m : int, optional
        m-index of the current QNM.
    new_l : int, optional
        l-index of the new QNM to convert to.
    new_m : int, optional
        m-index of the new QNM to convert to.

    Returns
    -------
    float or array
        The daming time of the new (l, m) QNM mode. If the combination of
        frequency and damping time provided for the current (l, m) QNM mode
        correspond to an unphysical Kerr black hole mass and/or spin,
        ``numpy.nan`` will be returned.
    )r   r   r   gx#?)r   r   r   r
   r   r8   r   r   )
r   r   r   r   r   r   rc   r   r   Znew_taur   r   r   taulmn_from_other_lmn  s    r   SEOBNRv4PHMc
          
   C   s6  | |||||||f}
t |
 }
|
d }|
d j}dd |
dd D }
|
\} }}}}}}}t| jtj}t| jtj}xt|jD ]}t| | }t|| }tt	t|| || || g}tt	t|| || || g}|dkrddl
m} y,|j|tj |tj ||dd	d
g|	d}W n tk
r>   wY nX |d	 d tj ||< |d
 }|d  d ||< |d dk r
||  d9  < q|dkrt||||tt|\}}}|||  ||< |||< qt||||tt|\}}}|||  ||< |||< qW ||}||}t||t||fS )a}  Estimates the final mass and spin from the given initial parameters.

    This uses the fits used by either the NRSur7dq4 or EOBNR models for
    converting from initial parameters to final, depending on the
    ``approximant`` argument.

    Parameters
    ----------
    mass1 : float
        The mass of one of the components, in solar masses.
    mass2 : float
        The mass of the other component, in solar masses.
    spin1x : float, optional
        The dimensionless x-component of the spin of mass1. Default is 0.
    spin1y : float, optional
        The dimensionless y-component of the spin of mass1. Default is 0.
    spin1z : float, optional
        The dimensionless z-component of the spin of mass1. Default is 0.
    spin2x : float, optional
        The dimensionless x-component of the spin of mass2. Default is 0.
    spin2y : float, optional
        The dimensionless y-component of the spin of mass2. Default is 0.
    spin2z : float, optional
        The dimensionless z-component of the spin of mass2. Default is 0.
    approximant : str, optional
        The waveform approximant to use for the fit function. If "NRSur7dq4",
        the NRSur7dq4Remnant fit in lalsimulation will be used. If "SEOBNRv4",
        the ``XLALSimIMREOBFinalMassSpin`` function in lalsimulation will be
        used. Otherwise, ``XLALSimIMREOBFinalMassSpinPrec`` from lalsimulation
        will be used, with the approximant name passed as the approximant
        in that function ("SEOBNRv4PHM" will work with this function).
        Default is "SEOBNRv4PHM".
    f_ref : float, optional
        The reference frequency for the spins. Only used by the NRSur7dq4
        fit. Default (-1) will use the default reference frequency for the
        approximant.

    Returns
    -------
    final_mass : float
        The final mass, in solar masses.
    final_spin : float
        The dimensionless final spin.
    r   r   c             S   s   g | ]}|  qS r   )r   )r   r;   r   r   r   
<listcomp>  s    z*get_final_from_initial.<locals>.<listcomp>NZ	NRSur7dq4)nrfitsZNRSur7dq4RemnantZ	FinalMassZ	FinalSpin)f_refr=   g      ?ZSEOBNRv4)r   r!   r
   fullr   r   r   r   listmapr   r   Z
eval_nrfitr   MSUN_SIRuntimeErrorsumlalsimZSimIMREOBFinalMassSpingetattrZSimIMREOBFinalMassSpinPrecr   r   )r   r   ro   rp   rq   ry   rz   rs   approximantr   r   r   r   r   r   r   r[   r\   r   r   r   resZsfr]   fmfsr   r   r   get_final_from_initial  sR    /
  




r  c
       
      C   s    t | |||||||||	d
d S )a*  Estimates the final mass from the given initial parameters.

    This uses the fits used by either the NRSur7dq4 or EOBNR models for
    converting from initial parameters to final, depending on the
    ``approximant`` argument.

    Parameters
    ----------
    mass1 : float
        The mass of one of the components, in solar masses.
    mass2 : float
        The mass of the other component, in solar masses.
    spin1x : float, optional
        The dimensionless x-component of the spin of mass1. Default is 0.
    spin1y : float, optional
        The dimensionless y-component of the spin of mass1. Default is 0.
    spin1z : float, optional
        The dimensionless z-component of the spin of mass1. Default is 0.
    spin2x : float, optional
        The dimensionless x-component of the spin of mass2. Default is 0.
    spin2y : float, optional
        The dimensionless y-component of the spin of mass2. Default is 0.
    spin2z : float, optional
        The dimensionless z-component of the spin of mass2. Default is 0.
    approximant : str, optional
        The waveform approximant to use for the fit function. If "NRSur7dq4",
        the NRSur7dq4Remnant fit in lalsimulation will be used. If "SEOBNRv4",
        the ``XLALSimIMREOBFinalMassSpin`` function in lalsimulation will be
        used. Otherwise, ``XLALSimIMREOBFinalMassSpinPrec`` from lalsimulation
        will be used, with the approximant name passed as the approximant
        in that function ("SEOBNRv4PHM" will work with this function).
        Default is "SEOBNRv4PHM".
    f_ref : float, optional
        The reference frequency for the spins. Only used by the NRSur7dq4
        fit. Default (-1) will use the default reference frequency for the
        approximant.

    Returns
    -------
    float
        The final mass, in solar masses.
    )r   r   )r  )
r   r   ro   rp   rq   ry   rz   rs   r   r   r   r   r   final_mass_from_initial  s    -r  c
       
      C   s    t | |||||||||	d
d S )a'  Estimates the final spin from the given initial parameters.

    This uses the fits used by either the NRSur7dq4 or EOBNR models for
    converting from initial parameters to final, depending on the
    ``approximant`` argument.

    Parameters
    ----------
    mass1 : float
        The mass of one of the components, in solar masses.
    mass2 : float
        The mass of the other component, in solar masses.
    spin1x : float, optional
        The dimensionless x-component of the spin of mass1. Default is 0.
    spin1y : float, optional
        The dimensionless y-component of the spin of mass1. Default is 0.
    spin1z : float, optional
        The dimensionless z-component of the spin of mass1. Default is 0.
    spin2x : float, optional
        The dimensionless x-component of the spin of mass2. Default is 0.
    spin2y : float, optional
        The dimensionless y-component of the spin of mass2. Default is 0.
    spin2z : float, optional
        The dimensionless z-component of the spin of mass2. Default is 0.
    approximant : str, optional
        The waveform approximant to use for the fit function. If "NRSur7dq4",
        the NRSur7dq4Remnant fit in lalsimulation will be used. If "SEOBNRv4",
        the ``XLALSimIMREOBFinalMassSpin`` function in lalsimulation will be
        used. Otherwise, ``XLALSimIMREOBFinalMassSpinPrec`` from lalsimulation
        will be used, with the approximant name passed as the approximant
        in that function ("SEOBNRv4PHM" will work with this function).
        Default is "SEOBNRv4PHM".
    f_ref : float, optional
        The reference frequency for the spins. Only used by the NRSur7dq4
        fit. Default (-1) will use the default reference frequency for the
        approximant.

    Returns
    -------
    float
        The dimensionless final spin.
    )r   r   )r  )
r   r   ro   rp   rq   ry   rz   rs   r   r   r   r   r   final_spin_from_initialD  s    -r  c             C   s   | d |t j t j  S )a   Calculate the gravitational-wave frequency from the
    total mass and invariant velocity.

    Parameters
    ----------
    v : float
        Invariant velocity
    M : float
        Binary total mass

    Returns
    -------
    f : float
        Gravitational-wave frequency
    g      @)r   rK   PI)vMr   r   r   velocity_to_frequency~  s    r  c             C   s   t j| t j |  d S )a)   Calculate the invariant velocity from the total
    mass and gravitational-wave frequency.

    Parameters
    ----------
    f: float
        Gravitational-wave frequency
    M: float
        Binary total mass

    Returns
    -------
    v : float or numpy.array
        Invariant velocity
    gUUUUUU?)r   r  rK   )fr  r   r   r   frequency_to_velocity  s    r
  c             C   s
   t d| 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
    g>,p ?)r  )r  r   r   r   f_schwarzchild_isco  s    r  c       
      C   s   d}t ||}|tjj9 }dtjjtjj | | tjjd  d  }d|  }dtjj|  | || |d   }d| || |d   }	|||	fS )	a9  Calculate the coefficents needed to compute the
    shift in t(f) and phi(f) due to non-linear tides.

    Parameters
    ----------
    amplitude: float
        Amplitude of effect
    n: float
        Growth dependence of effect
    m1: float
        Mass of component 1
    m2: float
        Mass of component 2

    Returns
    -------
    f_ref : float
        Reference frequency used to define A and n
    t_of_f_factor: float
        The constant factor needed to compute t(f)
    phi_of_f_factor: float
        The constant factor needed to compute phi(f)
    g      Y@g3333333@g      @g?g      @g      g      @g       )r)   r   r   ZG_SIr  r   )
	amplituder   r[   r\   r   Zmcr;   r   Zt_of_f_factorphi_of_f_factorr   r   r   nltides_coefs  s    
*$r  c             C   s   t | |||||\} }}}}}}t|j}t||||\}}	}
| |k}|
|  || | || d   ||< | |k}|
|  | | | || d   ||< t||S )a  Calculate the gravitational-wave phase shift bwtween
    f and f_coalescence = infinity due to non-linear tides.
    To compute the phase shift between e.g. f_low and f_isco,
    call this function twice and compute the difference.

    Parameters
    ----------
    f: float or numpy.array
        Frequency from which to compute phase
    f0: float or numpy.array
        Frequency that NL effects switch on
    amplitude: float or numpy.array
        Amplitude of effect
    n: float or numpy.array
        Growth dependence of effect
    m1: float or numpy.array
        Mass of component 1
    m2: float or numpy.array
        Mass of component 2

    Returns
    -------
    delta_phi: float or numpy.array
        Phase in radians
    g      @)r   r
   r   r!   r  r   )r	  r   r  r   r[   r\   r   Z	delta_phir   r]   r  r   r   r   r   nltides_gw_phase_difference  s    &&r  c       
      C   sj   t |||||\}}}}}}t|j|  } t| |||||}t|| }t||||||}	t|	| |S )a  Calculate the gravitational-wave phase shift bwtween
    f_low and f_isco due to non-linear tides.

    Parameters
    ----------
    f_low: float
        Frequency from which to compute phase. If the other
        arguments are passed as numpy arrays then the value
        of f_low is duplicated for all elements in the array
    f0: float or numpy.array
        Frequency that NL effects switch on
    amplitude: float or numpy.array
        Amplitude of effect
    n: float or numpy.array
        Growth dependence of effect
    m1: float or numpy.array
        Mass of component 1
    m2: float or numpy.array
        Mass of component 2

    Returns
    -------
    delta_phi: float or numpy.array
        Phase in radians
    )r   r
   r   r!   r  r  r   )
Zf_lowr   r  r   r[   r\   r   Zphi_lZf_iscoZphi_ir   r   r   nltides_gw_phase_diff_isco  s    r  mass2_from_mchirp_mass1rA   )F)FT)T)T)F)ra   )ra   ra   rg   )ra   ra   ra   rg   )r   )r   )r   F)r   r   )r=   r=   r   )r=   r=   r   )r=   r=   )r=   r=   )ra   ra   ra   ra   ra   ra   r   r   )ra   ra   ra   ra   ra   ra   r   r   )ra   ra   ra   ra   ra   ra   r   r   )s__doc__r   r
   r   Zpycbc.detectorr   Zpycbc.cosmologyrb   Zcoordinatesr   r   r   rn   r   ri   ZlibutilsZimport_optionalr   r   r   r   r   r    r$   r%   r&   r'   r(   r)   r,   r-   r/   r0   r2   r3   r4   r<   Z	vectorizer  r@   rA   rB   rC   rD   rE   rF   rI   rJ   rL   rM   rN   rO   rS   rT   rU   rV   r`   rf   rm   rr   rt   ru   r}   r   r   r   r   r   r   rw   rv   r   r   r   r   rx   r   r   r~   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r  r
  r  r  r  r  __all__r   r   r   r   <module>   s2  	
	


 
)




	
	

/
,		







%"
0&


,
&%  
Z  
0  
8***
