B
    â‹dEI ã            6   @   sþ  d Z ddlZddl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	 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ƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZG dd „ d eƒZG d!d"„ d"eƒZG d#d$„ d$eƒZG d%d&„ d&eƒZG d'd(„ d(eƒZ G d)d*„ d*eƒZ!G d+d,„ d,eƒZ"G d-d.„ d.eƒZ#G d/d0„ d0eƒZ$G d1d2„ d2eƒZ%G d3d4„ d4eƒZ&G d5d6„ d6e&ƒZ'G d7d8„ d8e&ƒZ(G d9d:„ d:eƒZ)G d;d<„ d<eƒZ*G d=d>„ d>eƒZ+G d?d@„ d@e!ƒZ,G dAdB„ dBe"ƒZ-e#e_.e%e_.e&e_.e'e_.e(e_.e)e_.e*e_.ee+_.e,e!_.e-e"_.ej/eej/ee#j/e#ej/ee$j/e$ej/ee%j/e%ej/ee&j/e&ej/ee'j/e'ej/ee(j/e(ej/eej/ee)j/e)ej/ee*j/e*e+j/e+ej/ee!j/e!e,j/e,e"j/e"e-j/e-ej/ee j/e ej/eiZ0eƒ eƒ eej1ej2ej3ej4ej5ej6ƒeej7ej8ej9ej:ej;ej<ƒeƒ eƒ e+ƒ eƒ gZ=dCdD„ e=D ƒZ>e> ?e&ej1ej2ej3ej4ej5ej6ƒe&ej7ej8ej9ej:ej;ej<ƒg¡ e=e> Z@dQdEdF„ZAdRdHdI„ZBdSdJdK„ZCdLdM„ ZDdTdOdP„ZEdS )UzJ
This modules provides classes and functions for transforming parameters.
é    N)Úconversions)Úcoordinates)Ú	cosmology)Úrecord)Ú
parameters)ÚBounds)ÚVARARGS_DELIM)Újframe_to_l0framec               @   sj   e Zd ZdZdZdZg Zg Zdd„ Zdd„ Z	dd„ Z
d	d
„ Zdd„ Zdd„ Zedd„ ƒZeddd„ƒZdS )ÚBaseTransformz=A base class for transforming between two sets of parameters.Nc             C   s   t | jƒ| _t | jƒ| _d S )N)ÚsetÚ_inputsÚinputsÚ_outputsÚoutputs)Úself© r   ú]/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/pycbc/transforms.pyÚ__init__(   s    zBaseTransform.__init__c             C   s
   |   |¡S )N)Ú	transform)r   Úmapsr   r   r   Ú__call__,   s    zBaseTransform.__call__c             C   s   t dƒ‚dS )z0This function transforms from inputs to outputs.z
Not added.N)ÚNotImplementedError)r   r   r   r   r   r   /   s    zBaseTransform.transformc             C   s   t dƒ‚dS )zgThe inverse conversions of transform. This function transforms from
        outputs to inputs.
        z
Not added.N)r   )r   r   r   r   r   Úinverse_transform3   s    zBaseTransform.inverse_transformc             C   s   t dƒ‚dS )z6The Jacobian for the inputs to outputs transformation.z#Jacobian transform not implemented.N)r   )r   r   r   r   r   Újacobian9   s    zBaseTransform.jacobianc             C   s   t dƒ‚dS )z6The Jacobian for the outputs to inputs transformation.z#Jacobian transform not implemented.N)r   )r   r   r   r   r   Úinverse_jacobian=   s    zBaseTransform.inverse_jacobianc          	      s    t | tjƒrtˆ  ¡ }‡ fdd„|D ƒ}xHt||ƒD ]:\}}y|  |g|g¡} W q2 tk
rj   || |< Y q2X q2W | S t | tƒr”|  ¡ }| 	ˆ ¡ |S t
dƒ‚dS )aÓ  This function takes the returned dict from `transform` and converts
        it to the same datatype as the input.

        Parameters
        ----------
        old_maps : {FieldArray, dict}
            The mapping object to add new maps to.
        new_maps : dict
            A dict with key as parameter name and value is numpy.array.

        Returns
        -------
        {FieldArray, dict}
            The old_maps object with new keys from new_maps.
        c                s   g | ]}ˆ | ‘qS r   r   )Ú.0Úkey)Únew_mapsr   r   ú
<listcomp>V   s    z/BaseTransform.format_output.<locals>.<listcomp>z&Input type must be FieldArray or dict.N)Ú
isinstancer   Ú
FieldArrayÚkeysÚzipÚ
add_fieldsÚ
ValueErrorÚdictÚcopyÚupdateÚ	TypeError)Zold_mapsr   r!   Úvaluesr   ÚvalsÚoutr   )r   r   Úformat_outputA   s    

zBaseTransform.format_outputc          	   C   sô   |}|dkrg }|dkri }n|  ¡ }t| t¡ƒ}dg| t| ¡ ƒ }i }xd| d ||g¡¡D ]L}	|	|krrqd| ||	|¡}
yt	|
ƒ}
W n t
k
r    Y nX | |	|
i¡ qdW | |¡ | f |Ž}||j tƒ ksè|j| tƒ krðt
dƒ‚|S )a­  Initializes a transform from the given section.

        Parameters
        ----------
        cp : pycbc.workflow.WorkflowConfigParser
            A parsed configuration file that contains the transform options.
        section : str
            Name of the section in the configuration file.
        outputs : str
            The names of the parameters that are output by this transformation,
            separated by `VARARGS_DELIM`. These must appear in the "tag" part
            of the section header.
        skip_opts : list, optional
            Do not read options in the given list.
        additional_opts : dict, optional
            Any additional arguments to pass to the class. If an option is
            provided that also exists in the config file, the value provided
            will be used instead of being read from the file.

        Returns
        -------
        cls
            An instance of the class.
        NÚnameú-z:outputs of class do not match outputs specified in section)r&   r   Úsplitr   Úlistr!   ÚoptionsÚjoinÚget_opt_tagÚfloatr$   r'   r   )ÚclsÚcpÚsectionr   Ú	skip_optsÚadditional_optsÚtagZspecial_argsÚ
extra_argsÚoptÚvalr+   r   r   r   Úfrom_configh   s0    

 zBaseTransform.from_config)NN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r-   Úinverser   r   r   r   r   r   r   r   Ústaticmethodr,   Úclassmethodr>   r   r   r   r   r
       s   'r
   c               @   sT   e Zd ZdZdZddd„Zddd„Zd	d
„ Zdd„ Zdd„ Z	dd„ Z
edd„ ƒZdS )ÚCustomTransforma  Allows for any transform to be defined.

    Parameters
    ----------
    input_args : (list of) str
        The names of the input parameters.
    output_args : (list of) str
        The names of the output parameters.
    transform_functions : dict
        Dictionary mapping input args to a string giving a function call;
        e.g., ``{'q': 'q_from_mass1_mass2(mass1, mass2)'}``.
    jacobian : str, optional
        String giving a jacobian function. The function must be in terms of
        the input arguments.

    Examples
    --------
    Create a custom transform that converts mass1, mass2 to mtotal, q:

    >>> t = transforms.CustomTransform(['mass1', 'mass2'], ['mtotal', 'q'], {'mtotal': 'mass1+mass2', 'q': 'mass1/mass2'}, '(mass1 + mass2) / mass2**2')

    Evaluate a pair of masses:

    >>> t.transform({'mass1': 10., 'mass2': 5.})
    {'mass1': 10.0, 'mass2': 5.0, 'mtotal': 15.0, 'q': 2.0}

    The Jacobian for the same pair of masses:

    >>> t.jacobian({'mass1': 10., 'mass2': 5.})
    0.59999999999999998

    ZcustomNc             C   sL   t |tƒr|g}t |tƒr |g}t|ƒ| _t|ƒ| _|| _|| _|  ¡  d S )N)r   Ústrr   r   r   Útransform_functionsÚ	_jacobianÚ_createscratch)r   Z
input_argsZoutput_argsrH   r   r   r   r   r   Ç   s    



