B
    d~$                 @   sL   d Z ddlZddlmZmZ ddlZddlmZ G dd dej	Z
dgZdS )zF
This modules provides classes for evaluating Gaussian distributions.
    N)erferfinv)boundedc                   sx   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 Zdd Zedd Z  ZS )Gaussiana	  A Gaussian distribution on the given parameters; the parameters are
    independent of each other.

    Bounds can be provided on each parameter, in which case the distribution
    will be a truncated Gaussian distribution.  The PDF of a truncated
    Gaussian distribution is given by:

    .. math::
        p(x|a, b, \mu,\sigma) = \frac{1}{\sqrt{2 \pi \sigma^2}}\frac{e^{- \frac{\left( x - \mu \right)^2}{2 \sigma^2}}}{\Phi(b|\mu, \sigma) - \Phi(a|\mu, \sigma)},

    where :math:`\mu` is the mean, :math:`\sigma^2` is the variance,
    :math:`a,b` are the bounds, and :math:`\Phi` is the cumulative distribution
    of an unbounded normal distribution, given by:

    .. math::
        \Phi(x|\mu, \sigma) = \frac{1}{2}\left[1 + \mathrm{erf}\left(\frac{x-\mu}{\sigma \sqrt{2}}\right)\right].

    Note that if :math:`[a,b) = [-\infty, \infty)`, this reduces to a standard
    Gaussian distribution.


    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.

    Parameters
    ----------
    \**params :
        The keyword arguments should provide the names of parameters and
        (optionally) some bounds, as either a tuple or a
        `boundaries.Bounds` instance. The mean and variance of each
        parameter can be provided by additional keyword arguments that have
        `_mean` and `_var` adding to the parameter name. For example,
        `foo=(-2,10), foo_mean=3, foo_var=2` would create a truncated Gaussian
        with mean 3 and variance 2, bounded between :math:`[-2, 10)`. If no
        mean or variance is provided, the distribution will have 0 mean and
        unit variance. If None is provided for the bounds, the distribution
        will be a normal, unbounded Gaussian (equivalent to setting the bounds
        to `[-inf, inf)`).

    Examples
    --------
    Create an unbounded Gaussian distribution with zero mean and unit variance:
    >>> dist = distributions.Gaussian(mass1=None)

    Create a bounded Gaussian distribution on :math:`[1,10)` with a mean of 3
    and a variance of 2:
    >>> dist = distributions.Gaussian(mass1=(1,10), mass1_mean=3, mass1_var=2)

    Create a bounded Gaussian distribution with the same parameters, but with
    cyclic boundary conditions:
    >>> dist = distributions.Gaussian(mass1=Bounds(1,10, cyclic=True), mass1_mean=3, mass1_var=2)
    Zgaussianc                s  i _ i _i _i _i _i _dd  D }dd  D }t fdd|D _t fdd|D _ttj	f   t
j t
   }t|rtdd|t
j t
   }t|rtdd|jtfd	d D  jtfd
d D  xj  D ]\}}j| }j| }|\}	}
tjjj|
||d dtjjj|	||d d }|tdtj | 9 }d| j|< tj| j|< dd|  j|< q6W d S )Nc             S   s   g | ]}| d r|qS )_mean)endswith).0p r
   i/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/pycbc/distributions/gaussian.py
<listcomp>\   s    z%Gaussian.__init__.<locals>.<listcomp>c             S   s   g | ]}| d r|qS )_var)r   )r   r	   r
   r
   r   r   ]   s    c                s"   g | ]}|d d   |gqS )N)pop)r   r	   )paramsr
   r   r   ^   s    c                s"   g | ]}|d d   |gqS )N)r   )r   r	   )r   r
   r   r   _   s    z#means provided for unknow params {}z, z"vars provided for unknow params {}c                s   g | ]}| j kr|d gqS )g        )r   )r   r	   )selfr
   r   r   m   s   c                s   g | ]}| j kr|d gqS )g      ?)r   )r   r	   )r   r
   r   r   o   s   g      ?)locscale   g      ?g      )_boundsr   r   Z_norm_lognorm_expnormdictsuperr   __init__setkeysany
