a
    ߙfb&                     @   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npZarrayT
_separablesumwhere)	transformr   separable_matrix r   9lib/python3.9/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   s:  t | trg }| jD ]$}t| jf}d||< || qt|}t|| jf}|dkrv||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< nJt|| jf}t
| jD ]}d|||f< q|dkr6t||| 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)Zmodelposr   ZaxesiZaxismZ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}|||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}zt ||}W n" tyX   td||Y n0 |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   Z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    




r-   c                 C   s^   |    }tur|S t| trBt| j}t| j}t| j ||S t| t	rZt
| 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)Z_calculate_separability_matrixNotImplementedr   r   r   r   r   
_operatorsopr   r'   r
   )r   Ztransform_matrixZsepleftZseprightr   r   r   r   "  s    



r   )&|+-*/z**)__doc__Znumpyr   corer   r   r   Zmappingsr   __all__r   r   r   r   r'   r*   r-   r   r/   r   r   r   r   <module>   s   '')0(