zCustomTransform.__init__é   c             C   s    t j|dd„ | jD ƒd| _dS )z3Creates a scratch FieldArray to use for transforms.c             S   s   g | ]}|t f‘qS r   )r4   )r   Úpr   r   r   r   Ù   s    z2CustomTransform._createscratch.<locals>.<listcomp>)ÚdtypeN)r   r    r   Ú_scratch)r   Úshaper   r   r   rJ   Ö   s    zCustomTransform._createscratchc             C   s¢   y*x$| j D ]}|| | j| dd…< q
W W nr tk
rœ   |t| j ƒd  }t|tjƒr`|j}nt|ƒ}|  	|¡ x$| j D ]}|| | j| dd…< qzW Y nX dS )z¹Copies the data in maps to the scratch space.

        If the maps contain arrays that are not the same shape as the scratch
        space, a new scratch space will be created.
        Nr   )
r   rN   r$   r0   r   ÚnumpyÚndarrayrO   ÚlenrJ   )r   r   rL   ÚinvalsrO   r   r   r   Ú_copytoscratchÜ   s    
zCustomTransform._copytoscratchc             C   s6   |t | jƒd  }t|tjt fƒs(d}n
tddƒ}|S )z9Determines how to slice the scratch for returning values.r   N)r0   r   r   rP   rQ   Úslice)r   r   rS   Úgetslicer   r   r   Ú	_getsliceò   s
    
zCustomTransform._getslicec                sL   ˆj dkrtdƒ‚ˆ |¡ ˆ |¡‰ ‡ ‡fdd„ˆj  ¡ D ƒ}ˆ ||¡S )ax  Applies the transform functions to the given maps object.

        Parameters
        ----------
        maps : dict, or FieldArray

        Returns
        -------
        dict or FieldArray
            A map object containing the transformed variables, along with the
            original variables. The type of the output will be the same as the
            input.
        Nz!no transform function(s) providedc                s    i | ]\}}ˆj | ˆ  |“qS r   )rN   )r   rL   Úfunc)rV   r   r   r   ú
<dictcomp>  s   z-CustomTransform.transform.<locals>.<dictcomp>)rH   r   rT   rW   Úitemsr,   )r   r   r+   r   )rV   r   r   r   û   s    


zCustomTransform.transformc             C   sF   | j d krtdƒ‚|  |¡ | j| j  }t|tjƒrB||  |¡ }|S )Nzno jacobian provided)rI   r   rT   rN   r   rP   rQ   rW   )r   r   r+   r   r   r   r     s    

zCustomTransform.jacobianc             C   s”   |}t | t¡ƒ}ttj| |d|¡ d¡ƒ}i }x"|D ]}| |||¡}|||< q8W d ||g¡}	| |	d¡r€| |d|¡}
nd}
| ||||
dS )aL  Loads a CustomTransform from the given config file.

        Example section:

        .. code-block:: ini

            [{section}-outvar1+outvar2]
            name = custom
            inputs = inputvar1, inputvar2
            outvar1 = func1(inputs)
            outvar2 = func2(inputs)
            jacobian = func(inputs)
        r   ú,r.   r   N)r   )	r   r/   r   ÚmaprG   Ústripr3   r2   Ú
has_option)r5   r6   r7   r   r:   r   rH   ÚvarrX   Úsr   r   r   r   r>      s    
zCustomTransform.from_config)N)rK   )r?   r@   rA   rB   r-   r   rJ   rT   rW   r   r   rE   r>   r   r   r   r   rF   £   s    

	
rF   c                   sF   e Zd ZdZdZd‡ fdd„	Zdd„ Zdd	„ Zd
d„ Zdd„ Z	‡  Z
S )ÚMchirpQToMass1Mass2z7Converts chirp mass and mass ratio to component masses.Zmchirp_q_to_mass1_mass2Nc                s~   |d krt j}|d krt j}|d kr*t j}|d kr8t j}|| _|| _|| _|| _| j| jg| _	| j| jg| _
tt| ƒ ¡  d S )N)r   Úmass1Úmass2ÚmchirpÚqÚmass1_paramÚmass2_paramÚmchirp_paramÚq_paramr   r   Úsuperra   r   )r   rf   rg   rh   ri   )Ú	__class__r   r   r   O  s    zMchirpQToMass1Mass2.__init__c             C   sL   i }t  || j || j ¡|| j< t  || j || j ¡|| j< |  ||¡S )aÕ  This function transforms from chirp mass and mass ratio to component
        masses.

        Parameters
        ----------
        maps : a mapping object

        Examples
        --------
        Convert a dict of numpy.array:

        >>> import numpy
        >>> from pycbc import transforms
        >>> t = transforms.MchirpQToMass1Mass2()
        >>> t.transform({'mchirp': numpy.array([10.]), 'q': numpy.array([2.])})
        {'mass1': array([ 16.4375183]), 'mass2': array([ 8.21875915]),
         'mchirp': array([ 10.]), 'q': array([ 2.])}

        Returns
        -------
        out : dict
            A dict with key as parameter name and value as numpy.array or float
            of transformed values.
        )r   Zmass1_from_mchirp_qrh   ri   rf   Zmass2_from_mchirp_qrg   r,   )r   r   r+   r   r   r   r   b  s    zMchirpQToMass1Mass2.transformc             C   sD   i }|| j  }|| j }t ||¡|| j< || || j< |  ||¡S )aÛ  This function transforms from component masses to chirp mass and
        mass ratio.

        Parameters
        ----------
        maps : a mapping object

        Examples
        --------
        Convert a dict of numpy.array:

        >>> import numpy
        >>> from pycbc import transforms
        >>> t = transforms.MchirpQToMass1Mass2()
        >>> t.inverse_transform({'mass1': numpy.array([16.4]), 'mass2': numpy.array([8.2])})
            {'mass1': array([ 16.4]), 'mass2': array([ 8.2]),
             'mchirp': array([ 9.97717521]), 'q': 2.0}

        Returns
        -------
        out : dict
            A dict with key as parameter name and value as numpy.array or float
            of transformed values.
        )rf   rg   r   Úmchirp_from_mass1_mass2rh   ri   r,   )r   r   r+   Úm1Úm2r   r   r   r   „  s    

z%MchirpQToMass1Mass2.inverse_transformc             C   s,   || j  }|| j }|d| |d  d  S )zWReturns the Jacobian for transforming mchirp and q to mass1 and
        mass2.
        g      ð?g      @gš™™™™™Ù?)rh   ri   )r   r   rd   re   r   r   r   r   ¤  s    

zMchirpQToMass1Mass2.jacobianc             C   s(   || j  }|| j }t ||¡|d  S )zWReturns the Jacobian for transforming mass1 and mass2 to
        mchirp and q.
        g       @)rf   rg   r   rl   )r   r   rm   rn   r   r   r   r   ¬  s    

z$MchirpQToMass1Mass2.inverse_jacobian)NNNN)r?   r@   rA   rB   r-   r   r   r   r   r   Ú__classcell__r   r   )rk   r   ra   J  s   " ra   c               @   sL   e Zd ZdZdZejejgZej	ej
gZdd„ Zdd„ Zdd„ Zd	d
„ ZdS )ÚMchirpEtaToMass1Mass2zAConverts chirp mass and symmetric mass ratio to component masses.Zmchirp_eta_to_mass1_mass2c             C   sL   i }t  |tj |tj ¡|tj< t  |tj |tj ¡|tj< |  ||¡S )aé  This function transforms from chirp mass and symmetric mass ratio to
        component masses.

        Parameters
        ----------
        maps : a mapping object

        Examples
        --------
        Convert a dict of numpy.array:

        >>> import numpy
        >>> from pycbc import transforms
        >>> t = transforms.MchirpEtaToMass1Mass2()
        >>> t.transform({'mchirp': numpy.array([10.]), 'eta': numpy.array([0.25])})
        {'mass1': array([ 16.4375183]), 'mass2': array([ 8.21875915]),
         'mchirp': array([ 10.]), 'eta': array([ 0.25])}

        Returns
        -------
        out : dict
            A dict with key as parameter name and value as numpy.array or float
            of transformed values.
        )	r   Úmass1_from_mchirp_etar   rd   Úetarb   Úmass2_from_mchirp_etarc   r,   )r   r   r+   r   r   r   r   ¼  s    zMchirpEtaToMass1Mass2.transformc             C   sH   i }|t j }|t j }t ||¡|t j< t ||¡|t j< |  ||¡S )aæ  This function transforms from component masses to chirp mass and
        symmetric mass ratio.

        Parameters
        ----------
        maps : a mapping object

        Examples
        --------
        Convert a dict of numpy.array:

        >>> import numpy
        >>> from pycbc import transforms
        >>> t = transforms.MchirpQToMass1Mass2()
        >>> t.inverse_transform({'mass1': numpy.array([8.2]), 'mass2': numpy.array([8.2])})
            {'mass1': array([ 8.2]), 'mass2': array([ 8.2]),
             'mchirp': array([ 9.97717521]), 'eta': 0.25}

        Returns
        -------
        out : dict
            A dict with key as parameter name and value as numpy.array or float
            of transformed values.
        )	r   rb   rc   r   rl   rd   Úeta_from_mass1_mass2rr   r,   )r   r   r+   rm   rn   r   r   r   r   Þ  s    

z'MchirpEtaToMass1Mass2.inverse_transformc             C   sD   |t j }|t j }t ||¡}t ||¡}|||  || d  S )zYReturns the Jacobian for transforming mchirp and eta to mass1 and
        mass2.
        é   )r   rd   rr   r   rq   rs   )r   r   rd   rr   rm   rn   r   r   r   r   þ  s
    

zMchirpEtaToMass1Mass2.jacobianc             C   s<   |t j }|t j }t ||¡}t ||¡}d| |d  S )zYReturns the Jacobian for transforming mass1 and mass2 to
        mchirp and eta.
        g      ð¿g333333ó?)r   rb   rc   r   rl   rt   )r   r   rm   rn   rd   rr   r   r   r   r     s
    

z&MchirpEtaToMass1Mass2.inverse_jacobianN)r?   r@   rA   rB   r-   r   rd   rr   r   rb   rc   r   r   r   r   r   r   r   r   r   rp   µ  s   " 
rp   c               @   sR   e Zd ZdZdZejejgZej	gZ
ddd„Zdd„ Zdd	„ Zd
d„ Zdd„ ZdS )ÚChirpDistanceToDistancezEConverts chirp distance to luminosity distance, given the chirp mass.Zchirp_distance_to_distanceçffffffö?c             C   s"   t | jƒ| _t | jƒ| _|| _d S )N)r   r   r   r   r   Úref_mass)r   rx   r   r   r   r     s    z ChirpDistanceToDistance.__init__c             C   s4   i }t j|tj |tj | jd|tj< |  ||¡S )aß  This function transforms from chirp distance to luminosity distance,
        given the chirp mass.

        Parameters
        ----------
        maps : a mapping object

        Examples
        --------
        Convert a dict of numpy.array:

        >>> import numpy as np
        >>> from pycbc import transforms
        >>> t = transforms.ChirpDistanceToDistance()
        >>> t.transform({'chirp_distance': np.array([40.]), 'mchirp': np.array([1.2])})
        {'mchirp': array([ 1.2]), 'chirp_distance': array([ 40.]), 'distance': array([ 39.48595679])}

        Returns
        -------
        out : dict
            A dict with key as parameter name and value as numpy.array or float
            of transformed values.
        )rx   )r   Z#distance_from_chirp_distance_mchirpr   Úchirp_distancerd   rx   Údistancer,   )r   r   r+   r   r   r   r     s    z!ChirpDistanceToDistance.transformc             C   s4   i }t j|tj |tj | jd|tj< |  ||¡S )aá  This function transforms from luminosity distance to chirp distance,
        given the chirp mass.

        Parameters
        ----------
        maps : a mapping object

        Examples
        --------
        Convert a dict of numpy.array:

        >>> import numpy as np
        >>> from pycbc import transforms
        >>> t = transforms.ChirpDistanceToDistance()
        >>> t.inverse_transform({'distance': np.array([40.]), 'mchirp': np.array([1.2])})
        {'distance': array([ 40.]), 'chirp_distance': array([ 40.52073522]), 'mchirp': array([ 1.2])}

        Returns
        -------
        out : dict
            A dict with key as parameter name and value as numpy.array or float
            of transformed values.
        )rx   )r   ry   r   rz   rd   rx   r,   )r   r   r+   r   r   r   r   ?  s     z)ChirpDistanceToDistance.inverse_transformc             C   s   d}|d }d| j  | d S )zsReturns the Jacobian for transforming chirp distance to
        luminosity distance, given the chirp mass.
        gffffffö?rd   g áÛÚŒÛë?g«ªªªªªê¿)rx   )r   r   rx   rd   r   r   r   r   ]  s    z ChirpDistanceToDistance.jacobianc             C   s   d}|d }d| j  | d S )zsReturns the Jacobian for transforming luminosity distance to
        chirp distance, given the chirp mass.
        gffffffö?rd   g áÛÚŒÛë?g«ªªªªªê?)rx   )r   r   rx   rd   r   r   r   r   e  s    z(ChirpDistanceToDistance.inverse_jacobianN)rw   )r?   r@   rA   rB   r-   r   ry   rd   r   rz   r   r   r   r   r   r   r   r   r   r   rv     s   
 rv   c                   sz   e Zd ZdZdZejejejej	ej
ejejejejejdgZejejejej	ej
ejejgZ‡ fdd„Zdd„ Z‡  ZS )ÚAlignTotalSpinzgConverts angles from total angular momentum J frame to orbital angular
     momentum L (waveform) frameZalign_total_spinÚphi_refc                s*   t | jƒ| _t | jƒ| _tt| ƒ ¡  d S )N)r   r   r   r   r   rj   r{   r   )r   )rk   r   r   r   {  s    zAlignTotalSpin.__init__c                sN  t ˆ tƒrtjjf ˆ Ž‰ ‡ fdd„| jD ƒ}ˆ jt t	ˆ ƒ¡gt	|ƒ |d}xú|D ]ò}t
dd„ |tj |tj |tj |tj gD ƒƒs6t |tj |tj |tj ¡\}}}t |tj |tj |tj ¡\}}	}
t|tj |tj |tj |d |tj tj||||
||	 d}x,|D ]}|| ||< qW qT|tj |tj< qTW |S )a\  
        Rigidly rotate binary so that the total angular momentum has the given
        inclination (iota) instead of the orbital angular momentum. Return
        the new inclination, s1, and s2. s1 and s2 are dimensionless spin.
        Note: the spins are assumed to be given in the frame defined by the
        orbital angular momentum.
        c                s   g | ]}|ˆ j kr|‘qS r   )Ú
fieldnames)r   Ún)r   r   r   r   ‹  s    z,AlignTotalSpin.transform.<locals>.<listcomp>)Únamesc             s   s   | ]}|d kV  qdS )g        Nr   )r   r`   r   r   r   ú	<genexpr>  s    z+AlignTotalSpin.transform.<locals>.<genexpr>r|   )ZphirefÚthetajnZphijlÚspin1_aÚspin2_aÚspin1_polarÚspin2_polarZspin12_deltaphi)r   r%   r   r    Zfrom_kwargsr   r#   rP   ZzerosrR   Úallr   Úspin1xÚspin1yÚspin2xÚspin2yr   Úcartesian_to_sphericalÚspin1zÚspin2zr	   rb   rc   Úf_refr   ÚpiÚinclination)r   r   Z	newfieldsZnewmapsÚitemZs1_aZs1_azZs1_polZs2_aZs2_azZs2_polr+   r   r   )r   r   r   €  s>    	