ValueErrorformatjoinupdateitemsscipystatsZnormcdfnumpysqrtpilog)r   r   Z	mean_argsZvar_argsmissingr	   ZbndsZsigmasqmuabZinvnorm)	__class__)r   r   r   r   P   sB    

zGaussian.__init__c             C   s   | j S )N)r   )r   r
   r
   r   mean   s    zGaussian.meanc             C   s   | j S )N)r   )r   r
   r
   r   var   s    zGaussian.varc             C   s4   | j | }| j| }ddt|| d| d    S )z3The CDF of the normal distribution, without bounds.g      ?g      ?r   )r   r   r   )r   paramvaluer,   r1   r
   r
   r   
_normalcdf   s    

zGaussian._normalcdfc             C   sd   | j | \}}|tj kr(| ||}nd}|tjkrD| ||}nd}| ||}|| ||  S )z-Returns the CDF of the given parameter value.g        g      ?)r   r'   infr4   )r   r2   r3   r-   r.   phi_aphi_bZphi_xr
   r
   r   r&      s    
zGaussian.cdfc             C   s4   | j | }| j| }|d| d td| d   S )z;The inverse CDF of the normal distribution, without bounds.r   g      ?g      ?)r   r   r   )r   r2   r	   r,   r1   r
   r
   r   _normalcdfinv   s    

zGaussian._normalcdfinvc             C   sd   | j | \}}|tj kr(| ||}nd}|tjkrD| ||}nd}||||   }| ||S )z#Return inverse of the CDF.
        g        g      ?)r   r'   r5   r4   r8   )r   r2   r	   r-   r.   r6   r7   Z
adjusted_pr
   r
   r   _cdfinv_param   s    
zGaussian._cdfinv_paramc             K   s   t | jf |S )zReturns the pdf at the given values. The keyword arguments must
        contain all of parameters in self's params. Unrecognized arguments are
        ignored.
        )r'   exp_logpdf)r   kwargsr
   r
   r   _pdf   s    zGaussian._pdfc                s.    kr"t  fddjD 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.
        c                s6   g | ].}j | j|  | j|  d    qS )g       @)r   r   r   )r   r	   )r<   r   r
   r   r      s   z$Gaussian._logpdf.<locals>.<listcomp>N)sum_paramsr'   r5   )r   r<   r
   )r<   r   r   r;      s    zGaussian._logpdfc             C   s   t j| |||ddS )a  Returns a Gaussian distribution based on a configuration file. The
        parameters for the distribution are retrieved from the section titled
        "[`section`-`variable_args`]" in the config file.

        Boundary arguments should be provided in the same way as described in
        `get_param_bounds_from_config`. In addition, the mean and variance of
        each parameter can be specified by setting `{param}_mean` and
        `{param}_var`, respectively. For example, the following would create a
        truncated Gaussian distribution between 0 and 6.28 for a parameter
        called `phi` with mean 3.14 and variance 0.5 that is cyclic:

        .. code-block:: ini

            [{section}-{tag}]
            min-phi = 0
            max-phi = 6.28
            phi_mean = 3.14
            phi_var = 0.5
            cyclic =

        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
            `prior.VARARGS_DELIM`. These must appear in the "tag" part
            of the section header.

        Returns
        -------
        Gaussian
            A distribution instance from the pycbc.inference.prior module.
        F)Zbounds_required)r   Zbounded_from_config)clscpsectionZvariable_argsr
   r
   r   from_config   s    'zGaussian.from_config)__name__
__module____qualname____doc__namer   propertyr0   r1   r4   r&   r8   r9   r=   r;   classmethodrC   __classcell__r
   r
   )r/   r   r      s   5/r   )rG   r'   Zscipy.specialr   r   Zscipy.statsr$   Zpycbc.distributionsr   ZBoundedDistr   __all__r
   r
   r
   r   <module>   s    Y