B
    d(                 @   sl   d Z ddlZddlmZ ddlmZ ddlmZ ddlmZ G dd dej	Z
G d	d
 d
ejZdd
gZdS )z|This modules provides classes for evaluating distributions for mchirp and
q (i.e., mass ratio) from uniform component mass.
    N)interp1d)hyp2f1)	power_law)boundedc                   s&   e Zd ZdZdZd fdd	Z  ZS )MchirpfromUniformMass1Mass2a/  A distribution for chirp mass from uniform component mass +
    constraints given by chirp mass. This is a special case for UniformPowerLaw
    with index 1. For more details see UniformPowerLaw.

    The parameters (i.e. `**params`) are independent of each other. Instances
    of this class can be called like a function. By default, `logpdf` will be
    called, but this can be changed by setting the class's `__call__` method
    to its pdf method.

    Derivation for the probability density function:

    .. math::

        P(m_1,m_2)dm_1dm_2 = P(\mathcal{M}_c,q)d\mathcal{M}_cdq

    Where :math:`\mathcal{M}_c` is chirp mass and :math:`q` is mass ratio,
    :math:`m_1` and :math:`m_2` are component masses. The jacobian to transform
    chirp mass and mass ratio to component masses is

    .. math::

        \frac{\partial(m_1,m_2)}{\partial(\mathcal{M}_c,q)} = \
        \mathcal{M}_c \left(\frac{1+q}{q^3}\right)^{2/5}

    (https://github.com/gwastro/pycbc/blob/master/pycbc/transforms.py#L416.)

    Because :math:`P(m_1,m_2) = const`, then

    .. math::

        P(\mathcal{M}_c,q) = P(\mathcal{M}_c)P(q)\propto
        \mathcal{M}_c \left(\frac{1+q}{q^3}\right)^{2/5}`.

    Therefore,

    .. math::
        P(\mathcal{M}_c) \propto \mathcal{M}_c

    and

    .. math::
        P(q) \propto \left(\frac{1+q}{q^3}\right)^{2/5}

    Examples
    --------

    Generate 10000 random numbers from this distribution in [5,100]

    >>> from pycbc import distributions as dist
    >>> minmc = 5, maxmc = 100, size = 10000
    >>> mc = dist.MchirpfromUniformMass1Mass2(value=(minmc,maxmc)).rvs(size)

    The settings in the configuration file for pycbc_inference should be

    .. code-block:: ini

        [variable_params]
        mchirp =
        [prior-mchirp]
        name = mchirp_from_uniform_mass1_mass2
        min-mchirp = 10
        max-mchirp = 80

    Parameters
    ----------
    \**params :
        The keyword arguments should provide the names of parameters and their
        corresponding bounds, as either tuples or a `boundaries.Bounds`
        instance.
    Zmchirp_from_uniform_mass1_mass2   c                s   t t| jf ddi| d S )Ndimr   )superr   __init__)selfr   params)	__class__ e/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/pycbc/distributions/mass.pyr
   e   s    z$MchirpfromUniformMass1Mass2.__init__)r   )__name__
__module____qualname____doc__namer
   __classcell__r   r   )r   r   r      s   Fr   c                   sv   e Zd ZdZdZ fddZedd Zedd Zd	d
 Z	dd Z
dd Zdd ZdddZe fddZ  ZS )QfromUniformMass1Mass2a  A distribution for mass ratio (i.e., q) from uniform component mass
    + constraints given by q.

    The parameters (i.e. `**params`) are independent of each other. Instances
    of this class can be called like a function. By default, `logpdf` will be
    called, but this can be changed by setting the class's `__call__` method
    to its pdf method.

    For mathematical derivation see the documentation above in the class
    `MchirpfromUniformMass1Mass2`.

    Parameters
    ----------
    \**params :
        The keyword arguments should provide the names of parameters and their
        corresponding bounds, as either tuples or a `boundaries.Bounds`
        instance.

    Examples
    --------

    Generate 10000 random numbers from this distribution in [1,8]

    >>> from pycbc import distributions as dist
    >>> minq = 1, maxq = 8, size = 10000
    >>> q = dist.QfromUniformMass1Mass2(value=(minq,maxq)).rvs(size)

    Zq_from_uniform_mass1_mass2c          	      sv   t t| jf | d| _d| _xD| jD ]:}|  j| || j| d | || j| d    _q&W t	| j| _d S )Ng      ?g           r   )
r	   r   r
   _norm_lognorm_params
_cdf_param_boundsnumpylog)r   r   p)r   r   r   r
      s     zQfromUniformMass1Mass2.__init__c             C   s   | j S )z6float: The normalization of the multi-dimensional pdf.)r   )r   r   r   r   norm   s    zQfromUniformMass1Mass2.normc             C   s   | j S )z$float: The log of the normalization.)r   )r   r   r   r   lognorm   s    zQfromUniformMass1Mass2.lognormc                sb   x(| j D ]}|  krtd|qW  | krZ| jt fdd| j D  }t|S dS dS )zReturns the pdf at the given values. The keyword arguments must
        contain all of parameters in self's params. Unrecognized arguments are
        ignored.
        z&Missing parameter {} to construct pdf.c                s(   g | ] }d  |  d  | d  qS )g      ?g?g333333?r   ).0r   )kwargsr   r   
<listcomp>   s   z/QfromUniformMass1Mass2._pdf.<locals>.<listcomp>g        N)r   keys
ValueErrorformatr   r   prodfloat)r   r#   r   Zpdfr   )r#   r   _pdf   s    zQfromUniformMass1Mass2._pdfc             K   sP   x(| j D ]}|| krtd|qW || krDt| jf |S tj S dS )zReturns the log of the pdf at the given values. The keyword
        arguments must contain all of parameters in self's params. Unrecognized
        arguments are ignored.
        z)Missing parameter {} to construct logpdf.N)r   r%   r&   r'   r   r   r*   inf)r   r#   r   r   r   r   _logpdf   s    zQfromUniformMass1Mass2._logpdfc             C   s8   || j kr&d|d  tddd|  S td|dS )aF  >>> from sympy import *
           >>> x = Symbol('x')
           >>> integrate((1+x)**(2/5)/x**(6/5))
           Output:
                             _
                      -0.2  |_  /-0.4, -0.2 |    I*pi\
                -5.0*x    * |   |           | x*e    |
                           2  1 \   0.8     |        /
        g      gɿgٿg?z{} is not contructed yet.N)r   r   r&   r'   )r   paramvaluer   r   r   r      s    

z!QfromUniformMass1Mass2._cdf_paramc             C   s   t |dk  s$t |dk r,td|| jkr| j| d }| j| d }t j||ddd}t| |||ddd}|| ||| || | | || S td		|d
S )zxReturn the inverse cdf to map the unit interval to parameter bounds.
        Note that value should be uniform in [0,1].r   r   z4q_from_uniform_m1_m2 cdfinv requires input in [0,1].i  T)numZendpointZcubic)kindZbounds_errorz{} is not contructed yet.N)
r   arrayanyr&   r   r   Zlinspacer   r   r'   )r   r-   r.   lower_boundupper_boundZq_arrayZq_invcdf_interpr   r   r   _cdfinv_param   s     $

z$QfromUniformMass1Mass2._cdfinv_paramr   Nc             C   sj   |dk	r|t fg}ndd | jD }tj||d}x2|D ]*\}}tjjdd|d}| ||||< q8W |S )a  Gives a set of random values drawn from this distribution.

        Parameters
        ----------
        size : {1, int}
            The number of values to generate; default is 1.
        param : {None, string}
            If provided, will just return values for the given parameter.
            Otherwise, returns random values for each parameter.

        Returns
        -------
        structured array
            The random values in a numpy structured array. If a param was
            specified, the array will only have an element corresponding to the
            given parameter. Otherwise, the array will have an element for each
            parameter in self's params.
        Nc             S   s   g | ]}|t fqS r   )r)   )r"   r   r   r   r   r$      s    z.QfromUniformMass1Mass2.rvs.<locals>.<listcomp>)dtyper   r   )size)r)   r   r   Zzerosrandomuniformr5   )r   r7   r-   r6   Zarrr   _Zuniformcdfvaluer   r   r   rvs   s    zQfromUniformMass1Mass2.rvsc                s   t t| j|||ddS )a  Returns a distribution based on a configuration file. The parameters
        for the distribution are retrieved from the section titled
        "[`section`-`variable_args`]" in the config file.

        Example:

        .. code-block:: ini

            [variable_params]
            q =
            [prior-q]
            name = q_from_uniform_mass1_mass2
            min-q = 1
            max-q = 8

        Parameters
        ----------
        cp : pycbc.workflow.WorkflowConfigParser
            A parsed configuration file that contains the distribution
            options.
        section : str
            Name of the section in the configuration file.
        variable_args : str
            The names of the parameters for this distribution, separated by
            ``VARARGS_DELIM``. These must appear in the "tag" part
            of the section header.

        Returns
        -------
        QfromUniformMass1Mass2
            A distribution instance from the pycbc.distributions.bounded
        module.
        T)Zbounds_required)r	   r   from_config)clscpsectionZvariable_args)r   r   r   r<      s    #
z"QfromUniformMass1Mass2.from_config)r   N)r   r   r   r   r   r
   propertyr    r!   r*   r,   r   r5   r;   classmethodr<   r   r   r   )r   r   r   i   s   	
r   )r   r   Zscipy.interpolater   Zscipy.specialr   Zpycbc.distributionsr   r   ZUniformPowerLawr   ZBoundedDistr   __all__r   r   r   r   <module>   s   N <