zAlignTotalSpin.transform)r?   r@   rA   rB   r-   r   r   r‡   rˆ   rŒ   r‰   rŠ   r   rb   rc   rŽ   r   r   r   r   r   ro   r   r   )rk   r   r{   n  s   
r{   c                   s4   e Zd ZdZdZ‡ fdd„Zdd„ Zdd„ Z‡  ZS )	ÚSphericalToCartesiana¤  Converts spherical coordinates to cartesian.

    Parameters
    ----------
    x : str
        The name of the x parameter.
    y : str
        The name of the y parameter.
    z : str
        The name of the z parameter.
    radial : str
        The name of the radial parameter.
    azimuthal : str
        The name of the azimuthal angle parameter.
    polar : str
        The name of the polar angle parameter.
    Úspherical_to_cartesianc                sZ   || _ || _|| _|| _|| _|| _| j| j| jg| _| j | j| jg| _tt	| ƒ 
¡  d S )N)ÚxÚyÚzÚradialÚpolarÚ	azimuthalr   r   rj   r’   r   )r   r”   r•   r–   r—   r™   r˜   )rk   r   r   r   Æ  s    zSphericalToCartesian.__init__c       	      C   sT   | j }| j}| j}t || || || ¡\}}}| j|| j|| j|i}|  ||¡S )a€  This function transforms from spherical to cartesian spins.

        Parameters
        ----------
        maps : a mapping object

        Examples
        --------
        Convert a dict of numpy.array:

        >>> import numpy
        >>> from pycbc import transforms
        >>> t = transforms.SphericalToCartesian('x', 'y', 'z',
                                                'a', 'phi', 'theta')
        >>> t.transform({'a': numpy.array([0.1]), 'phi': numpy.array([0.1]),
                        'theta': numpy.array([0.1])})
            {'a': array([ 0.1]), 'phi': array([ 0.1]), 'theta': array([ 0.1]),
             'x': array([ 0.00993347]), 'y': array([ 0.00099667]),
             'z': array([ 0.09950042])}

        Returns
        -------
        out : dict
            A dict with key as parameter name and value as numpy.array or float
            of transformed values.
        )	r—   r™   r˜   r   r“   r”   r•   r–   r,   )	r   r   ÚaÚazÚpor”   r•   r–   r+   r   r   r   r   Ñ  s     zSphericalToCartesian.transformc       	      C   sT   | j }| j}| j}t || || || ¡\}}}| j|| j|| j|i}|  ||¡S )a2  This function transforms from cartesian to spherical spins.

        Parameters
        ----------
        maps : a mapping object

        Returns
        -------
        out : dict
            A dict with key as parameter name and value as numpy.array or float
            of transformed values.
        )	r”   r•   r–   r   r‹   r—   r™   r˜   r,   )	r   r   r”   r•   r–   rš   r›   rœ   r+   r   r   r   r   ó  s     z&SphericalToCartesian.inverse_transform)	r?   r@   rA   rB   r-   r   r   r   ro   r   r   )rk   r   r’   ±  s
   "r’   c                   s$   e Zd ZdZdZ‡ fdd„Z‡  ZS )ÚSphericalSpin1ToCartesianSpin1aE  Converts spherical spin parameters (radial and two angles) to
    catesian spin parameters. This class only transforms spsins for the first
    component mass.

    **Deprecation Warning:** This will be removed in a future update. Use
    :py:class:`SphericalToCartesian` with spin-parameter names passed in
    instead.
    Z$spherical_spin_1_to_cartesian_spin_1c                s4   t  d | jtj¡¡ tt| ƒ dddddd¡ d S )Nz´Deprecation warning: the {} transform will be removed in a future update. Please use {} instead, passing spin1x, spin1y, spin1z, spin1_a, spin1_azimuthal, spin1_polar as arguments.r‡   rˆ   rŒ   r‚   Úspin1_azimuthalr„   )ÚloggingÚwarningÚformatr-   r’   rj   r   r   )r   )rk   r   r   r     s    
