B
    q\+                 @   s<   d Z ddlmZ ddgZG dd deZG dd deZdS )z
Special models useful for complex compound models where control is needed over
which outputs from a source model are mapped to which inputs of a target model.
   )FittableModelMappingIdentityc                   sf   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	dd Z
dd Zedd Z  ZS )r   a  
    Allows inputs to be reordered, duplicated or dropped.

    Parameters
    ----------
    mapping : tuple
        A tuple of integers representing indices of the inputs to this model
        to return and in what order to return them.  See
        :ref:`compound-model-mappings` for more details.
    n_inputs : int
        Number of inputs; if `None` (default) then ``max(mapping) + 1`` is
        used (i.e. the highest input index used in the mapping).
    name : str, optional
        A human-friendly name associated with this model instance
        (particularly useful for identifying the individual components of a
        compound model).
    meta : dict-like
        Free-form metadata to associate with this model.

    Raises
    ------
    TypeError
        Raised when number of inputs is less that ``max(mapping)``.

    Examples
    --------

    >>> from astropy.modeling.models import Polynomial2D, Shift, Mapping
    >>> poly1 = Polynomial2D(1, c0_0=1, c1_0=2, c0_1=3)
    >>> poly2 = Polynomial2D(1, c0_0=1, c1_0=2.4, c0_1=2.1)
    >>> model = (Shift(1) & Shift(2)) | Mapping((0, 1, 0, 1)) | (poly1 & poly2)
    >>> model(1, 2)  # doctest: +FLOAT_CMP
    (17.0, 14.2)
    TNc                s   |d kr*t dd tt|d D | _nt dd t|D | _t dd tt|D | _|| _dd | jD | _dd | jD | _t	 j
||d	 d S )
Nc             s   s   | ]}d t | V  qdS )xN)str).0idx r	   8lib/python3.7/site-packages/astropy/modeling/mappings.py	<genexpr>3   s   z#Mapping.__init__.<locals>.<genexpr>r   c             s   s   | ]}d t | V  qdS )r   N)r   )r   r   r	   r	   r
   r   6   s   c             s   s   | ]}d t | V  qdS )r   N)r   )r   r   r	   r	   r
   r   8   s    c             S   s   i | ]
}d |qS )Fr	   )r   keyr	   r	   r
   
<dictcomp>:   s    z$Mapping.__init__.<locals>.<dictcomp>c             S   s   i | ]
}d |qS )Fr	   )r   r   r	   r	   r
   r   ;   s    )namemeta)tuplerangemax_inputslen_outputs_mappingZ_input_units_strictZ _input_units_allow_dimensionlesssuper__init__)selfmappingn_inputsr   r   )	__class__r	   r
   r   1   s    zMapping.__init__c             C   s   | j S )zU
        The name(s) of the input variable(s) on which a model is evaluated.
        )r   )r   r	   r	   r
   inputs?   s    zMapping.inputsc             C   s   | j S )z*The name(s) of the output(s) of the model.)r   )r   r	   r	   r
   outputsG   s    zMapping.outputsc             C   s   | j S )z,Integers representing indices of the inputs.)r   )r   r	   r	   r
   r   M   s    zMapping.mappingc             C   s*   | j d krd| jS d| j| j S d S )Nz<Mapping({0})>z<Mapping({0}, name={1})>)r   formatr   )r   r	   r	   r
   __repr__S   s    
zMapping.__repr__c                sh   t  | jkr:| jd k	r| jnd}td|| jt  t fdd| jD }| jdkrd|d S |S )Nr   z{0} expects {1} inputs; got {2}c             3   s   | ]} | V  qd S )Nr	   )r   r   )argsr	   r
   r   `   s    z#Mapping.evaluate.<locals>.<genexpr>r       )r   r   r   	TypeErrorr   r   r   Z	n_outputs)r   r!   r   resultr	   )r!   r
   evaluateY   s    
zMapping.evaluatec                sd   y t  fddt jD }W n$ tk
rD   td jY nX  |} j|_	 j	|_|S )a)  
        A `Mapping` representing the inverse of the current mapping.

        Raises
        ------
        `NotImplementedError`
            An inverse does no exist on mappings that drop some of its inputs
            (there is then no way to reconstruct the inputs that were dropped).
        c             3   s   | ]} j |V  qd S )N)r   index)r   r   )r   r	   r
   r   t   s   z"Mapping.inverse.<locals>.<genexpr>z[Mappings such as {0} that drop one or more of their inputs are not invertible at this time.)
r   r   r   
ValueErrorNotImplementedErrorr   r   r   r   r   )r   r   invr	   )r   r
   inverseg   s    
zMapping.inverse)NNN)__name__
__module____qualname____doc__linearr   propertyr   r   r   r    r%   r*   __classcell__r	   r	   )r   r
   r      s   "c                   s:   e Zd ZdZdZd
 fdd	Zdd Zedd	 Z  Z	S )r   a  
    Returns inputs unchanged.

    This class is useful in compound models when some of the inputs must be
    passed unchanged to the next model.

    Parameters
    ----------
    n_inputs : int
        Specifies the number of inputs this identity model accepts.
    name : str, optional
        A human-friendly name associated with this model instance
        (particularly useful for identifying the individual components of a
        compound model).
    meta : dict-like
        Free-form metadata to associate with this model.

    Examples
    --------

    Transform ``(x, y)`` by a shift in x, followed by scaling the two inputs::

        >>> from astropy.modeling.models import (Polynomial1D, Shift, Scale,
        ...                                      Identity)
        >>> model = (Shift(1) & Identity(1)) | Scale(1.2) & Scale(2)
        >>> model(1,1)  # doctest: +FLOAT_CMP
        (2.4, 2.0)
        >>> model.inverse(2.4, 2) # doctest: +FLOAT_CMP
        (1.0, 1.0)
    TNc                s"   t t|}t j|||d d S )N)r   r   )r   r   r   r   )r   r   r   r   r   )r   r	   r
   r      s    zIdentity.__init__c             C   s*   | j d krd| jS d| j| j S d S )Nz<Identity({0})>z<Identity({0}, name={1})>)r   r   r   )r   r	   r	   r
   r       s    
zIdentity.__repr__c             C   s   | S )zl
        The inverse transformation.

        In this case of `Identity`, ``self.inverse is self``.
        r	   )r   r	   r	   r
   r*      s    zIdentity.inverse)NN)
r+   r,   r-   r.   r/   r   r    r0   r*   r1   r	   r	   )r   r
   r      s
   N)r.   Zcorer   __all__r   r   r	   r	   r	   r
   <module>   s   u