B
    d&                 @   s   d Z ddlZddlmZmZmZ ddlmZ ddgZ	dd Z
d	d Zd
d Zdd Zdd Zdd Zdd Zdd ZeeeeeeedZdS )a  
Functions to determine if a model is separable, i.e.
if the model outputs are independent.

It analyzes ``n_inputs``, ``n_outputs`` and the operators
in a compound model by stepping through the transforms
and creating a ``coord_matrix`` of shape (``n_outputs``, ``n_inputs``).


Each modeling operator is represented by a function which
takes two simple models (or two ``coord_matrix`` arrays) and
returns an array of shape (``n_outputs``, ``n_inputs``).

    N   )ModelModelDefinitionErrorCompoundModel)Mappingis_separableseparability_matrixc             C   sT   | j dkr,| jdkr,tdg| j j}|S t| }|d}t|dkdd}|S )a  
    A separability test for the outputs of a transform.

    Parameters
    ----------
    transform : `~astropy.modeling.core.Model`
        A (compound) model.

    Returns
    -------
    is_separable : ndarray
        A boolean array with size ``transform.n_outputs`` where
        each element indicates whether the output is independent
        and the result of a separable transform.

    Examples
    --------
    >>> from astropy.modeling.models import Shift, Scale, Rotation2D, Polynomial2D
    >>> is_separable(Shift(1) & Shift(2) | Scale(1) & Scale(2))
        array([ True,  True]...)
    >>> is_separable(Shift(1) & Shift(2) | Rotation2D(2))
        array([False, False]...)
    >>> is_separable(Shift(1) & Shift(2) | Mapping([0, 1, 0, 1]) |         Polynomial2D(1) & Polynomial2D(2))
        array([False, False]...)
    >>> is_separable(Shift(1) & Shift(2) | Mapping([0, 1, 0, 1]))
        array([ True,  True,  True,  True]...)

    r   FT)n_inputs	n_outputsnparrayT
_separablesumwhere)	transformr   separable_matrix r   g/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/astropy/modeling/separable.pyr      s    
c             C   sJ   | j dkr,| jdkr,tj| j| j ftjdS t| }t|dkdd}|S )at  
    Compute the correlation between outputs and inputs.

    Parameters
    ----------
    transform : `~astropy.modeling.core.Model`
        A (compound) model.

    Returns
    -------
    separable_matrix : ndarray
        A boolean correlation matrix of shape (n_outputs, n_inputs).
        Indicates the dependence of outputs on inputs. For completely
        independent outputs, the diagonal elements are True and
        off-diagonal elements are False.

    Examples
    --------
    >>> from astropy.modeling.models import Shift, Scale, Rotation2D, Polynomial2D
    >>> separability_matrix(Shift(1) & Shift(2) | Scale(1) & Scale(2))
        array([[ True, False], [False,  True]]...)
    >>> separability_matrix(Shift(1) & Shift(2) | Rotation2D(2))
        array([[ True,  True], [ True,  True]]...)
    >>> separability_matrix(Shift(1) & Shift(2) | Mapping([0, 1, 0, 1]) |         Polynomial2D(1) & Polynomial2D(2))
        array([[ True,  True], [ True,  True]]...)
    >>> separability_matrix(Shift(1) & Shift(2) | Mapping([0, 1, 0, 1]))
        array([[ True, False], [False,  True], [ True, False], [False,  True]]...)

    r   )Zdtyper   TF)r	   r
   r   onesZbool_r   r   )r   r   r   r   r   r   B   s    
c             C   sD   t | tr| j}n
| jd }t |tr.|j}n
|jd }|| }|S )aB  
    Compute the number of outputs of two models.

    The two models are the left and right model to an operation in
    the expression tree of a compound model.

    Parameters
    ----------
    left, right : `astropy.modeling.Model` or ndarray
        If input is of an array, it is the output of `coord_matrix`.

    r   )
isinstancer   r
   shape)leftrightZlnoutZrnoutnoutpr   r   r   _compute_n_outputsi   s    