z'SphericalSpin1ToCartesianSpin1.__init__)r?   r@   rA   rB   r-   r   ro   r   r   )rk   r   r     s   r   c                   s$   e Zd ZdZdZ‡ fdd„Z‡  ZS )ÚSphericalSpin2ToCartesianSpin2aE  Converts spherical spin parameters (radial and two angles) to
    catesian spin parameters. This class only transforms spsins for the first
    component mass.

    **Deprecation Warning:** This will be removed in a future update. Use
    :py:class:`SphericalToCartesian` with spin-parameter names passed in
    instead.
    Z$spherical_spin_2_to_cartesian_spin_2c                s4   t  d | jtj¡¡ tt| ƒ dddddd¡ d S )Nz´Deprecation warning: the {} transform will be removed in a future update. Please use {} instead, passing spin2x, spin2y, spin2z, spin2_a, spin2_azimuthal, spin2_polar as arguments.r‰   rŠ   r   rƒ   Úspin2_azimuthalr…   )rŸ   r    r¡   r-   r’   rj   r¢   r   )r   )rk   r   r   r   /  s    
z'SphericalSpin2ToCartesianSpin2.__init__)r?   r@   rA   rB   r-   r   ro   r   r   )rk   r   r¢   #  s   r¢   c               @   s0   e Zd ZdZdZdZejgZej	gZ
dd„ ZdS )ÚDistanceToRedshiftzConverts distance to redshift.Zdistance_to_redshiftNc             C   s"   t jt |t j ¡i}|  ||¡S )ak  This function transforms from distance to redshift.

        Parameters
        ----------
        maps : a mapping object

        Examples
        --------
        Convert a dict of numpy.array:

        >>> import numpy
        >>> from pycbc import transforms
        >>> t = transforms.DistanceToRedshift()
        >>> t.transform({'distance': numpy.array([1000])})
            {'distance': array([1000]), 'redshift': 0.19650987609144363}

        Returns
        -------
        out : dict
            A dict with key as parameter name and value as numpy.array or float
            of transformed values.
        )r   Úredshiftr   rz   r,   )r   r   r+   r   r   r   r   F  s    zDistanceToRedshift.transform)r?   r@   rA   rB   r-   rC   r   rz   r   r¥   r   r   r   r   r   r   r¤   >  s   r¤   c               @   sJ   e Zd ZdZdZejejejdgZ	ejejej
ejgZdd„ Zdd„ ZdS )	ÚAlignedMassSpinToCartesianSpinz7Converts mass-weighted spins to cartesian z-axis spins.Z#aligned_mass_spin_to_cartesian_spinÚchi_ac             C   sd   |t j }|t j }i }t |||t j |d ¡|t j< t |||t j |d ¡|t j< |  	||¡S )ae  This function transforms from aligned mass-weighted spins to
        cartesian spins aligned along the z-axis.

        Parameters
        ----------
        maps : a mapping object

        Returns
        -------
        out : dict
            A dict with key as parameter name and value as numpy.array or float
            of transformed values.
        r§   )
r   rb   rc   r   Z%spin1z_from_mass1_mass2_chi_eff_chi_aÚchi_effrŒ   Z%spin2z_from_mass1_mass2_chi_eff_chi_ar   r,   )r   r   rb   rc   r+   r   r   r   r   m  s    

z(AlignedMassSpinToCartesianSpin.transformc          	   C   sZ   |t j }|t j }|t j }|t j }t jt ||||¡dt ||||¡i}|  ||¡S )a…  This function transforms from component masses and cartesian spins
        to mass-weighted spin parameters aligned with the angular momentum.

        Parameters
        ----------
        maps : a mapping object

        Returns
        -------
        out : dict
            A dict with key as parameter name and value as numpy.array or float
            of transformed values.
        r§   )	r   rb   rŒ   rc   r   r¨   r   r§   r,   )r   r   rb   rŒ   rc   r   r+   r   r   r   r   †  s    



z0AlignedMassSpinToCartesianSpin.inverse_transformN)r?   r@   rA   rB   r-   r   rb   rc   r¨   r   rŒ   r   r   r   r   r   r   r   r   r¦   a  s   r¦   c               @   sT   e Zd ZdZdZejejddddgZejejej	ej
ejejgZdd„ Zd	d
„ ZdS )Ú!PrecessionMassSpinToCartesianSpinz:Converts mass-weighted spins to cartesian x-y plane spins.Z&precession_mass_spin_to_cartesian_spinÚxi1Úxi2Úphi_aÚphi_sc             C   sè  t  |d |d ¡}t  |d |d ¡}t  |d |d |d |d ¡}t  |d |d |d |d ¡}t  ||d |d ¡}t  ||d |d ¡}t  ||||d |d ¡}t  ||||d |d ¡}	i }
t	|t
jƒrxtt
j|d |d gƒ\}}||k}||k }t
 || || f¡|
tj< t
 || |	| f¡|
tj< t
 || || f¡|
tj< t
 || || f¡|
tj< nd|d |d kr´||
tj< ||
tj< ||
tj< |	|
tj< n(||
tj< |	|
tj< ||
tj< ||
tj< |  ||
¡S )aU  This function transforms from mass-weighted spins to caretsian spins
        in the x-y plane.

        Parameters
        ----------
        maps : a mapping object

        Returns
        -------
        out : dict
            A dict with key as parameter name and value as numpy.array or float
            of transformed values.
        rb   rc   rª   r«   r¬   r­   )r   Zprimary_massZsecondary_massZprimary_spinZsecondary_spinZspin1x_from_xi1_phi_a_phi_sZspin1y_from_xi1_phi_a_phi_sZ'spin2x_from_mass1_mass2_xi2_phi_a_phi_sZ'spin2y_from_mass1_mass2_xi2_phi_a_phi_sr   rP   rQ   r\   ÚarrayÚconcatenater   r‡   rˆ   r‰   rŠ   r,   )r   r   Zm_pZm_sZxi_pZxi_sZspinx_pZspiny_pZspinx_sZspiny_sr+   rb   rc   Úmask_mass1_gte_mass2Úmask_mass1_lt_mass2r   r   r   r   ¯  sJ    






z+PrecessionMassSpinToCartesianSpin.transformc       	   	   C   s  i }t  |tj |tj |tj |tj |tj |tj ¡}t  	|tj |tj |tj |tj |tj |tj ¡}t  
|tj |tj |tj |tj |tj |tj ¡|d< t  |tj |tj |tj |tj ¡|d< t|tjƒrPttj|tj |tj gƒ\}}||k}||k }t || || f¡|d< t || || f¡|d< n4|d |d krt||d< ||d< n||d< ||d< |  ||¡S )a‹  This function transforms from component masses and cartesian spins to
        mass-weighted spin parameters perpendicular with the angular momentum.

        Parameters
        ----------
        maps : a mapping object

        Returns
        -------
        out : dict
            A dict with key as parameter name and value as numpy.array or float
            of transformed values.
        r¬   r­   rª   r«   rb   rc   )r   Z
primary_xir   rb   rc   r‡   rˆ   r‰   rŠ   Zsecondary_xir¬   r­   r   rP   rQ   r\   r®   r¯   r,   )	r   r   r+   rª   r«   rb   rc   r°   r±   r   r   r   r   ù  sT    
z3PrecessionMassSpinToCartesianSpin.inverse_transformN)r?   r@   rA   rB   r-   r   rb   rc   r   r‡   rˆ   r‰   rŠ   r   r   r   r   r   r   r   r©      s   Jr©   c               @   s>   e Zd ZdZdZejejejej	ej
ejgZdgZdd„ ZdS )ÚCartesianSpinToChiPz$Converts cartesian spins to `chi_p`.Úcartesian_spin_to_chi_pÚchi_pc          	   C   sL   i }t  |tj |tj |tj |tj |tj |tj ¡|d< |  	||¡S )a•  This function transforms from component masses and caretsian spins
        to chi_p.

        Parameters
        ----------
        maps : a mapping object

        Examples
        --------
        Convert a dict of numpy.array:

        Returns
        -------
        out : dict
            A dict with key as parameter name and value as numpy.array or float
            of transformed values.
        r´   )
