B
    â‹dD)  ã               @   sN   d dl Z d dlZd dlZd dlmZmZ ddlmZmZ G dd„ dejƒZ	dS )é    N)ÚconversionsÚ
boundariesé   )ÚuniformÚboundedc                   sT   e Zd ZdZdZd‡ fdd	„	Z‡ fd
d„Zdd„ Zd‡ fdd„	Ze	dd„ ƒZ
‡  ZS )ÚUniformF0Taua²  A distribution uniform in QNM frequency and damping time.

    Constraints may be placed to exclude frequencies and damping times
    corresponding to specific masses and spins.

    To ensure a properly normalized pdf that accounts for the constraints
    on final mass and spin, a renormalization factor is calculated upon
    initialization. This is calculated numerically: f0 and tau are drawn
    randomly, then the norm is scaled by the fraction of points that yield
    final masses and spins within the constraints. The `norm_tolerance` keyword
    arguments sets the error on the estimate of the norm from this numerical
    method. If this value is too large, such that no points are found in
    the allowed region, a ValueError is raised.

    Parameters
    ----------
    f0 : tuple or boundaries.Bounds
        The range of QNM frequencies (in Hz).
    tau : tuple or boundaries.Bounds
        The range of QNM damping times (in s).
    final_mass : tuple or boundaries.Bounds, optional
        The range of final masses to allow. Default is [0,inf).
    final_spin : tuple or boundaries.Bounds, optional
        The range final spins to allow. Must be in [-0.996, 0.996], which is
        the default.
    rdfreq : str, optional
        Use the given string as the name for the f0 parameter. Default is 'f0'.
    damping_time : str, optional
        Use the given string as the name for the tau parameter. Default is
        'tau'.
    norm_tolerance : float, optional
        The tolerance on the estimate of the normalization. Default is 1e-3.
    norm_seed : int, optional
        Seed to use for the random number generator when estimating the norm.
        Default is 0. After the norm is estimated, the random number generator
        is set back to the state it was in upon initialization.

    Examples
    --------

    Create a distribution:

    >>> dist = UniformF0Tau(f0=(10., 2048.), tau=(1e-4,1e-2))

    Check that all random samples drawn from the distribution yield final
    masses > 1:

    >>> from pycbc import conversions
    >>> samples = dist.rvs(size=1000)
    >>> (conversions.final_mass_from_f0_tau(samples['f0'],
            samples['tau']) > 1.).all()
    True

    Create a distribution with tighter bounds on final mass and spin:

    >>> dist = UniformF0Tau(f0=(10., 2048.), tau=(1e-4,1e-2),
            final_mass=(20., 200.), final_spin=(0,0.996))

    Check that all random samples drawn from the distribution are in the
    final mass and spin constraints:

    >>> samples = dist.rvs(size=1000)
    >>> (conversions.final_mass_from_f0_tau(samples['f0'],
            samples['tau']) >= 20.).all()
    True
    >>> (conversions.final_mass_from_f0_tau(samples['f0'],
            samples['tau']) < 200.).all()
    True
    >>> (conversions.final_spin_from_f0_tau(samples['f0'],
            samples['tau']) >= 0.).all()
    True
    >>> (conversions.final_spin_from_f0_tau(samples['f0'],
            samples['tau']) < 0.996).all()
    True

    Zuniform_f0_tauNÚf0Útauçü©ñÒMbP?r   c	                s*  |d krt dƒ‚|d kr t dƒ‚|| _|| _||||i}	tt| ƒjf |	Ž |d kr\dtjf}|d krhd}tj	|d |d d| _
tj	|d |d d| _tj ¡ }
tj |¡ td|d	  ƒ}tt| ƒj|d
}tj |
¡ |  |¡ ¡ }|dkrút dƒ‚|  jt |¡t |¡ 7  _t | j¡| _d S )Nzmust provide a range for f0zmust provide a range for taug        )g¬Zd;ßï¿g¬Zd;ßï?r   r   )Z	min_boundZ	max_boundg      ð?é   )ÚsizezWthe normalization is < then the norm_tolerance; try again with a smaller nrom_tolerance)Ú
ValueErrorÚrdfreqÚdamping_timeÚsuperr   Ú__init__ÚnumpyÚinfr   ZBoundsÚfinal_mass_boundsÚfinal_spin_boundsÚrandomZ	get_stateÚseedÚintÚrvsZ	set_stateÚ_constraintsÚsumZ_lognormÚlogÚexpZ_norm)Úselfr   r	   Ú
final_massÚ
final_spinr   r   Únorm_toleranceÚ	norm_seedZparent_argsÚsZnsamplesÚdrawsZnum_in)Ú	__class__© úd/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/pycbc/distributions/qnm.pyr   h   s4    