r   c             C   sV   dd }|| \}}||\}}||ks0||krDt d||||t||f}|S )a  
    Function corresponding to one of the arithmetic operators
    ['+', '-'. '*', '/', '**'].

    This always returns a nonseparable output.


    Parameters
    ----------
    left, right : `astropy.modeling.Model` or ndarray
        If input is of an array, it is the output of `coord_matrix`.

    Returns
    -------
    result : ndarray
        Result from this operation.
    c             S   s,   t | tr| j| j }}n
| j\}}||fS )N)r   r   r
   r	   r   )inputr
   r	   r   r   r   _n_inputs_outputs   s    

z&_arith_oper.<locals>._n_inputs_outputszUnsupported operands for arithmetic operator: left (n_inputs={}, n_outputs={}) and right (n_inputs={}, n_outputs={}); models must have the same n_inputs and the same n_outputs for this operator.)r   formatr   r   )r   r   r   Zleft_inputsZleft_outputsZright_inputsZright_outputsresultr   r   r   _arith_oper   s    r    c             C   sB  t | trg }x.| jD ]$}t| jf}d||< || qW t|}t|| jf}|dkrz||d| jd| jf< n||| j d| j df< |S | j	st|| jf}|dkrd|d| jd| jf< nd|| j d| j df< nNt|| jf}x t
| jD ]}d|||f< qW |dkr>t||| j }|S )a  
    Create an array representing inputs and outputs of a simple model.

    The array has a shape (noutp, model.n_inputs).

    Parameters
    ----------
    model : `astropy.modeling.Model`
        model
    pos : str
        Position of this model in the expression tree.
        One of ['left', 'right'].
    noutp : int
        Number of outputs of the compound model of which the input model
        is a left or right child.

    r   r   Nr   )r   r   mappingr   zerosr	   appendZvstackr
   Z	separablerangeZroll)modelposr   ZaxesiZaxismmatr   r   r   _coord_matrix   s.    


r*   c             C   s   t | |}t| tr"t| d|}n4t|| jd f}| |d| jd d| jd f< t|trnt|d|}n8t||jd f}d||jd  d|jd  df< t||gS )a  
    Function corresponding to '&' operation.

    Parameters
    ----------
    left, right : `astropy.modeling.Model` or ndarray
        If input is of an array, it is the output of `coord_matrix`.

    Returns
    -------
    result : ndarray
        Result from this operation.

    r   r   Nr   r   )r   r   r   r*   r   r"   r   Zhstack)r   r   r   cleftcrightr   r   r   _cstack   s    

 
$r-   c             C   s`   ||  } }dd }|| d}||d}yt ||}W n$ tk
rZ   td||Y nX |S )a  
    Function corresponding to "|" operation.

    Parameters
    ----------
    left, right : `astropy.modeling.Model` or ndarray
        If input is of an array, it is the output of `coord_matrix`.

    Returns
    -------
    result : ndarray
        Result from this operation.
    c             S   s"   t | trt| || j}n| }|S )zQ
        Return ``n_inputs``, ``n_outputs`` for a model or coord_matrix.
        )r   r   r*   r
   )r   positionZcoordsr   r   r   r     s    
z _cdot.<locals>._n_inputs_outputsr   r   zbModels cannot be combined with the "|" operator; left coord_matrix is {}, right coord_matrix is {})r   dot
ValueErrorr   r   )r   r   r   r+   r,   r   r   r   r   _cdot   s    



r1   c             C   sJ   t | tr.t| j}t| j}t| j ||S t | trFt| d| j	S dS )aq  
    Calculate the separability of outputs.

    Parameters
    ----------
    transform : `astropy.modeling.Model`
        A transform (usually a compound model).

    Returns :
    is_separable : ndarray of dtype np.bool
        An array of shape (transform.n_outputs,) of boolean type
        Each element represents the separablity of the corresponding output.
    r   N)
r   r   r   r   r   
_operatorsopr   r*   r
   )r   ZsepleftZseprightr   r   r   r   "  s    



r   )&|+-*/z**)__doc__numpyr   corer   r   r   Zmappingsr   __all__r   r   r   r    r*   r-   r1   r   r2   r   r   r   r   <module>   s   '')0(