r   r´   r   rb   rc   r‡   rˆ   r‰   rŠ   r,   )r   r   r+   r   r   r   r   N  s    zCartesianSpinToChiP.transformN)r?   r@   rA   rB   r-   r   rb   rc   r‡   rˆ   r‰   rŠ   r   r   r   r   r   r   r   r²   @  s   r²   c                   s’   e Zd ZdZdZd‡ fdd„	Zedd„ ƒZed	d
„ ƒZedd„ ƒZ	edd„ ƒZ
edd„ ƒZedd„ ƒZedd„ ƒZdd„ Ze‡ fdd„ƒZ‡  ZS )ÚLambdaFromTOVFilea   Transforms mass values corresponding to Lambda values for a given EOS
    interpolating from the mass-Lambda data for that EOS read in from an
    external ASCII file.

    The interpolation of the mass-Lambda data is a one-dimensional piecewise
    linear interpolation. If the ``redshift_mass`` keyword argument is ``True``
    (the default), the mass values to be transformed are assumed to be detector
    frame masses. In that case, a distance should be provided along with the
    mass for transformation to the source frame mass before the Lambda values
    are extracted from the interpolation. If the transform is read in from a
    config file, an example code block would be:

    .. code-block:: ini

        [{section}-lambda1]
        name = lambda_from_tov_file
        mass_param = mass1
        lambda_param = lambda1
        distance = 40
        mass_lambda_file = {filepath}

    If this transform is used in a parameter estimation analysis where
    distance is a variable parameter, the distance to be used will vary
    with each draw. In that case, the example code block will be:

    .. code-block:: ini

        [{section}-lambda1]
        name = lambda_from_tov_file
        mass_param = mass1
        lambda_param = lambda1
        mass_lambda_file = filepath

    If your prior is in terms of the source-frame masses (``srcmass``), then
    you can shut off the redshifting by adding ``do-not-redshift-mass`` to the
    config file. In this case you do not need to worry about a distance.
    Example:

    .. code-block:: ini

        [{section}-lambda1]
        name = lambda_from_tov_file
        mass_param = srcmass1
        lambda_param = lambda1
        mass_lambda_file = filepath
        do-not-redshift-mass =

    Parameters
    ----------
    mass_param : str
        The name of the mass parameter to transform.
    lambda_param : str
        The name of the tidal deformability parameter that mass_param is to
        be converted to interpolating from the data in the mass-Lambda file.
    mass_lambda_file : str
        Path of the mass-Lambda data file. The first column in the data file
        should contain mass values, and the second column Lambda values.
    distance : float, optional
        The distance (in Mpc) of the source. Used to redshift the mass. Needed
        if ``redshift_mass`` is True and no distance parameter exists If
        None, then a distance must be provided to the transform.
    redshift_mass : bool, optional
        Redshift the mass parameters when computing the lambdas. Default is
        False.
    file_columns : list of str, optional
        The names and order of columns in the ``mass_lambda_file``. Must
        contain at least 'mass' and 'lambda'. If not provided, will assume the
        order is ('mass', 'lambda').
    Zlambda_from_tov_fileNTc       	         sv   || _ || _|| _|| _|| _|dg| _|g| _|d kr@ddg}dd„ |D ƒ}tj| j |d}|| _	t
t| ƒ ¡  d S )Nrz   ÚmassÚlambdac             S   s   g | ]}|t f‘qS r   )r4   )r   Úfnamer   r   r   r   Ç  s    z.LambdaFromTOVFile.__init__.<locals>.<listcomp>)rM   )Z_mass_lambda_fileÚ_mass_paramÚ_lambda_paramÚredshift_massÚ	_distancer   r   rP   ZloadtxtÚ_datarj   rµ   r   )	r   Ú
mass_paramÚlambda_paramÚmass_lambda_filerz   r»   Úfile_columnsrM   Údata)rk   r   r   r   µ  s    	
zLambdaFromTOVFile.__init__c             C   s   | j S )z!Returns the input mass parameter.)r¹   )r   r   r   r   r¾   Ì  s    zLambdaFromTOVFile.mass_paramc             C   s   | j S )z$Returns the output lambda parameter.)rº   )r   r   r   r   r¿   Ñ  s    zLambdaFromTOVFile.lambda_paramc             C   s   | j S )N)r½   )r   r   r   r   rÂ   Ö  s    zLambdaFromTOVFile.datac             C   s
   | j d S )zVReturns the mass data read from the mass-Lambda data file for
        an EOS.
        r¶   )r½   )r   r   r   r   Ú	mass_dataÚ  s    zLambdaFromTOVFile.mass_datac             C   s
   | j d S )zXReturns the Lambda data read from the mass-Lambda data file for
        an EOS.
        r·   )r½   )r   r   r   r   Úlambda_dataá  s    zLambdaFromTOVFile.lambda_datac             C   s   | j S )zxReturns the fixed distance to transform mass samples from detector
        to source frame if one is specified.
        )r¼   )r   r   r   r   rz   è  s    zLambdaFromTOVFile.distancec             C   s$   | |  ¡ krd}nt | ||¡}|S )aè  Returns Lambda corresponding to a given mass interpolating from the
        TOV data.

        Parameters
        ----------
        m : float
            Value of the mass.
        mass_data : array
            Mass array from the Lambda-M curve of an EOS.
        lambda_data : array
            Lambda array from the Lambda-M curve of an EOS.

        Returns
        -------
        lambdav : float
            The Lambda corresponding to the mass `m` for the EOS considered.
        g        )ÚmaxrP   Zinterp)Zm_srcrÃ   rÄ   Zlambdavr   r   r   Úlambda_from_tov_dataï  s    z&LambdaFromTOVFile.lambda_from_tov_datac          
   C   s¬   || j  }| jrx| jdk	r"| j}n>y|d }W n0 tk
r^ } zt d¡ |‚W dd}~X Y nX ddt t|ƒ¡  }nd}| j	|  
|| | jd | jd ¡i}|  ||¡S )aÚ  Computes the transformation of mass to Lambda.

        Parameters
        ----------
        maps : dict or FieldArray
            A dictionary or FieldArray which provides a map between the
            parameter name of the variable to transform and its value(s).

        Returns
        -------
        out : dict or FieldArray
            A map between the transformed variable name and value(s), along
            with the original variable name and value(s).
        Nrz   z™Either provide distance samples in the list of samples to be transformed, or provide a fixed distance value as input when initializing LambdaFromTOVFile.g      ð?r¶   r·   )r¹   r»   r¼   ÚKeyErrorrŸ   r    r   r¥   Úabsrº   rÆ   r½   r,   )r   r   ÚmÚdÚeÚshiftr+   r   r   r   r   	  s    

zLambdaFromTOVFile.transformc                sH   |  d ||g¡d¡r&ddi}dg}nd }d }tt| ƒj|||||dS )Nr.   zdo-not-redshift-massr»   F)r8   r9   )r^   r2   rj   rµ   r>   )r5   r6   r7   r   r9   r8   )rk   r   r   r>   1  s    
zLambdaFromTOVFile.from_config)NTN)r?   r@   rA   rB   r-   r   Úpropertyr¾   r¿   rÂ   rÃ   rÄ   rz   rD   rÆ   r   rE   r>   ro   r   r   )rk   r   rµ   l  s   E  (rµ   c                   sv   e Zd ZdZdZd‡ fdd„	Zedd„ ƒZed	d
„ ƒZedd„ ƒZ	edd„ ƒZ
dd„ Zdd„ Ze‡ fdd„ƒZ‡  ZS )ÚLambdaFromMultipleTOVFilesa‹  Uses multiple equation of states.

    Parameters
    ----------
    mass_param : str
        The name of the mass parameter to transform.
    lambda_param : str
        The name of the tidal deformability parameter that mass_param is to
        be converted to interpolating from the data in the mass-Lambda file.
    mass_lambda_file : str
        Path of the mass-Lambda data file. The first column in the data file
        should contain mass values, and the second column Lambda values.
    distance : float, optional
        The distance (in Mpc) of the source. Used to redshift the mass. If
        None, then a distance must be provided to the transform.
    file_columns : list of str, optional
        The names and order of columns in the ``mass_lambda_file``. Must
        contain at least 'mass' and 'lambda'. If not provided, will assume the
        order is ('radius', 'mass', 'lambda').
    Zlambda_from_multiple_tov_filesNTc          	      s¾   || _ || _|| _|| _|| _|ddg| _|g| _i | _t| j dƒJ}xB|D ]:}| 	d¡}	t
tj |	¡ d¡d ƒ}
tj |	¡| j|
< qLW W d Q R X i | _|d kr¦d}|| _tt| ƒ ¡  d S )NÚeosrz   ÚrÚ
Ú.r   )Zradiusr¶   r·   )Ú	_map_filer¹   rº   r¼   r»   r   r   Ú
_eos_filesÚopenÚrstripÚintÚosÚpathÚbasenamer/   ÚabspathÚ
_eos_cacheÚ_file_columnsrj   rÎ   r   )r   r¾   r¿   Úmap_filerz   r»   rÁ   ÚfpÚliner¸   Zeosidx)rk   r   r   r   W  s$    	

 z#LambdaFromMultipleTOVFiles.__init__c             C   s   | j S )z!Returns the input mass parameter.)r¹   )r   r   r   r   r¾   u  s    z%LambdaFromMultipleTOVFiles.mass_paramc             C   s   | j S )z$Returns the output lambda parameter.)rº   )r   r   r   r   r¿   z  s    z'LambdaFromMultipleTOVFiles.lambda_paramc             C   s   | j S )zVReturns the mass data read from the mass-Lambda data file for
        an EOS.
        )rÓ   )r   r   r   r   rÞ     s    z#LambdaFromMultipleTOVFiles.map_filec             C   s   | j S )zxReturns the fixed distance to transform mass samples from detector
        to source frame if one is specified.
        )r¼   )r   r   r   r   rz   †  s    z#LambdaFromMultipleTOVFiles.distancec             C   sx   y| j | }W nd tk
rr   y6| j| }t| j| j|| j| j| jd}|| j |< W n tk
rl   d}Y nX Y nX |S )z^Gets the EOS for the given index.

        If the index is not in range returns None.
        )r¾   r¿   rÀ   rz   r»   rÁ   N)	rÜ   rÇ   rÔ   rµ   r¹   rº   r¼   r»   rÝ   )r   Ú	eos_indexrÏ   r¸   r   r   r   Úget_eos  s     