zUniformF0Tau.__init__c                s&   t t| ƒ |¡}|r"||  |¡M }|S )N)r   r   Ú__contains__r   )r   ÚparamsÚisin)r%   r&   r'   r(      s    zUniformF0Tau.__contains__c       
   	   C   sª   || j  }|| j }t d| j ¡rJ| j  d¡}t|d ƒt|d ƒ }}nd\}}tjddB tj	||||d}tj
||||d}| j |¡| j |¡@ }	W d Q R X |	S )	Nzf_\d{3}Zf_r   r   )r   r   Úignore)Úinvalid)ÚlÚm)r   r   ÚreÚmatchÚstripr   r   Zerrstater   Zfinal_mass_from_f0_tauZfinal_spin_from_f0_taur   r(   r   )
r   r)   r   r	   Úmoder-   r.   ÚmfZsfr*   r&   r&   r'   r   “   s    


zUniformF0Tau._constraintsr   c       	         s„   t |ƒ}dd„ | jD ƒ}tj||d}|}d}xP|r~tt| ƒj|d}|  |¡}| ¡ }|| |||| …< ||7 }|| }q0W |S )a  Draw random samples from this distribution.

        Parameters
        ----------
        size : int, optional
            The number of draws to do. Default is 1.

        Returns
        -------
        array
            A structured array of the random draws.
        c             S   s   g | ]}|t f‘qS r&   )Úfloat)Ú.0Úpr&   r&   r'   ú
<listcomp>³   s    z$UniformF0Tau.rvs.<locals>.<listcomp>)Údtyper   )r   )	r   r)   r   Zzerosr   r   r   r   r   )	r   r   r8   ZarrÚ	remainingZkeepidxr$   ÚmaskZaddpts)r%   r&   r'   r   ¥   s    
zUniformF0Tau.rvsc          	   C   s  |}t | tj¡ƒ}t |||d¡}t |||d¡}| |d|¡rR| |d|¡}nd}| |d|¡rt| |d|¡}nd}|t ||gƒkstdƒ‚t |||d¡}	t |||d¡}
i }| |d|¡rØt	| |d|¡ƒ|d< | |d	|¡rüt
| |d	|¡ƒ|d	< | f |||	|
||d
œ|—ŽS )a  Initialize this class from a config file.

        Bounds on ``f0``, ``tau``, ``final_mass`` and ``final_spin`` should
        be specified by providing ``min-{param}`` and ``max-{param}``. If
        the ``f0`` or ``tau`` param should be renamed, ``rdfreq`` and
        ``damping_time`` should be provided; these must match
        ``variable_args``. If ``rdfreq`` and ``damping_time`` are not
        provided, ``variable_args`` are expected to be ``f0`` and ``tau``.

        Only ``min/max-f0`` and ``min/max-tau`` need to be provided.

        Example:

        .. code-block:: ini

            [{section}-f0+tau]
            name = uniform_f0_tau
            min-f0 = 10
            max-f0 = 2048
            min-tau = 0.0001
            max-tau = 0.010
            min-final_mass = 10

        Parameters
        ----------
        cp : pycbc.workflow.WorkflowConfigParser
            WorkflowConfigParser instance to read.
        section : str
            The name of the section to read.
        variable_args : str
            The name of the variable args. These should be separated by
            ``pycbc.VARARGS_DELIM``.

        Returns
        -------
        UniformF0Tau :
            This class initialized with the parameters provided in the config
            file.
        r   r	   r   r   z8variable args do not match rdfreq and damping_time namesr   r    r!   r"   )r   r	   r   r    r   r   )ÚsetÚsplitÚpycbcZVARARGS_DELIMr   Zget_param_bounds_from_configZhas_option_tagZget_opt_tagr   r4   r   )ÚclsÚcpÚsectionZvariable_argsÚtagr   r	   r   r   r   r    Z
extra_optsr&   r&   r'   Úfrom_configÀ   s6    )zUniformF0Tau.from_config)NNNNr   r	   r
   r   )r   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__Únamer   r(   r   r   ÚclassmethodrB   Ú__classcell__r&   r&   )r%   r'   r      s   L  #r   )
r/   r   r=   r   r   Ú r   r   ZUniformr   r&   r&   r&   r'   Ú<module>   s
   