z"LambdaFromMultipleTOVFiles.get_eosc             C   sN   || j  }t|d ƒ}|  |¡}|dk	r2| |¡S | jtji}|  ||¡S dS )z7Transforms mass value and eos index into a lambda valuerÏ   N)r¹   r×   râ   r   rº   rP   Únanr,   )r   r   rÉ   rá   rÏ   r+   r   r   r   r   ¤  s    


z$LambdaFromMultipleTOVFiles.transformc                sH   |  d ||g¡d¡r&ddi}dg}nd }d }tt| ƒj|||||dS )Nr.   zdo-not-redshift-massr»   F)r8   r9   )r^   r2   rj   rÎ   r>   )r5   r6   r7   r   r9   r8   )rk   r   r   r>   ±  s    
z&LambdaFromMultipleTOVFiles.from_config)NTN)r?   r@   rA   rB   r-   r   rÍ   r¾   r¿   rÞ   rz   râ   r   rE   r>   ro   r   r   )rk   r   rÎ   ?  s     rÎ   c                   s\   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‡  ZS )ÚLoga.  Applies a log transform from an `inputvar` parameter to an `outputvar`
    parameter. This is the inverse of the exponent transform.

    Parameters
    ----------
    inputvar : str
        The name of the parameter to transform.
    outputvar : str
        The name of the transformed parameter.
    Úlogc                s.   || _ || _|g| _|g| _tt| ƒ ¡  d S )N)Ú	_inputvarÚ
_outputvarr   r   rj   rä   r   )r   ÚinputvarÚ	outputvar)rk   r   r   r   Í  s
    zLog.__init__c             C   s   | j S )zReturns the input parameter.)ræ   )r   r   r   r   rè   Ô  s    zLog.inputvarc             C   s   | j S )zReturns the output parameter.)rç   )r   r   r   r   ré   Ù  s    zLog.outputvarc             C   s&   || j  }| jt |¡i}|  ||¡S )aÅ  Computes :math:`\log(x)`.

        Parameters
        ----------
        maps : dict or FieldArray
            A dictionary or FieldArray which provides a map between the
            parameter name of the variable to transform and its value(s).

        Returns
        -------
        out : dict or FieldArray
            A map between the transformed variable name and value(s), along
            with the original variable name and value(s).
        )ræ   rç   rP   rå   r,   )r   r   r”   r+   r   r   r   r   Þ  s    
zLog.transformc             C   s&   || j  }| jt |¡i}|  ||¡S )aÇ  Computes :math:`y = e^{x}`.

        Parameters
        ----------
        maps : dict or FieldArray
            A dictionary or FieldArray which provides a map between the
            parameter name of the variable to transform and its value(s).

        Returns
        -------
        out : dict or FieldArray
            A map between the transformed variable name and value(s), along
            with the original variable name and value(s).
        )rç   ræ   rP   Úexpr,   )r   r   r•   r+   r   r   r   r   ñ  s    
zLog.inverse_transformc             C   s   || j  }d| S )aÞ  Computes the Jacobian of :math:`y = \log(x)`.

        This is:

        .. math::

            \frac{\mathrm{d}y}{\mathrm{d}x} = \frac{1}{x}.

        Parameters
        ----------
        maps : dict or FieldArray
            A dictionary or FieldArray which provides a map between the
            parameter name of the variable to transform and its value(s).

        Returns
        -------
        float
            The value of the jacobian at the given point(s).
        g      ð?)ræ   )r   r   r”   r   r   r   r     s    
zLog.jacobianc             C   s   || j  }t |¡S )aÖ  Computes the Jacobian of :math:`y = e^{x}`.

        This is:

        .. math::

            \frac{\mathrm{d}y}{\mathrm{d}x} = e^{x}.

        Parameters
        ----------
        maps : dict or FieldArray
            A dictionary or FieldArray which provides a map between the
            parameter name of the variable to transform and its value(s).

        Returns
        -------
        float
            The value of the jacobian at the given point(s).
        )rç   rP   rê   )r   r   r”   r   r   r   r     s    
zLog.inverse_jacobian)r?   r@   rA   rB   r-   r   rÍ   rè   ré   r   r   r   r   ro   r   r   )rk   r   rä   ¿  s   
rä   c                   s˜   e Zd ZdZdZd‡ fdd„	Zedd„ ƒZedd	„ ƒZed
d„ ƒZ	e
ddd„ƒZe
ddd„ƒZdd„ Zdd„ Zdd„ Zdd„ Zed ‡ fdd„	ƒZ‡  ZS )!ÚLogita  Applies a logit transform from an `inputvar` parameter to an `outputvar`
    parameter. This is the inverse of the logistic transform.

    Typically, the input of the logit function is assumed to have domain
    :math:`\in (0, 1)`. However, the `domain` argument can be used to expand
    this to any finite real interval.

    Parameters
    ----------
    inputvar : str
        The name of the parameter to transform.
    outputvar : str
        The name of the transformed parameter.
    domain : tuple or distributions.bounds.Bounds, optional
        The domain of the input parameter. Can be any finite
        interval. Default is (0., 1.).
    Úlogit©g        g      ð?c                s\   || _ || _|g| _|g| _t|d |d ddd| _|d | _|d | _tt	| ƒ 
¡  d S )Nr   rK   rÕ   )Z	btype_minZ	btype_max)ræ   rç   r   r   r   Ú_boundsÚ_aÚ_brj   rë   r   )r   rè   ré   Údomain)rk   r   r   r   H  s    

zLogit.__init__c             C   s   | j S )zReturns the input parameter.)ræ   )r   r   r   r   rè   T  s    zLogit.inputvarc             C   s   | j S )zReturns the output parameter.)rç   )r   r   r   r   ré   Y  s    zLogit.outputvarc             C   s   | j S )z*Returns the domain of the input parameter.)rî   )r   r   r   r   Úbounds^  s    zLogit.boundsç        ç      ð?c             C   s   t  | | ¡t  ||  ¡ S )a„  Computes the logit function with domain :math:`x \in (a, b)`.

        This is given by:

        .. math::

            \mathrm{logit}(x; a, b) = \log\left(\frac{x-a}{b-x}\right).

        Note that this is also the inverse of the logistic function with range
        :math:`(a, b)`.

        Parameters
        ----------
        x : float
            The value to evaluate.
        a : float, optional
            The minimum bound of the domain of x. Default is 0.
        b : float, optional
            The maximum bound of the domain of x. Default is 1.

        Returns
        -------
        float
            The logit of x.
        )rP   rå   )r”   rš   Úbr   r   r   rì   c  s    zLogit.logitc             C   s   t  | ¡}|||  d|  S )a¿  Computes the logistic function with range :math:`\in (a, b)`.

        This is given by:

        .. math::

            \mathrm{logistic}(x; a, b) = \frac{a + b e^x}{1 + e^x}.

        Note that this is also the inverse of the logit function with domain
        :math:`(a, b)`.

        Parameters
        ----------
        x : float
            The value to evaluate.
        a : float, optional
            The minimum bound of the range of the logistic function. Default
            is 0.
        b : float, optional
            The maximum bound of the range of the logistic function. Default
            is 1.

        Returns
        -------
        float
            The logistic of x.
        g      ð?)rP   rê   )r”   rš   rõ   Úexpxr   r   r   Úlogistic€  s    
zLogit.logisticc             C   sZ   || j  }| j |¡}t|tjƒr*| ¡ }|s6tdƒ‚| j|  	|| j
| j¡i}|  ||¡S )a$  Computes :math:`\mathrm{logit}(x; a, b)`.

        The domain :math:`a, b` of :math:`x` are given by the class's bounds.

        Parameters
        ----------
        maps : dict or FieldArray
            A dictionary or FieldArray which provides a map between the
            parameter name of the variable to transform and its value(s).

        Returns
        -------
        out : dict or FieldArray
            A map between the transformed variable name and value(s), along
            with the original variable name and value(s).
        z$one or more values are not in bounds)ræ   rî   Ú__contains__r   rP   rQ   r†   r$   rç   rì   rï   rð   r,   )r   r   r”   Úisinr+   r   r   r   r      s    
zLogit.transformc             C   s.   || j  }| j|  || j| j¡i}|  ||¡S )a,  Computes :math:`y = \mathrm{logistic}(x; a,b)`.

        The codomain :math:`a, b` of :math:`y` are given by the class's bounds.

        Parameters
        ----------
        maps : dict or FieldArray
            A dictionary or FieldArray which provides a map between the
            parameter name of the variable to transform and its value(s).

        Returns
        -------
        out : dict or FieldArray
            A map between the transformed variable name and value(s), along
            with the original variable name and value(s).
        )rç   ræ   r÷   rï   rð   r,   )r   r   r•   r+   r   r   r   r   »  s    
zLogit.inverse_transformc             C   sf   || j  }| j |¡}t|tjƒr4| ¡ s4tdƒ‚n|sFtd |¡ƒ‚| j	| j
 || j
 | j	|   S )a  Computes the Jacobian of :math:`y = \mathrm{logit}(x; a,b)`.

        This is:

        .. math::

            \frac{\mathrm{d}y}{\mathrm{d}x} = \frac{b -a}{(x-a)(b-x)},

        where :math:`x \in (a, b)`.

        Parameters
        ----------
        maps : dict or FieldArray
            A dictionary or FieldArray which provides a map between the
            parameter name of the variable to transform and its value(s).

        Returns
        -------
        float
            The value of the jacobian at the given point(s).
        z$one or more values are not in boundsz{} is not in bounds)ræ   rî   rø   r   rP   rQ   r†   r$   r¡   rð   rï   )r   r   r”   rù   r   r   r   r   Ð  s    

zLogit.jacobianc             C   s0   || j  }t |¡}|| j| j  d| d  S )a%  Computes the Jacobian of :math:`y = \mathrm{logistic}(x; a,b)`.

        This is:

        .. math::

            \frac{\mathrm{d}y}{\mathrm{d}x} = \frac{e^x (b-a)}{(1+e^y)^2},

        where :math:`y \in (a, b)`.

        Parameters
        ----------
        maps : dict or FieldArray
            A dictionary or FieldArray which provides a map between the
            parameter name of the variable to transform and its value(s).

        Returns
        -------
        float
            The value of the jacobian at the given point(s).
        g      ð?g       @)rç   rP   rê   rð   rï   )r   r   r”   rö   r   r   r   r   ï  s    

zLogit.inverse_jacobianNc                s  |  |d|¡}d ||g¡}d |¡}|dkr2g }|dkr@i }n| ¡ }| ||¡rn|  |||¡}	| |¡ nd}	d |¡}| ||¡r¢|  |||¡}
| |¡ nd}
|	dkr¶|
dk	sÆ|
dkrØ|	dk	rØtd ||¡ƒ‚n"|	dk	rú| dt|	ƒt|
ƒfi¡ t	t
| ƒ |||||¡S )a  Initializes a Logit transform from the given section.

        The section must specify an input and output variable name. The domain
        of the input may be specified using `min-{input}`, `max-{input}`.
        Example:

        .. code-block:: ini

            [{section}-logitq]
            name = logit
            inputvar = q
            outputvar = logitq
            min-q = 1
            max-q = 8

        Parameters
        ----------
        cp : pycbc.workflow.WorkflowConfigParser
            A parsed configuration file that contains the transform options.
        section : str
            Name of the section in the configuration file.
        outputs : str
            The names of the parameters that are output by this transformation,
            separated by `VARARGS_DELIM`. These must appear in the "tag" part
            of the section header.
        skip_opts : list, optional
            Do not read options in the given list.
        additional_opts : dict, optional
            Any additional arguments to pass to the class. If an option is
            provided that also exists in the config file, the value provided
            will be used instead of being read from the file.

        Returns
        -------
        cls
            An instance of the class.
        rè   r.   zmin-{}Nzmax-{}z;if providing a min(max)-{}, must also provide a max(min)-{}rñ   )r3   r2   r¡   r&   r^   Úappendr$   r'   r4   rj   rë   r>   )r5   r6   r7   r   r8   r9   rè   r`   r<   rš   rõ   )rk   r   r   r>   	  s2    )

 
zLogit.from_config)rí   )ró   rô   )ró   rô   )NN)r?   r@   rA   rB   r-   r   rÍ   rè   ré   rò   rD   rì   r÷   r   r   r   r   rE   r>   ro   r   r   )rk   r   rë   3  s    rë   c               @   s:   e Zd ZdZdZeZejZejZej	Z
ej
Z	ddd„ZdS )ÚMass1Mass2ToMchirpQz#The inverse of MchirpQToMass1Mass2.Zmass1_mass2_to_mchirp_qNc             C   sz   |d krt j}|d krt j}|d kr*t j}|d kr8t j}|| _|| _|| _|| _| j| jg| _	| j| jg| _
t | ¡ d S )N)r   rb   rc   rd   re   rf   rg   rh   ri   r   r   r
   r   )r   rf   rg   rh   ri   r   r   r   r   c  s    zMass1Mass2ToMchirpQ.__init__)NNNN)r?   r@   rA   rB   r-   ra   rC   r   r   r   r   r   r   r   r   r   rû   Y  s   rû   c               @   s<   e Zd ZdZdZeZejZejZej	Z
ej
Z	ejZejZdS )ÚMass1Mass2ToMchirpEtaz%The inverse of MchirpEtaToMass1Mass2.Zmass1_mass2_to_mchirp_etaN)r?   r@   rA   rB   r-   rp   rC   r   r   r   r   r   r   r   r   r   r   rü   w  s   rü   c               @   sD   e Zd ZdZdZeZejej	gZ
ejgZejZejZejZejZdS )ÚDistanceToChirpDistancez'The inverse of ChirpDistanceToDistance.Zdistance_to_chirp_distanceN)r?   r@   rA   rB   r-   rv   rC   r   rz   rd   r   ry   r   r   r   r   r   r   r   r   r   rý   „  s   rý   c                   s@   e Zd ZdZdZeZejZejZej	Z
ej
Z	‡ fdd„Z‡  ZS )ÚCartesianToSphericala¤  Converts spherical coordinates to cartesian.

    Parameters
    ----------
    x : str
        The name of the x parameter.
    y : str
        The name of the y parameter.
    z : str
        The name of the z parameter.
    radial : str
        The name of the radial parameter.
    azimuthal : str
        The name of the azimuthal angle parameter.
    polar : str
        The name of the polar angle parameter.
    r‹   c                sD   t t| ƒj|Ž  | j}| j}|| _|| _t| jƒ| _t| jƒ| _d S )N)rj   rþ   r   r   r   r   r   r   )r   Úargsr   r   )rk   r   r   r   «  s    zCartesianToSpherical.__init__)r?   r@   rA   rB   r-   r’   rC   r   r   r   r   r   ro   r   r   )rk   r   rþ   ‘  s   rþ   c                   s$   e Zd ZdZdZ‡ fdd„Z‡  ZS )ÚCartesianSpin1ToSphericalSpin1zÔThe inverse of SphericalSpin1ToCartesianSpin1.

    **Deprecation Warning:** This will be removed in a future update. Use
    :py:class:`CartesianToSpherical` with spin-parameter names passed in
    instead.
    Z$cartesian_spin_1_to_spherical_spin_1c                s4   t  d | jtj¡¡ tt| ƒ dddddd¡ d S )Nz´Deprecation warning: the {} transform will be removed in a future update. Please use {} instead, passing spin1x, spin1y, spin1z, spin1_a, spin1_azimuthal, spin1_polar as arguments.r‡   rˆ   rŒ   r‚   rž   r„   )rŸ   r    r¡   r-   rþ   rj   r   r   )r   )rk   r   r   r   À  s    
z'CartesianSpin1ToSphericalSpin1.__init__)r?   r@   rA   rB   r-   r   ro   r   r   )rk   r   r   ¶  s   r   c                   s$   e Zd ZdZdZ‡ fdd„Z‡  ZS )ÚCartesianSpin2ToSphericalSpin2zÔThe inverse of SphericalSpin2ToCartesianSpin2.

    **Deprecation Warning:** This will be removed in a future update. Use
    :py:class:`CartesianToSpherical` with spin-parameter names passed in
    instead.
    Z$cartesian_spin_2_to_spherical_spin_2c                s4   t  d | jtj¡¡ tt| ƒ dddddd¡ d S )Nz´Deprecation warning: the {} transform will be removed in a future update. Please use {} instead, passing spin2x, spin2y, spin2z, spin2_a, spin2_azimuthal, spin2_polar as arguments.r‰   rŠ   r   rƒ   r£   r…   )rŸ   r    r¡   r-   rþ   rj   r  r   )r   )rk   r   r   r   Ù  s    
z'CartesianSpin2ToSphericalSpin2.__init__)r?   r@   rA   rB   r-   r   ro   r   r   )rk   r   r  Ï  s   r  c               @   s<   e Zd ZdZdZeZejZejZej	Z
ej
Z	ejZejZdS )ÚCartesianSpinToAlignedMassSpinz.The inverse of AlignedMassSpinToCartesianSpin.Z#cartesian_spin_to_aligned_mass_spinN)r?   r@   rA   rB   r-   r¦   rC   r   r   r   r   r   r   r   r   r   r   r  è  s   r  c               @   s<   e Zd ZdZdZeZejZejZej	Z
ej
Z	ejZejZdS )Ú!CartesianSpinToPrecessionMassSpinz1The inverse of PrecessionMassSpinToCartesianSpin.Z&cartesian_spin_to_precession_mass_spinN)r?   r@   rA   rB   r-   r©   rC   r   r   r   r   r   r   r   r   r   r   r  õ  s   r  c               @   s<   e Zd ZdZdZeZejZejZej	Z
ej
Z	ejZejZdS )ÚChiPToCartesianSpinz%The inverse of `CartesianSpinToChiP`.r³   N)r?   r@   rA   rB   r-   r²   rC   r   r   r   r   r   r   r   r   r   r   r    s   r  c                   s@   e Zd ZdZdZeZejZejZej	Z
ej
Z	‡ fdd„Z‡  ZS )ÚExponenta  Applies an exponent transform to an `inputvar` parameter.

    This is the inverse of the log transform.

    Parameters
    ----------
    inputvar : str
        The name of the parameter to transform.
    outputvar : str
        The name of the transformed parameter.
    Úexponentc                s   t t| ƒ ||¡ d S )N)rj   r  r   )r   rè   ré   )rk   r   r   r   #  s    zExponent.__init__)r?   r@   rA   rB   r-   rä   rC   r   r   r   r   r   ro   r   r   )rk   r   r    s   r  c                   s`   e Zd ZdZdZeZejZejZej	Z
ej
Z	d‡ fdd„	Zedd„ ƒZed‡ fd	d
„	ƒZ‡  ZS )ÚLogistica|  Applies a logistic transform from an `input` parameter to an `output`
    parameter. This is the inverse of the logit transform.

    Typically, the output of the logistic function has range :math:`\in [0,1)`.
    However, the `codomain` argument can be used to expand this to any
    finite real interval.

    Parameters
    ----------
    inputvar : str
        The name of the parameter to transform.
    outputvar : str
        The name of the transformed parameter.
    frange : tuple or distributions.bounds.Bounds, optional
        The range of the output parameter. Can be any finite
        interval. Default is (0., 1.).
    r÷   ©g        g      ð?c                s   t t| ƒj|||d d S )N)rñ   )rj   r  r   )r   rè   ré   Úcodomain)rk   r   r   r   A  s    zLogistic.__init__c             C   s   | j S )z*Returns the range of the output parameter.)rî   )r   r   r   r   rò   D  s    zLogistic.boundsNc                s  |  |d|¡}|dkrg }|dkr(i }n| ¡ }d ||g¡}d |¡}| ||¡rn|  |||¡}	| |¡ nd}	d |¡}| ||¡r¢|  |||¡}
| |¡ nd}
|	dkr¶|
dk	sÆ|
dkrØ|	dk	rØtd ||¡ƒ‚n"|	dk	rú| dt|	ƒt|
ƒfi¡ t	t
| ƒ |||||¡S )a  Initializes a Logistic transform from the given section.

        The section must specify an input and output variable name. The
        codomain of the output may be specified using `min-{output}`,
        `max-{output}`. Example:

        .. code-block:: ini

            [{section}-q]
            name = logistic
            inputvar = logitq
            outputvar = q
            min-q = 1
            max-q = 8

        Parameters
        ----------
        cp : pycbc.workflow.WorkflowConfigParser
            A parsed configuration file that contains the transform options.
        section : str
            Name of the section in the configuration file.
        outputs : str
            The names of the parameters that are output by this transformation,
            separated by `VARARGS_DELIM`. These must appear in the "tag" part
            of the section header.
        skip_opts : list, optional
            Do not read options in the given list.
        additional_opts : dict, optional
            Any additional arguments to pass to the class. If an option is
            provided that also exists in the config file, the value provided
            will be used instead of being read from the file.

        Returns
        -------
        cls
            An instance of the class.
        ÚoutputNr.   zmin-{}zmax-{}z;if providing a min(max)-{}, must also provide a max(min)-{}r	  )r3   r&   r2   r¡   r^   rú   r$   r'   r4   rj   r  r>   )r5   r6   r7   r   r8   r9   ré   r`   r<   rš   rõ   )rk   r   r   r>   I  s2    )

 
zLogistic.from_config)r  )NN)r?   r@   rA   rB   r-   rë   rC   r   r   r   r   r   rÍ   rò   rE   r>   ro   r   r   )rk   r   r  '  s   r  c             C   s(   g | ] }|j d ks|jdks|  ¡ ‘qS )Nr“   )rC   r-   )r   Z_tr   r   r   r   â  s   r   c             C   sf  t |tƒst|ƒn|}g }xH| D ]@}d}x(|D ] }|| ¡ sD|dkrH|nd7 }q.W || d¡7 }q W tt| ƒt|ƒ ƒ} |rŽt|ƒ}|  |¡} g }xdtD ]\}|j |¡s˜|j 	| ¡r¶q˜|j | ¡}	|	r˜|	 |j
¡s˜|	 |¡rÞq˜|  |j
¡ | |¡ q˜W g }
xTtD ]L}|j
 |¡rt|j | ¡ƒdkr|  |j
¡ |
 |¡ | |j¡ qW |
| }t| ƒ|fS )aù  Determines if any additional parameters from the InferenceFile are
    needed to get derived parameters that user has asked for.

    First it will try to add any base parameters that are required to calculate
    the derived parameters. Then it will add any sampling parameters that are
    required to calculate the base parameters needed.

    Parameters
    ----------
    requested_params : list
        List of parameters that user wants.
    variable_args : list
        List of parameters that InferenceFile has.
    valid_params : list
        List of parameters that can be accepted.

    Returns
    -------
    requested_params : list
        Updated list of parameters that user wants.
    all_c : list
        List of BaseTransforms to apply.
    Ú Ú_ú r   )r   r   Úisalnumr/   r0   ÚintersectionÚcommon_cbc_inverse_transformsr   ÚissubsetÚ
isdisjointr   r'   rú   Úcommon_cbc_forward_transformsrR   )Zrequested_paramsZvariable_argsZvalid_paramsÚ
new_paramsr<   r`   ÚchZfrom_base_cÚ	converterZ	intersectZ	to_base_cZall_cr   r   r   Úget_common_cbc_transformsÿ  s@    

 




r  Fc          	   C   sZ   |r|ddd… }xB|D ]:}y|r.|  | ¡} n
| | ¡} W q tk
rP   wY qX qW | S )a]  Applies a list of BaseTransform instances on a mapping object.

    Parameters
    ----------
    samples : {FieldArray, dict}
        Mapping object to apply transforms to.
    transforms : list
        List of BaseTransform instances to apply. Nested transforms are assumed
        to be in order for forward transforms.
    inverse : bool, optional
        Apply inverse transforms. In this case transforms will be applied in
        the opposite order. Default is False.

    Returns
    -------
    samples : {FieldArray, dict}
        Mapping object with transforms applied. Same type as input.
    Néÿÿÿÿ)r   r   r   )ÚsamplesÚ
transformsrC   Útr   r   r   Úapply_transformsO	  s    
r  c             C   sF   d}|r&x8|D ]}||  | ¡9 }qW nx|D ]}|| | ¡9 }q,W |S )a'  Computes the jacobian of the list of transforms at the given sample
    points.

    Parameters
    ----------
    samples : {FieldArray, dict}
        Mapping object specifying points at which to compute jacobians.
    transforms : list
        List of BaseTransform instances to apply. Nested transforms are assumed
        to be in order for forward transforms.
    inverse : bool, optional
        Compute inverse jacobians. Default is False.

    Returns
    -------
    float :
        The product of the jacobians of all fo the transforms.
    g      ð?)r   r   )r  r  rC   Újr  r   r   r   Úcompute_jacobiano	  s    

r  c             C   sx   t ƒ jdd„ | D ƒŽ }g }dd„ | D ƒ}xJ|rrg }x8|D ]0}|j |¡r^| |¡ ||j8 }q8| |¡ q8W |}q*W |S )a°  Orders transforms to ensure proper chaining.

    For example, if `transforms = [B, A, C]`, and `A` produces outputs needed
    by `B`, the transforms will be re-rorderd to `[A, B, C]`.

    Parameters
    ----------
    transforms : list
        List of transform instances to order.

    Outputs
    -------
    list :
        List of transformed ordered such that forward transforms can be carried
        out without error.
    c             S   s    g | ]}t |jƒt |jƒ ‘qS r   )r   r   r   )r   r  r   r   r   r   ž	  s    z$order_transforms.<locals>.<listcomp>c             S   s   g | ]}|‘qS r   r   )r   r  r   r   r   r    	  s    )r   Úunionr   r  rú   r   )r  r   r+   Ú	remainingÚleftoverr  r   r   r   Úorder_transformsŒ	  s    

r"  r  c             C   sJ   g }x<|   |¡D ].}|  |d|¡}t|  | ||¡}| |¡ qW t|ƒS )a  Returns a list of PyCBC transform instances for a section in the
    given configuration file.

    If the transforms are nested (i.e., the output of one transform is the
    input of another), the returned list will be sorted by the order of the
    nests.

    Parameters
    ----------
    cp : WorflowConfigParser
        An open config file to read.
    section : {"transforms", string}
        Prefix on section names from which to retrieve the transforms.

    Returns
    -------
    list
        A list of the parsed transforms.
    r-   )Zget_subsectionsr3   r  r>   rú   r"  )r6   r7   ZtransZ
subsectionr-   r  r   r   r   Úread_transforms_from_config®	  s    r#  )N)F)F)r  )FrB   rØ   rŸ   rP   Zpycbcr   r   r   Zpycbc.ior   Zpycbc.waveformr   Zpycbc.boundariesr   r   Zpycbc.pnutilsr	   Úobjectr
   rF   ra   rp   rv   r{   r’   r   r¢   r¤   r¦   r©   r²   rµ   rÎ   rä   rë   rû   rü   rý   rþ   r   r  r  r  r  r  r  rC   r-   r  r‡   rˆ   rŒ   r‚   rž   r„   r‰   rŠ   r   rƒ   r£   r…   r  r  ÚextendZcommon_cbc_transformsr  r  r  r"  r#  r   r   r   r   Ú<module>   sþ     (k^[CW#? !, T t  (%l

P
 
"