B
    q\                @   s  d Z ddlmZ ddlZddlmZmZmZ ddl	m
Z
mZ ddlmZ ddlmZ dd	lmZmZ d
dddddddddddddddddddddd d!d"d#gZd$ej ZeeejjZd%ed%ed%  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 d1d deZ)G d2d# d#eZ*G d3d deZ+G d4d deZ,G d5d deZ-G d6d deZ.G d7d" d"eZ/G d8d9 d9eZ0G d:d; d;eZ1G d<d deZ2G d=d deZ3G d>d  d eZ4G d?d! d!eZ5G d@d deZ6G dAd deZ7G dBd
 d
eZ8G dCd deZ9G dDd deZ:G dEd deZ;dS )FzMathematical models.    )OrderedDictN   )Fittable1DModelFittable2DModelModelDefinitionError)	ParameterInputParameterError)ellipse_extent)units)Quantity
UnitsError
AiryDisk2DMoffat1DMoffat2DBox1DBox2DConst1DConst2D	Ellipse2DDisk2D
Gaussian1D
Gaussian2DLinear1D	Lorentz1DMexicanHat1DMexicanHat2DRedshiftScaleFactorScaleMultiplySersic1DSersic2DShiftSine1DTrapezoid1DTrapezoidDisk2DRing2DVoigt1D   g       @c               @   sv   e Zd ZdZeddZeddZededfdZddd	Z	e
d
d Zedd Zedd Ze
dd Zdd ZdS )r   a  
    One dimensional Gaussian model.

    Parameters
    ----------
    amplitude : float
        Amplitude of the Gaussian.
    mean : float
        Mean of the Gaussian.
    stddev : float
        Standard deviation of the Gaussian.

    Notes
    -----

    Model formula:

        .. math:: f(x) = A e^{- \frac{\left(x - x_{0}\right)^{2}}{2 \sigma^{2}}}

    Examples
    --------
    >>> from astropy.modeling import models
    >>> def tie_center(model):
    ...         mean = 50 * model.stddev
    ...         return mean
    >>> tied_parameters = {'mean': tie_center}

    Specify that 'mean' is a tied parameter in one of two ways:

    >>> g1 = models.Gaussian1D(amplitude=10, mean=5, stddev=.3,
    ...                             tied=tied_parameters)

    or

    >>> g1 = models.Gaussian1D(amplitude=10, mean=5, stddev=.3)
    >>> g1.mean.tied
    False
    >>> g1.mean.tied = tie_center
    >>> g1.mean.tied
    <function tie_center at 0x...>

    Fixed parameters:

    >>> g1 = models.Gaussian1D(amplitude=10, mean=5, stddev=.3,
    ...                        fixed={'stddev': True})
    >>> g1.stddev.fixed
    True

    or

    >>> g1 = models.Gaussian1D(amplitude=10, mean=5, stddev=.3)
    >>> g1.stddev.fixed
    False
    >>> g1.stddev.fixed = True
    >>> g1.stddev.fixed
    True

    .. plot::
        :include-source:

        import numpy as np
        import matplotlib.pyplot as plt

        from astropy.modeling.models import Gaussian1D

        plt.figure()
        s1 = Gaussian1D()
        r = np.arange(-5, 5, .01)

        for factor in range(1, 4):
            s1.amplitude = factor
            plt.plot(r, s1(r), color=str(0.25 * factor), lw=2)

        plt.axis([-5, 5, -1, 4])
        plt.show()

    See Also
    --------
    Gaussian2D, Box1D, Moffat1D, Lorentz1D
    r   )defaultr   N)r(   bounds      @c             C   s    | j }|| j }|| || fS )a  
        Tuple defining the default ``bounding_box`` limits,
        ``(x_low, x_high)``

        Parameters
        ----------
        factor : float
            The multiple of `stddev` used to define the limits.
            The default is 5.5, corresponding to a relative error < 1e-7.

        Examples
        --------
        >>> from astropy.modeling.models import Gaussian1D
        >>> model = Gaussian1D(mean=0, stddev=2)
        >>> model.bounding_box
        (-11.0, 11.0)

        This range can be set directly (see: `Model.bounding_box
        <astropy.modeling.Model.bounding_box>`) or by using a different factor,
        like:

        >>> model.bounding_box = model.bounding_box(factor=2)
        >>> model.bounding_box
        (-4.0, 4.0)
        )meanstddev)selffactorx0dx r1   Alib/python3.7/site-packages/astropy/modeling/functional_models.pybounding_boxz   s    
zGaussian1D.bounding_boxc             C   s
   | j t S )z$Gaussian full width at half maximum.)r,   GAUSSIAN_SIGMA_TO_FWHM)r-   r1   r1   r2   fwhm   s    zGaussian1D.fwhmc             C   s"   |t d| | d  |d   S )z,
        Gaussian1D model function.
        g      r'   )npexp)x	amplituder+   r,   r1   r1   r2   evaluate   s    zGaussian1D.evaluatec             C   s\   t d|d  | | d  }|| | |  |d  }|| | | d  |d  }|||gS )z8
        Gaussian1D model function derivatives.
        g      r'      )r6   r7   )r8   r9   r+   r,   d_amplitudeZd_meanZd_stddevr1   r1   r2   	fit_deriv   s    zGaussian1D.fit_derivc             C   s    | j jd krd S d| j jiS d S )Nr8   )r+   unit)r-   r1   r1   r2   input_units   s    zGaussian1D.input_unitsc             C   s&   t d|d fd|d fd|d fgS )Nr+   r8   r,   r9   y)r   )r-   inputs_unitoutputs_unitr1   r1   r2   _parameter_units_for_data_units   s    
z*Gaussian1D._parameter_units_for_data_units)r*   )__name__
__module____qualname____doc__r   r9   r+   FLOAT_EPSILONr,   r3   propertyr5   staticmethodr:   r=   r?   rC   r1   r1   r1   r2   r   !   s   P


 c                   s   e Zd Z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jejejddddf fdd	Zed	d
 Zedd ZdddZedd Zedd Zedd Zdd Z  ZS )r   al  
    Two dimensional Gaussian model.

    Parameters
    ----------
    amplitude : float
        Amplitude of the Gaussian.
    x_mean : float
        Mean of the Gaussian in x.
    y_mean : float
        Mean of the Gaussian in y.
    x_stddev : float or None
        Standard deviation of the Gaussian in x before rotating by theta. Must
        be None if a covariance matrix (``cov_matrix``) is provided. If no
        ``cov_matrix`` is given, ``None`` means the default value (1).
    y_stddev : float or None
        Standard deviation of the Gaussian in y before rotating by theta. Must
        be None if a covariance matrix (``cov_matrix``) is provided. If no
        ``cov_matrix`` is given, ``None`` means the default value (1).
    theta : float, optional
        Rotation angle in radians. The rotation angle increases
        counterclockwise.  Must be None if a covariance matrix (``cov_matrix``)
        is provided. If no ``cov_matrix`` is given, ``None`` means the default
        value (0).
    cov_matrix : ndarray, optional
        A 2x2 covariance matrix. If specified, overrides the ``x_stddev``,
        ``y_stddev``, and ``theta`` defaults.

    Notes
    -----
    Model formula:

        .. math::

            f(x, y) = A e^{-a\left(x - x_{0}\right)^{2}  -b\left(x - x_{0}\right)
            \left(y - y_{0}\right)  -c\left(y - y_{0}\right)^{2}}

    Using the following definitions:

        .. math::
            a = \left(\frac{\cos^{2}{\left (\theta \right )}}{2 \sigma_{x}^{2}} +
            \frac{\sin^{2}{\left (\theta \right )}}{2 \sigma_{y}^{2}}\right)

            b = \left(\frac{\sin{\left (2 \theta \right )}}{2 \sigma_{x}^{2}} -
            \frac{\sin{\left (2 \theta \right )}}{2 \sigma_{y}^{2}}\right)

            c = \left(\frac{\sin^{2}{\left (\theta \right )}}{2 \sigma_{x}^{2}} +
            \frac{\cos^{2}{\left (\theta \right )}}{2 \sigma_{y}^{2}}\right)

    If using a ``cov_matrix``, the model is of the form:
        .. math::
            f(x, y) = A e^{-0.5 \left(\vec{x} - \vec{x}_{0}\right)^{T} \Sigma^{-1} \left(\vec{x} - \vec{x}_{0}\right)}

    where :math:`\vec{x} = [x, y]`, :math:`\vec{x}_{0} = [x_{0}, y_{0}]`,
    and :math:`\Sigma` is the covariance matrix:

        .. math::
            \Sigma = \left(\begin{array}{ccc}
            \sigma_x^2               & \rho \sigma_x \sigma_y \\
            \rho \sigma_x \sigma_y   & \sigma_y^2
            \end{array}\right)

    :math:`\rho` is the correlation between ``x`` and ``y``, which should
    be between -1 and +1.  Positive correlation corresponds to a
    ``theta`` in the range 0 to 90 degrees.  Negative correlation
    corresponds to a ``theta`` in the range of 0 to -90 degrees.

    See [1]_ for more details about the 2D Gaussian function.

    See Also
    --------
    Gaussian1D, Box2D, Moffat2D

    References
    ----------
    .. [1] https://en.wikipedia.org/wiki/Gaussian_function
    r   )r(   r   g        Nc          	      s  |d kr@|d kr| j jj}|d kr,| j jj}|d kr| j jj}n|d k	sX|d k	sX|d k	rbtdn^t|}|jdkr~t	dtj
|\}	}
t|	\}}|
d d df }t|d |d }|di  |d dtd f |d dtd f t jf ||||||d	| d S )
Nz3Cannot specify both cov_matrix and x/y_stddev/theta)r'   r'   zCovariance matrix must be 2x2r   r   r)   x_stddevy_stddev)r9   x_meany_meanrK   rL   theta)	__class__rK   r(   rL   rO   r   r6   arrayshape
ValueErrorZlinalgZeigsqrtZarctan2
setdefaultrH   super__init__)r-   r9   rM   rN   rK   rL   rO   Z
cov_matrixkwargsZeig_valsZeig_vecsZy_vec)rP   r1   r2   rW     s,    




zGaussian2D.__init__c             C   s
   | j t S )z)Gaussian full width at half maximum in X.)rK   r4   )r-   r1   r1   r2   x_fwhm>  s    zGaussian2D.x_fwhmc             C   s
   | j t S )z)Gaussian full width at half maximum in Y.)rL   r4   )r-   r1   r1   r2   y_fwhmC  s    zGaussian2D.y_fwhm      @c             C   sT   || j  }|| j }| jj}t|||\}}| j| | j| f| j| | j| ffS )a  
        Tuple defining the default ``bounding_box`` limits in each dimension,
        ``((y_low, y_high), (x_low, x_high))``

        The default offset from the mean is 5.5-sigma, corresponding
        to a relative error < 1e-7. The limits are adjusted for rotation.

        Parameters
        ----------
        factor : float, optional
            The multiple of `x_stddev` and `y_stddev` used to define the limits.
            The default is 5.5.

        Examples
        --------
        >>> from astropy.modeling.models import Gaussian2D
        >>> model = Gaussian2D(x_mean=0, y_mean=0, x_stddev=1, y_stddev=2)
        >>> model.bounding_box
        ((-11.0, 11.0), (-5.5, 5.5))

        This range can be set directly (see: `Model.bounding_box
        <astropy.modeling.Model.bounding_box>`) or by using a different factor
        like:

        >>> model.bounding_box = model.bounding_box(factor=2)
        >>> model.bounding_box
        ((-4.0, 4.0), (-2.0, 2.0))
        )rK   rL   rO   valuer	   rN   rM   )r-   r.   abrO   r0   dyr1   r1   r2   r3   H  s    

zGaussian2D.bounding_boxc             C   s   t |d }t |d }	t d| }
|d }|d }| | }|| }d|| |	|   }d|
| |
|   }d|	| ||   }|t ||d  || |  ||d     S )z!Two dimensional Gaussian functionr'   g       @g      ?)r6   cossinr7   )r8   r@   r9   rM   rN   rK   rL   rO   cost2sint2sin2txstd2ystd2xdiffydiffr]   r^   cr1   r1   r2   r:   n  s    zGaussian2D.evaluatec       )      C   s  t |}t |}	t |d }
t |d }t d| }t d| }|d }|d }|d }|d }| | }|| }|d }|d }d|
| ||   }d|| ||   }d|| |
|   }|t || || |  ||    }|	| d| d|   }|
 | }| | }|| ||  }| | }|| }| } | | }!|
 | }"|| }#|d| | ||   }$||| d| |   }%||| || |  |!|    }&||| || |  |"|    }'||| || |  | |    }(|#|$|%|&|'|(gS )zGTwo dimensional Gaussian function derivative with respect to parametersr'   g       @r;   g      ?g      ?)r6   r`   ra   r7   ))r8   r@   r9   rM   rN   rK   rL   rO   costsintrb   rc   Zcos2trd   re   rf   Zxstd3Zystd3rg   rh   Zxdiff2Zydiff2r]   r^   ri   gZ	da_dthetaZda_dx_stddevZda_dy_stddevZ	db_dthetaZdb_dx_stddevZdb_dy_stddevZ	dc_dthetaZdc_dx_stddevZdc_dy_stddevZdg_dAZ
dg_dx_meanZ
dg_dy_meanZdg_dx_stddevZdg_dy_stddevZ	dg_dthetar1   r1   r2   r=     sT    







zGaussian2D.fit_derivc             C   s2   | j jd kr| jjd krd S | j j| jjdS d S )N)r8   r@   )rM   r>   rN   )r-   r1   r1   r2   r?     s    zGaussian2D.input_unitsc          	   C   sZ   |d |d krt dtd|d fd|d fd|d fd|d fdtjfd	|d
 fgS )Nr8   r@   z(Units of 'x' and 'y' inputs should matchrM   rN   rK   rL   rO   r9   z)r   r   urad)r-   rA   rB   r1   r1   r2   rC     s    


z*Gaussian2D._parameter_units_for_data_units)r[   )rD   rE   rF   rG   r   r9   rM   rN   rK   rL   rO   r(   rW   rI   rY   rZ   r3   rJ   r:   r=   r?   rC   __classcell__r1   r1   )rP   r2   r      s"   M





(
&/c               @   sb   e Zd ZdZdZdZeddZdZe	dd Z
e	dd	 Zed
d Zedd Zedd ZdS )r!   zv
    Shift a coordinate.

    Parameters
    ----------
    offset : float
        Offset to add to a coordinate.
    )r8   r   )r(   Tc             C   s    | j jd krd S d| j jiS d S )Nr8   )offsetr>   )r-   r1   r1   r2   r?     s    zShift.input_unitsc             C   s   |   }| jd9  _|S )z,One dimensional inverse Shift model function)copyrq   )r-   invr1   r1   r2   inverse  s    zShift.inversec             C   s   | | S )z$One dimensional Shift model functionr1   )r8   rq   r1   r1   r2   r:     s    zShift.evaluatec             C   s   | S )z=Evaluate the implicit term (x) of one dimensional Shift modelr1   )r8   r1   r1   r2   sum_of_implicit_terms  s    zShift.sum_of_implicit_termsc             G   s   t | }|gS )z@One dimensional Shift model derivative with respect to parameter)r6   	ones_like)r8   paramsZd_offsetr1   r1   r2   r=     s    
zShift.fit_derivN)rD   rE   rF   rG   inputsoutputsr   rq   linearrI   r?   ru   rJ   r:   rv   r=   r1   r1   r1   r2   r!     s   
c               @   sb   e Zd ZdZdZdZeddZdZdZ	dZ
dZedd Zedd	 Zed
d Zedd ZdS )r   a   
    Multiply a model by a dimensionless factor.

    Parameters
    ----------
    factor : float
        Factor by which to scale a coordinate.

    Notes
    -----

    If ``factor`` is a `~astropy.units.Quantity` then the units will be
    stripped before the scaling operation.

    )r8   r   )r(   Tc             C   s    | j jd krd S d| j jiS d S )Nr8   )r.   r>   )r-   r1   r1   r2   r?     s    zScale.input_unitsc             C   s   |   }d| j |_|S )z,One dimensional inverse Scale model functionr   )rs   r.   )r-   rt   r1   r1   r2   ru     s    zScale.inversec             C   s   t |tjr|j}||  S )z$One dimensional Scale model function)
isinstancern   r   r\   )r8   r.   r1   r1   r2   r:     s    zScale.evaluatec             G   s
   | }|gS )z@One dimensional Scale model derivative with respect to parameterr1   )r8   rx   d_factorr1   r1   r2   r=   %  s    zScale.fit_derivN)rD   rE   rF   rG   ry   rz   r   r.   r{   fittableZ_input_units_strictZ _input_units_allow_dimensionlessrI   r?   ru   rJ   r:   r=   r1   r1   r1   r2   r     s   
c               @   sN   e Zd ZdZdZdZeddZdZdZ	e
dd Zedd	 Zed
d ZdS )r   z
    Multiply a model by a quantity or number.

    Parameters
    ----------
    factor : float
        Factor by which to multiply a coordinate.
    )r8   r   )r(   Tc             C   s   |   }d| j |_|S )z/One dimensional inverse multiply model functionr   )rs   r.   )r-   rt   r1   r1   r2   ru   >  s    zMultiply.inversec             C   s   ||  S )z'One dimensional multiply model functionr1   )r8   r.   r1   r1   r2   r:   E  s    zMultiply.evaluatec             G   s
   | }|gS )zCOne dimensional multiply model derivative with respect to parameterr1   )r8   rx   r}   r1   r1   r2   r=   J  s    zMultiply.fit_derivN)rD   rE   rF   rG   ry   rz   r   r.   r{   r~   rI   ru   rJ   r:   r=   r1   r1   r1   r2   r   -  s   
c               @   s@   e Zd ZdZedddZedd Zedd Ze	d	d
 Z
dS )r   z
    One dimensional redshift scale factor model.

    Parameters
    ----------
    z : float
        Redshift value.

    Notes
    -----
    Model formula:

        .. math:: f(x) = x (1 + z)
    Zredshiftr   )Zdescriptionr(   c             C   s   d| |  S )z2One dimensional RedshiftScaleFactor model functionr   r1   )r8   rm   r1   r1   r2   r:   d  s    zRedshiftScaleFactor.evaluatec             C   s
   | }|gS )z4One dimensional RedshiftScaleFactor model derivativer1   )r8   rm   Zd_zr1   r1   r2   r=   j  s    zRedshiftScaleFactor.fit_derivc             C   s    |   }dd| j  d |_|S )z!Inverse RedshiftScaleFactor modelg      ?)rs   rm   )r-   rt   r1   r1   r2   ru   q  s    zRedshiftScaleFactor.inverseN)rD   rE   rF   rG   r   rm   rJ   r:   r=   rI   ru   r1   r1   r1   r2   r   R  s
   c               @   sR   e Zd ZdZeddZeddZeddZdZe	dd Z
edd	 Zd
d ZdS )r   a  
    One dimensional Sersic surface brightness profile.

    Parameters
    ----------
    amplitude : float
        Surface brightness at r_eff.
    r_eff : float
        Effective (half-light) radius
    n : float
        Sersic Index.

    See Also
    --------
    Gaussian1D, Moffat1D, Lorentz1D

    Notes
    -----
    Model formula:

    .. math::

        I(r)=I_e\exp\left\{-b_n\left[\left(\frac{r}{r_{e}}\right)^{(1/n)}-1\right]\right\}

    The constant :math:`b_n` is defined such that :math:`r_e` contains half the total
    luminosity, and can be solved for numerically.

    .. math::

        \Gamma(2n) = 2\gamma (b_n,2n)

    Examples
    --------
    .. plot::
        :include-source:

        import numpy as np
        from astropy.modeling.models import Sersic1D
        import matplotlib.pyplot as plt

        plt.figure()
        plt.subplot(111, xscale='log', yscale='log')
        s1 = Sersic1D(amplitude=1, r_eff=5)
        r=np.arange(0, 100, .01)

        for n in range(1, 10):
             s1.n = n
             plt.plot(r, s1(r), color=str(float(n) / 15))

        plt.axis([1e-1, 30, 1e-2, 1e3])
        plt.xlabel('log Radius')
        plt.ylabel('log Surface Brightness')
        plt.text(.25, 1.5, 'n=1')
        plt.text(.25, 300, 'n=10')
        plt.xticks([])
        plt.yticks([])
        plt.show()

    References
    ----------
    .. [1] http://ned.ipac.caltech.edu/level5/March05/Graham/Graham2.html
    r   )r(      Nc             C   sn   | j dkr>yddlm} || _ W n tk
r<   tdY nX |t|  d| d || d|  d   S )z(One dimensional Sersic profile function.Nr   )gammaincinvz%Sersic1D model requires scipy > 0.11.r'   g      ?r   )_gammaincinvscipy.specialr   rS   ImportErrorr6   r7   )clsrr9   r_effnr   r1   r1   r2   r:     s    

zSersic1D.evaluatec             C   s    | j jd krd S d| j jiS d S )Nr8   )r   r>   )r-   r1   r1   r2   r?     s    zSersic1D.input_unitsc             C   s   t d|d fd|d fgS )Nr   r8   r9   r@   )r   )r-   rA   rB   r1   r1   r2   rC     s    z(Sersic1D._parameter_units_for_data_units)rD   rE   rF   rG   r   r9   r   r   r   classmethodr:   rI   r?   rC   r1   r1   r1   r2   r   z  s   >


c               @   sZ   e Zd Z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dS )r"   aL  
    One dimensional Sine model.

    Parameters
    ----------
    amplitude : float
        Oscillation amplitude
    frequency : float
        Oscillation frequency
    phase : float
        Oscillation phase

    See Also
    --------
    Const1D, Linear1D


    Notes
    -----
    Model formula:

        .. math:: f(x) = A \sin(2 \pi f x + 2 \pi p)

    Examples
    --------
    .. plot::
        :include-source:

        import numpy as np
        import matplotlib.pyplot as plt

        from astropy.modeling.models import Sine1D

        plt.figure()
        s1 = Sine1D(amplitude=1, frequency=.25)
        r=np.arange(0, 10, .01)

        for amplitude in range(1,4):
             s1.amplitude = amplitude
             plt.plot(r, s1(r), color=str(0.25 * amplitude), lw=2)

        plt.axis([0, 10, -5, 5])
        plt.show()
    r   )r(   r   c             C   s.   t ||  |  }t|tr |j}|t| S )z#One dimensional Sine model function)TWOPIr|   r   r\   r6   ra   )r8   r9   	frequencyphaseZargumentr1   r1   r2   r:     s    
zSine1D.evaluatec             C   sl   t t| |  t|  }t|  | t t| |  t|   }t| t t| |  t|   }|||gS )z%One dimensional Sine model derivative)r6   ra   r   r`   )r8   r9   r   r   r<   Zd_frequencyZd_phaser1   r1   r2   r=     s    
zSine1D.fit_derivc             C   s$   | j jd krd S dd| j j iS d S )Nr8   g      ?)r   r>   )r-   r1   r1   r2   r?   #  s    zSine1D.input_unitsc             C   s    t d|d d fd|d fgS )Nr   r8   rr   r9   r@   )r   )r-   rA   rB   r1   r1   r2   rC   *  s    z&Sine1D._parameter_units_for_data_unitsN)rD   rE   rF   rG   r   r9   r   r   rJ   r:   r=   rI   r?   rC   r1   r1   r1   r2   r"     s   ,


c               @   s`   e Zd ZdZeddZeddZdZedd Z	edd	 Z
ed
d Zedd Zdd ZdS )r   a(  
    One dimensional Line model.

    Parameters
    ----------
    slope : float
        Slope of the straight line

    intercept : float
        Intercept of the straight line

    See Also
    --------
    Const1D

    Notes
    -----
    Model formula:

        .. math:: f(x) = a x + b
    r   )r(   r   Tc             C   s   ||  | S )z#One dimensional Line model functionr1   )r8   slope	interceptr1   r1   r2   r:   J  s    zLinear1D.evaluatec             C   s   | }t | }||gS )z@One dimensional Line model derivative with respect to parameters)r6   rw   )r8   r   r   Zd_sloped_interceptr1   r1   r2   r=   P  s    
zLinear1D.fit_derivc             C   s&   | j d }| j | j  }| j||dS )Nrr   )r   r   )r   r   rP   )r-   Z	new_slopeZnew_interceptr1   r1   r2   ru   X  s    
zLinear1D.inversec             C   s4   | j jd kr| jjd krd S d| j j| jj iS d S )Nr8   )r   r>   r   )r-   r1   r1   r2   r?   ^  s    zLinear1D.input_unitsc             C   s$   t d|d fd|d |d  fgS )Nr   r@   r   r8   )r   )r-   rA   rB   r1   r1   r2   rC   e  s    z(Linear1D._parameter_units_for_data_unitsN)rD   rE   rF   rG   r   r   r   r{   rJ   r:   r=   rI   ru   r?   rC   r1   r1   r1   r2   r   /  s   

c               @   sJ   e Zd ZdZeddZeddZeddZdZe	dd Z
e	dd	 Zd
S )Planar2Da  
    Two dimensional Plane model.

    Parameters
    ----------
    slope_x : float
        Slope of the straight line in X

    slope_y : float
        Slope of the straight line in Y

    intercept : float
        Z-intercept of the straight line

    See Also
    --------
    Linear1D, Polynomial2D

    Notes
    -----
    Model formula:

        .. math:: f(x, y) = a x + b y + c
    r   )r(   r   Tc             C   s   ||  ||  | S )z$Two dimensional Plane model functionr1   )r8   r@   slope_xslope_yr   r1   r1   r2   r:     s    zPlanar2D.evaluatec             C   s   | }|}t | }|||gS )zATwo dimensional Plane model derivative with respect to parameters)r6   rw   )r8   r@   r   r   r   Z	d_slope_xZ	d_slope_yr   r1   r1   r2   r=     s    
zPlanar2D.fit_derivN)rD   rE   rF   rG   r   r   r   r   r{   rJ   r:   r=   r1   r1   r1   r2   r   j  s   


r   c               @   sd   e Zd ZdZeddZeddZeddZedd Z	edd Z
dd
dZedd Zdd ZdS )r   a_  
    One dimensional Lorentzian model.

    Parameters
    ----------
    amplitude : float
        Peak value
    x_0 : float
        Position of the peak
    fwhm : float
        Full width at half maximum

    See Also
    --------
    Gaussian1D, Box1D, MexicanHat1D

    Notes
    -----
    Model formula:

    .. math::

        f(x) = \frac{A \gamma^{2}}{\gamma^{2} + \left(x - x_{0}\right)^{2}}

    Examples
    --------
    .. plot::
        :include-source:

        import numpy as np
        import matplotlib.pyplot as plt

        from astropy.modeling.models import Lorentz1D

        plt.figure()
        s1 = Lorentz1D()
        r = np.arange(-5, 5, .01)

        for factor in range(1, 4):
            s1.amplitude = factor
            plt.plot(r, s1(r), color=str(0.25 * factor), lw=2)

        plt.axis([-5, 5, -1, 4])
        plt.show()
    r   )r(   r   c             C   s(   ||d d  | | d |d d   S )z)One dimensional Lorentzian model functiong       @r'   r1   )r8   r9   x_0r5   r1   r1   r2   r:     s    zLorentz1D.evaluatec             C   sj   |d |d | | d   }|| d|  d|   |d | | d   }d| | | d|  }|||gS )zFOne dimensional Lorentzian model derivative with respect to parametersr'   r   r1   )r8   r9   r   r5   r<   d_x_0Zd_fwhmr1   r1   r2   r=     s
    zLorentz1D.fit_deriv   c             C   s    | j }|| j }|| || fS )ar  Tuple defining the default ``bounding_box`` limits,
        ``(x_low, x_high)``.

        Parameters
        ----------
        factor : float
            The multiple of FWHM used to define the limits.
            Default is chosen to include most (99%) of the
            area under the curve, while still showing the
            central feature of interest.

        )r   r5   )r-   r.   r/   r0   r1   r1   r2   r3     s    
zLorentz1D.bounding_boxc             C   s    | j jd krd S d| j jiS d S )Nr8   )r   r>   )r-   r1   r1   r2   r?     s    zLorentz1D.input_unitsc             C   s&   t d|d fd|d fd|d fgS )Nr   r8   r5   r9   r@   )r   )r-   rA   rB   r1   r1   r2   rC     s    
z)Lorentz1D._parameter_units_for_data_unitsN)r   )rD   rE   rF   rG   r   r9   r   r5   rJ   r:   r=   r3   rI   r?   rC   r1   r1   r1   r2   r     s   -




c            	   @   s   e Zd ZdZeddZeddZedej dZ	ee
ddZeddddgdd	d
dgddddgddddggZedd Zedd Zedd Zdd ZdS )r&   a!  
    One dimensional model for the Voigt profile.

    Parameters
    ----------
    x_0 : float
        Position of the peak
    amplitude_L : float
        The Lorentzian amplitude
    fwhm_L : float
        The Lorentzian full width at half maximum
    fwhm_G : float
        The Gaussian full width at half maximum

    See Also
    --------
    Gaussian1D, Lorentz1D

    Notes
    -----
    Algorithm for the computation taken from
    McLean, A. B., Mitchell, C. E. J. & Swanston, D. M. Implementation of an
    efficient analytical approximation to the Voigt function for photoemission
    lineshape analysis. Journal of Electron Spectroscopy and Related Phenomena
    69, 125-132 (1994)

    Examples
    --------
    .. plot::
        :include-source:

        import numpy as np
        from astropy.modeling.models import Voigt1D
        import matplotlib.pyplot as plt

        plt.figure()
        x = np.arange(0, 10, 0.01)
        v1 = Voigt1D(x_0=5, amplitude_L=10, fwhm_L=0.5, fwhm_G=0.9)
        plt.plot(x, v1(x))
        plt.show()
    r   )r(   r   r'   gq=
ףpgQIg??g~:?g?g~:ؿgX9vӿg.1?g/$?g~k	g/$g~k	?c             C   s   | j \}}}}	ttd}
|| d |
 | }t|dtjf }||
 | }t|dtjf }tj|||  |	||   || d || d   dd}|| ttj |
 | | S )Nr'   .rr   )axis)_abcdr6   rT   log
atleast_1dnewaxissumpi)r   r8   r   amplitude_Lfwhm_Lfwhm_GABCDsqrt_ln2XYVr1   r1   r2   r:   2  s    :zVoigt1D.evaluatec          	   C   s  | j \}}}}	ttd}
|| d |
 | }t|d d tjf }||
 | }t|d d tjf }|| ttj |
 | }|||  |	||   }|| d || d  }tj|| dd}tj|	| d||  | t|  dd}tj|| d||  | t|  dd}| | d |
 | || | ||| ||
 |   | ||
| d||  | ||     | g}|S )Nr'   rr   )r   )	r   r6   rT   r   r   r   r   r   Zsquare)r   r8   r   r   r   r   r   r   r   r   r   r   r   ZconstantalphaZbetar   ZdVdxZdVdyZdydar1   r1   r2   r=   @  s"    ,,
0zVoigt1D.fit_derivc             C   s    | j jd krd S d| j jiS d S )Nr8   )r   r>   )r-   r1   r1   r2   r?   W  s    zVoigt1D.input_unitsc             C   s0   t d|d fd|d fd|d fd|d fgS )Nr   r8   r   r   r   r@   )r   )r-   rA   rB   r1   r1   r2   rC   ^  s    

z'Voigt1D._parameter_units_for_data_unitsN)rD   rE   rF   rG   r   r   r   r6   r   r   r   r   rQ   r   r   r:   r=   rI   r?   rC   r1   r1   r1   r2   r&     s   )




c               @   sJ   e Zd ZdZeddZdZedd Zedd Z	e
d	d
 Zdd ZdS )r   a  
    One dimensional Constant model.

    Parameters
    ----------
    amplitude : float
        Value of the constant function

    See Also
    --------
    Const2D

    Notes
    -----
    Model formula:

        .. math:: f(x) = A

    Examples
    --------
    .. plot::
        :include-source:

        import numpy as np
        import matplotlib.pyplot as plt

        from astropy.modeling.models import Const1D

        plt.figure()
        s1 = Const1D()
        r = np.arange(-5, 5, .01)

        for factor in range(1, 4):
            s1.amplitude = factor
            plt.plot(r, s1(r), color=str(0.25 * factor), lw=2)

        plt.axis([-5, 5, -1, 4])
        plt.show()
    r   )r(   Tc             C   s\   |j dkr(tj| dd} | |  n|tj| dd } t|trTt| |jddS | S dS )z'One dimensional Constant model functionr   F)subok)r>   rs   N)	sizer6   
empty_likefillitemrw   r|   r   r>   )r8   r9   r1   r1   r2   r:     s    

zConst1D.evaluatec             C   s   t | }|gS )zDOne dimensional Constant model derivative with respect to parameters)r6   rw   )r8   r9   r<   r1   r1   r2   r=     s    
zConst1D.fit_derivc             C   s   d S )Nr1   )r-   r1   r1   r2   r?     s    zConst1D.input_unitsc             C   s   t d|d fgS )Nr9   r@   )r   )r-   rA   rB   r1   r1   r2   rC     s    z'Const1D._parameter_units_for_data_unitsN)rD   rE   rF   rG   r   r9   r{   rJ   r:   r=   rI   r?   rC   r1   r1   r1   r2   r   e  s   '
c               @   s>   e Zd ZdZeddZdZedd Ze	dd Z
d	d
 ZdS )r   z
    Two dimensional Constant model.

    Parameters
    ----------
    amplitude : float
        Value of the constant function

    See Also
    --------
    Const1D

    Notes
    -----
    Model formula:

        .. math:: f(x, y) = A
    r   )r(   Tc             C   s\   |j dkr(tj| dd} | |  n|tj| dd } t|trTt| |jddS | S dS )z'Two dimensional Constant model functionr   F)r   )r>   rs   N)	r   r6   r   r   r   rw   r|   r   r>   )r8   r@   r9   r1   r1   r2   r:     s    

zConst2D.evaluatec             C   s   d S )Nr1   )r-   r1   r1   r2   r?     s    zConst2D.input_unitsc             C   s   t d|d fgS )Nr9   rm   )r   )r-   rA   rB   r1   r1   r2   rC     s    z'Const2D._parameter_units_for_data_unitsN)rD   rE   rF   rG   r   r9   r{   rJ   r:   rI   r?   rC   r1   r1   r1   r2   r     s   
c               @   sx   e Zd Z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edd Zed	d
 Zdd ZdS )r   aA  
    A 2D Ellipse model.

    Parameters
    ----------
    amplitude : float
        Value of the ellipse.

    x_0 : float
        x position of the center of the disk.

    y_0 : float
        y position of the center of the disk.

    a : float
        The length of the semimajor axis.

    b : float
        The length of the semiminor axis.

    theta : float
        The rotation angle in radians of the semimajor axis.  The
        rotation angle increases counterclockwise from the positive x
        axis.

    See Also
    --------
    Disk2D, Box2D

    Notes
    -----
    Model formula:

    .. math::

        f(x, y) = \left \{
                    \begin{array}{ll}
                      \mathrm{amplitude} & : \left[\frac{(x - x_0) \cos
                        \theta + (y - y_0) \sin \theta}{a}\right]^2 +
                        \left[\frac{-(x - x_0) \sin \theta + (y - y_0)
                        \cos \theta}{b}\right]^2  \leq 1 \\
                      0 & : \mathrm{otherwise}
                    \end{array}
                  \right.

    Examples
    --------
    .. plot::
        :include-source:

        import numpy as np
        from astropy.modeling.models import Ellipse2D
        from astropy.coordinates import Angle
        import matplotlib.pyplot as plt
        import matplotlib.patches as mpatches
        x0, y0 = 25, 25
        a, b = 20, 10
        theta = Angle(30, 'deg')
        e = Ellipse2D(amplitude=100., x_0=x0, y_0=y0, a=a, b=b,
                      theta=theta.radian)
        y, x = np.mgrid[0:50, 0:50]
        fig, ax = plt.subplots(1, 1)
        ax.imshow(e(x, y), origin='lower', interpolation='none', cmap='Greys_r')
        e2 = mpatches.Ellipse((x0, y0), 2*a, 2*b, theta.degree, edgecolor='red',
                              facecolor='none')
        ax.add_patch(e2)
        plt.show()
    r   )r(   r   c             C   s   | | }|| }	t |}
t |}||
 |	|  }||  |	|
  }|| d || d  dk}t |g|g}t|trt||jddS |S dS )z'Two dimensional Ellipse model function.r'   g      ?F)r>   rs   N)r6   r`   ra   selectr|   r   r>   )r8   r@   r9   r   y_0r]   r^   rO   ZxxZyyrj   rk   Z
numerator1Z
numerator2Z
in_ellipseresultr1   r1   r2   r:   0  s    


zEllipse2D.evaluatec             C   sL   | j }| j}| jj}t|||\}}| j| | j| f| j| | j| ffS )zu
        Tuple defining the default ``bounding_box`` limits.

        ``((y_low, y_high), (x_low, x_high))``
        )r]   r^   rO   r\   r	   r   r   )r-   r]   r^   rO   r0   r_   r1   r1   r2   r3   B  s    zEllipse2D.bounding_boxc             C   s&   | j jd krd S | j j| jjdS d S )N)r8   r@   )r   r>   r   )r-   r1   r1   r2   r?   R  s    zEllipse2D.input_unitsc          	   C   sZ   |d |d krt dtd|d fd|d fd|d fd|d fdtjfd	|d
 fgS )Nr8   r@   z(Units of 'x' and 'y' inputs should matchr   r   r]   r^   rO   r9   rm   )r   r   rn   ro   )r-   rA   rB   r1   r1   r2   rC   Z  s    


z)Ellipse2D._parameter_units_for_data_unitsN)rD   rE   rF   rG   r   r9   r   r   r]   r^   rO   rJ   r:   rI   r3   r?   rC   r1   r1   r1   r2   r     s   D





c               @   sd   e Zd Z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dS )r   af  
    Two dimensional radial symmetric Disk model.

    Parameters
    ----------
    amplitude : float
        Value of the disk function
    x_0 : float
        x position center of the disk
    y_0 : float
        y position center of the disk
    R_0 : float
        Radius of the disk

    See Also
    --------
    Box2D, TrapezoidDisk2D

    Notes
    -----
    Model formula:

        .. math::

            f(r) = \left \{
                     \begin{array}{ll}
                       A & : r \leq R_0 \\
                       0 & : r > R_0
                     \end{array}
                   \right.
    r   )r(   r   c             C   sR   | | d || d  }t ||d kg|g}t|trJt||jddS |S dS )z#Two dimensional Disk model functionr'   F)r>   rs   N)r6   r   r|   r   r>   )r8   r@   r9   r   r   R_0rrr   r1   r1   r2   r:     s
    
zDisk2D.evaluatec             C   s0   | j | j | j | j f| j| j | j| j ffS )zu
        Tuple defining the default ``bounding_box`` limits.

        ``((y_low, y_high), (x_low, x_high))``
        )r   r   r   )r-   r1   r1   r2   r3     s    zDisk2D.bounding_boxc             C   s2   | j jd kr| jjd krd S | j j| jjdS d S )N)r8   r@   )r   r>   r   )r-   r1   r1   r2   r?     s    zDisk2D.input_unitsc             C   sH   |d |d krt dtd|d fd|d fd|d fd|d fgS )	Nr8   r@   z(Units of 'x' and 'y' inputs should matchr   r   r   r9   rm   )r   r   )r-   rA   rB   r1   r1   r2   rC     s    

z&Disk2D._parameter_units_for_data_unitsN)rD   rE   rF   rG   r   r9   r   r   r   rJ   r:   rI   r3   r?   rC   r1   r1   r1   r2   r   h  s   



c                   s   e Zd ZdZeddZeddZeddZeddZeddZ	ej
ej
ej
ej
e	j
df fdd	Zedd	 Zed
d Zedd Zdd Z  ZS )r%   a7  
    Two dimensional radial symmetric Ring model.

    Parameters
    ----------
    amplitude : float
        Value of the disk function
    x_0 : float
        x position center of the disk
    y_0 : float
        y position center of the disk
    r_in : float
        Inner radius of the ring
    width : float
        Width of the ring.
    r_out : float
        Outer Radius of the ring. Can be specified instead of width.

    See Also
    --------
    Disk2D, TrapezoidDisk2D

    Notes
    -----
    Model formula:

        .. math::

            f(r) = \left \{
                     \begin{array}{ll}
                       A & : r_{in} \leq r \leq r_{out} \\
                       0 & : \text{else}
                     \end{array}
                   \right.

    Where :math:`r_{out} = r_{in} + r_{width}`.
    r   )r(   r   Nc                sX   |d k	r&|| j jkrtd|| }n|d kr6| j j}t jf |||||d| d S )Nz6Cannot specify both width and outer radius separately.)r9   r   r   r_inwidth)r   r(   r   rV   rW   )r-   r9   r   r   r   r   Zr_outrX   )rP   r1   r2   rW     s    
zRing2D.__init__c       
      C   sj   | | d || d  }t ||d k||| d k}t |g|g}	t|trbt|	|jddS |	S dS )z$Two dimensional Ring model function.r'   F)r>   rs   N)r6   logical_andr   r|   r   r>   )
r8   r@   r9   r   r   r   r   r   Zr_ranger   r1   r1   r2   r:     s     
zRing2D.evaluatec             C   s4   | j | j }| j| | j| f| j| | j| ffS )zn
        Tuple defining the default ``bounding_box``.

        ``((y_low, y_high), (x_low, x_high))``
        )r   r   r   r   )r-   drr1   r1   r2   r3     s    zRing2D.bounding_boxc             C   s&   | j jd krd S | j j| jjdS d S )N)r8   r@   )r   r>   r   )r-   r1   r1   r2   r?     s    zRing2D.input_unitsc             C   sR   |d |d krt dtd|d fd|d fd|d fd|d fd|d	 fgS )
Nr8   r@   z(Units of 'x' and 'y' inputs should matchr   r   r   r   r9   rm   )r   r   )r-   rA   rB   r1   r1   r2   rC     s    


z&Ring2D._parameter_units_for_data_units)rD   rE   rF   rG   r   r9   r   r   r   r   r(   rW   rJ   r:   rI   r3   r?   rC   rp   r1   r1   )rP   r2   r%     s   %




c               @   s   e Zd ZdZdd ZdS )Delta1Dz%One dimensional Dirac delta function.c             C   s   t dd S )NzNot implemented)r   )r-   r1   r1   r2   rW   (  s    zDelta1D.__init__N)rD   rE   rF   rG   rW   r1   r1   r1   r2   r   %  s   r   c               @   s   e Zd ZdZdd ZdS )Delta2Dz%Two dimensional Dirac delta function.c             C   s   t dd S )NzNot implemented)r   )r-   r1   r1   r2   rW   /  s    zDelta2D.__init__N)rD   rE   rF   rG   rW   r1   r1   r1   r2   r   ,  s   r   c               @   sZ   e Zd Z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dS )r   a  
    One dimensional Box model.

    Parameters
    ----------
    amplitude : float
        Amplitude A
    x_0 : float
        Position of the center of the box function
    width : float
        Width of the box

    See Also
    --------
    Box2D, TrapezoidDisk2D

    Notes
    -----
    Model formula:

      .. math::

            f(x) = \left \{
                     \begin{array}{ll}
                       A & : x_0 - w/2 \leq x \leq x_0 + w/2 \\
                       0 & : \text{else}
                     \end{array}
                   \right.

    Examples
    --------
    .. plot::
        :include-source:

        import numpy as np
        import matplotlib.pyplot as plt

        from astropy.modeling.models import Box1D

        plt.figure()
        s1 = Box1D()
        r = np.arange(-5, 5, .01)

        for factor in range(1, 4):
            s1.amplitude = factor
            s1.width = factor
            plt.plot(r, s1(r), color=str(0.25 * factor), lw=2)

        plt.axis([-5, 5, -1, 4])
        plt.show()
    r   )r(   r   c             C   sX   t | ||d  k| ||d  k}t |g|gd}t|trPt||jddS |S dS )z"One dimensional Box model functiong       @r   F)r>   rs   N)r6   r   r   r|   r   r>   )r8   r9   r   r   Zinsider   r1   r1   r2   r:   l  s
    $
zBox1D.evaluatec             C   s   | j d }| j| | j| fS )zc
        Tuple defining the default ``bounding_box`` limits.

        ``(x_low, x_high))``
        r'   )r   r   )r-   r0   r1   r1   r2   r3   x  s    
zBox1D.bounding_boxc             C   s    | j jd krd S d| j jiS d S )Nr8   )r   r>   )r-   r1   r1   r2   r?     s    zBox1D.input_unitsc             C   s&   t d|d fd|d fd|d fgS )Nr   r8   r   r9   r@   )r   )r-   rA   rB   r1   r1   r2   rC     s    
z%Box1D._parameter_units_for_data_unitsN)rD   rE   rF   rG   r   r9   r   r   rJ   r:   rI   r3   r?   rC   r1   r1   r1   r2   r   3  s   3


c               @   sn   e Zd Z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ed	d
 Zdd ZdS )r   a  
    Two dimensional Box model.

    Parameters
    ----------
    amplitude : float
        Amplitude A
    x_0 : float
        x position of the center of the box function
    x_width : float
        Width in x direction of the box
    y_0 : float
        y position of the center of the box function
    y_width : float
        Width in y direction of the box

    See Also
    --------
    Box1D, Gaussian2D, Moffat2D

    Notes
    -----
    Model formula:

      .. math::

            f(x, y) = \left \{
                     \begin{array}{ll}
            A : & x_0 - w_x/2 \leq x \leq x_0 + w_x/2 \text{ and} \\
                & y_0 - w_y/2 \leq y \leq y_0 + w_y/2 \\
            0 : & \text{else}
                     \end{array}
                   \right.

    r   )r(   r   c       
      C   s   t | ||d  k| ||d  k}t |||d  k|||d  k}t t ||g|gd}	t|tr|t|	|jddS |	S dS )z"Two dimensional Box model functiong       @r   F)r>   rs   N)r6   r   r   r|   r   r>   )
r8   r@   r9   r   r   x_widthy_widthZx_rangeZy_ranger   r1   r1   r2   r:     s    
zBox2D.evaluatec             C   s<   | j d }| jd }| j| | j| f| j| | j| ffS )zn
        Tuple defining the default ``bounding_box``.

        ``((y_low, y_high), (x_low, x_high))``
        r'   )r   r   r   r   )r-   r0   r_   r1   r1   r2   r3     s    

zBox2D.bounding_boxc             C   s&   | j jd krd S | j j| jjdS d S )N)r8   r@   )r   r>   r   )r-   r1   r1   r2   r?     s    zBox2D.input_unitsc             C   s:   t d|d fd|d fd|d fd|d fd|d fgS )	Nr   r8   r   r@   r   r   r9   rm   )r   )r-   rA   rB   r1   r1   r2   rC     s
    


z%Box2D._parameter_units_for_data_unitsN)rD   rE   rF   rG   r   r9   r   r   r   r   rJ   r:   rI   r3   r?   rC   r1   r1   r1   r2   r     s   #




c               @   sd   e Zd Z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dS )r#   ae  
    One dimensional Trapezoid model.

    Parameters
    ----------
    amplitude : float
        Amplitude of the trapezoid
    x_0 : float
        Center position of the trapezoid
    width : float
        Width of the constant part of the trapezoid.
    slope : float
        Slope of the tails of the trapezoid

    See Also
    --------
    Box1D, Gaussian1D, Moffat1D

    Examples
    --------
    .. plot::
        :include-source:

        import numpy as np
        import matplotlib.pyplot as plt

        from astropy.modeling.models import Trapezoid1D

        plt.figure()
        s1 = Trapezoid1D()
        r = np.arange(-5, 5, .01)

        for factor in range(1, 4):
            s1.amplitude = factor
            s1.width = factor
            plt.plot(r, s1(r), color=str(0.25 * factor), lw=2)

        plt.axis([-5, 5, -1, 4])
        plt.show()
    r   )r(   r   c             C   s   ||d  }||d  }|||  }|||  }t | |k| |k }	t | |k| |k }
t | |k| |k }|| |  }|}|||   }t |	|
|g|||g}t|trt||jddS |S dS )z(One dimensional Trapezoid model functiong       @F)r>   rs   N)r6   r   r   r|   r   r>   )r8   r9   r   r   r   Zx2Zx3Zx1Zx4Zrange_aZrange_bZrange_cZval_aZval_bZval_cr   r1   r1   r2   r:     s    
zTrapezoid1D.evaluatec             C   s*   | j d | j| j  }| j| | j| fS )zc
        Tuple defining the default ``bounding_box`` limits.

        ``(x_low, x_high))``
        r'   )r   r9   r   r   )r-   r0   r1   r1   r2   r3   2  s    zTrapezoid1D.bounding_boxc             C   s    | j jd krd S d| j jiS d S )Nr8   )r   r>   )r-   r1   r1   r2   r?   >  s    zTrapezoid1D.input_unitsc             C   s8   t d|d fd|d fd|d |d  fd|d fgS )Nr   r8   r   r   r@   r9   )r   )r-   rA   rB   r1   r1   r2   rC   E  s    
z+Trapezoid1D._parameter_units_for_data_unitsN)rD   rE   rF   rG   r   r9   r   r   r   rJ   r:   rI   r3   r?   rC   r1   r1   r1   r2   r#     s   (



c               @   sn   e Zd Z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ed	d
 Zdd ZdS )r$   a  
    Two dimensional circular Trapezoid model.

    Parameters
    ----------
    amplitude : float
        Amplitude of the trapezoid
    x_0 : float
        x position of the center of the trapezoid
    y_0 : float
        y position of the center of the trapezoid
    R_0 : float
        Radius of the constant part of the trapezoid.
    slope : float
        Slope of the tails of the trapezoid in x direction.

    See Also
    --------
    Disk2D, Box2D
    r   )r(   r   c             C   s   t | | d || d  }||k}t ||k||||  k}	|}
||||   }t ||	g|
|g}t|trt||jddS |S dS )z-Two dimensional Trapezoid Disk model functionr'   F)r>   rs   N)r6   rT   r   r   r|   r   r>   )r8   r@   r9   r   r   r   r   r   Zrange_1Zrange_2Zval_1Zval_2r   r1   r1   r2   r:   h  s    
zTrapezoidDisk2D.evaluatec             C   s:   | j | j| j  }| j| | j| f| j| | j| ffS )zn
        Tuple defining the default ``bounding_box``.

        ``((y_low, y_high), (x_low, x_high))``
        )r   r9   r   r   r   )r-   r   r1   r1   r2   r3   x  s    zTrapezoidDisk2D.bounding_boxc             C   s2   | j jd kr| jjd krd S | j j| jjdS d S )N)r8   r@   )r   r>   r   )r-   r1   r1   r2   r?     s    zTrapezoidDisk2D.input_unitsc             C   sZ   |d |d krt dtd|d fd|d fd|d fd|d |d  fd	|d fgS )
Nr8   r@   z(Units of 'x' and 'y' inputs should matchr   r   r   r   rm   r9   )r   r   )r-   rA   rB   r1   r1   r2   rC     s    

z/TrapezoidDisk2D._parameter_units_for_data_unitsN)rD   rE   rF   rG   r   r9   r   r   r   r   rJ   r:   rI   r3   r?   rC   r1   r1   r1   r2   r$   L  s   




c               @   sX   e Zd ZdZeddZeddZeddZedd Z	ddd	Z
ed
d Zdd ZdS )r   a  
    One dimensional Mexican Hat model.

    Parameters
    ----------
    amplitude : float
        Amplitude
    x_0 : float
        Position of the peak
    sigma : float
        Width of the Mexican hat

    See Also
    --------
    MexicanHat2D, Box1D, Gaussian1D, Trapezoid1D

    Notes
    -----
    Model formula:

    .. math::

        f(x) = {A \left(1 - \frac{\left(x - x_{0}\right)^{2}}{\sigma^{2}}\right)
        e^{- \frac{\left(x - x_{0}\right)^{2}}{2 \sigma^{2}}}}

    Examples
    --------
    .. plot::
        :include-source:

        import numpy as np
        import matplotlib.pyplot as plt

        from astropy.modeling.models import MexicanHat1D

        plt.figure()
        s1 = MexicanHat1D()
        r = np.arange(-5, 5, .01)

        for factor in range(1, 4):
            s1.amplitude = factor
            s1.width = factor
            plt.plot(r, s1(r), color=str(0.25 * factor), lw=2)

        plt.axis([-5, 5, -2, 4])
        plt.show()
    r   )r(   r   c             C   s4   | | d d|d   }|dd|   t |  S )z*One dimensional Mexican Hat model functionr'   r   )r6   r7   )r8   r9   r   sigmaZxx_wwr1   r1   r2   r:     s    zMexicanHat1D.evaluate      $@c             C   s    | j }|| j }|| || fS )zTuple defining the default ``bounding_box`` limits,
        ``(x_low, x_high)``.

        Parameters
        ----------
        factor : float
            The multiple of sigma used to define the limits.

        )r   r   )r-   r.   r/   r0   r1   r1   r2   r3     s    

zMexicanHat1D.bounding_boxc             C   s    | j jd krd S d| j jiS d S )Nr8   )r   r>   )r-   r1   r1   r2   r?     s    zMexicanHat1D.input_unitsc             C   s&   t d|d fd|d fd|d fgS )Nr   r8   r   r9   r@   )r   )r-   rA   rB   r1   r1   r2   rC     s    
z,MexicanHat1D._parameter_units_for_data_unitsN)r   )rD   rE   rF   rG   r   r9   r   r   rJ   r:   r3   rI   r?   rC   r1   r1   r1   r2   r     s   /



c               @   sX   e Zd Z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dS )r   aY  
    Two dimensional symmetric Mexican Hat model.

    Parameters
    ----------
    amplitude : float
        Amplitude
    x_0 : float
        x position of the peak
    y_0 : float
        y position of the peak
    sigma : float
        Width of the Mexican hat

    See Also
    --------
    MexicanHat1D, Gaussian2D

    Notes
    -----
    Model formula:

    .. math::

        f(x, y) = A \left(1 - \frac{\left(x - x_{0}\right)^{2}
        + \left(y - y_{0}\right)^{2}}{\sigma^{2}}\right)
        e^{\frac{- \left(x - x_{0}\right)^{2}
        - \left(y - y_{0}\right)^{2}}{2 \sigma^{2}}}
    r   )r(   r   c             C   s<   | | d || d  d|d   }|d|  t |  S )z*Two dimensional Mexican Hat model functionr'   r   )r6   r7   )r8   r@   r9   r   r   r   Zrr_wwr1   r1   r2   r:     s    $zMexicanHat2D.evaluatec             C   s&   | j jd krd S | j j| jjdS d S )N)r8   r@   )r   r>   r   )r-   r1   r1   r2   r?     s    zMexicanHat2D.input_unitsc             C   sH   |d |d krt dtd|d fd|d fd|d fd|d fgS )	Nr8   r@   z(Units of 'x' and 'y' inputs should matchr   r   r   r9   rm   )r   r   )r-   rA   rB   r1   r1   r2   rC   %  s    

z,MexicanHat2D._parameter_units_for_data_unitsN)rD   rE   rF   rG   r   r9   r   r   r   rJ   r:   rI   r?   rC   r1   r1   r1   r2   r     s   



c               @   s`   e Zd ZdZeddZeddZeddZeddZdZ	dZ
edd Zedd	 Zd
d ZdS )r   a  
    Two dimensional Airy disk model.

    Parameters
    ----------
    amplitude : float
        Amplitude of the Airy function.
    x_0 : float
        x position of the maximum of the Airy function.
    y_0 : float
        y position of the maximum of the Airy function.
    radius : float
        The radius of the Airy disk (radius of the first zero).

    See Also
    --------
    Box2D, TrapezoidDisk2D, Gaussian2D

    Notes
    -----
    Model formula:

        .. math:: f(r) = A \left[\frac{2 J_1(\frac{\pi r}{R/R_z})}{\frac{\pi r}{R/R_z}}\right]^2

    Where :math:`J_1` is the first order Bessel function of the first
    kind, :math:`r` is radial distance from the maximum of the Airy
    function (:math:`r = \sqrt{(x - x_0)^2 + (y - y_0)^2}`), :math:`R`
    is the input ``radius`` parameter, and :math:`R_z =
    1.2196698912665045`).

    For an optical system, the radius of the first zero represents the
    limiting angular resolution and is approximately 1.22 * lambda / D,
    where lambda is the wavelength of the light and D is the diameter of
    the aperture.

    See [1]_ for more details about the Airy disk.

    References
    ----------
    .. [1] https://en.wikipedia.org/wiki/Airy_disk
    r   )r(   r   Nc             C   s   | j dkrXy0ddlm}m} |ddd tj | _ || _W n tk
rV   tdY nX t	|| d || d  || j   }	t
|	tr|	tj}	t|	j}
tj|	|	dk  }d| | | d |
|	dk< t
|trt|
tjdd	}
|
|9 }
|
S )
z#Two dimensional Airy model functionNr   )j1jn_zerosr   z'AiryDisk2D model requires scipy > 0.11.r'   g       @F)rs   )_rzr   r   r   r6   r   _j1rS   r   rT   r|   r   Zto_valuern   Zdimensionless_unscaledZonesrR   )r   r8   r@   r9   r   r   radiusr   r   r   rm   Zrtr1   r1   r2   r:   c  s"    

(

zAiryDisk2D.evaluatec             C   s&   | j jd krd S | j j| jjdS d S )N)r8   r@   )r   r>   r   )r-   r1   r1   r2   r?     s    zAiryDisk2D.input_unitsc             C   sH   |d |d krt dtd|d fd|d fd|d fd|d fgS )	Nr8   r@   z(Units of 'x' and 'y' inputs should matchr   r   r   r9   rm   )r   r   )r-   rA   rB   r1   r1   r2   rC     s    

z*AiryDisk2D._parameter_units_for_data_units)rD   rE   rF   rG   r   r9   r   r   r   r   r   r   r:   rI   r?   rC   r1   r1   r1   r2   r   1  s   )



c               @   sp   e Zd Z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e	dd Zdd ZdS )r   a  
    One dimensional Moffat model.

    Parameters
    ----------
    amplitude : float
        Amplitude of the model.
    x_0 : float
        x position of the maximum of the Moffat model.
    gamma : float
        Core width of the Moffat model.
    alpha : float
        Power index of the Moffat model.

    See Also
    --------
    Gaussian1D, Box1D

    Notes
    -----
    Model formula:

    .. math::

        f(x) = A \left(1 + \frac{\left(x - x_{0}\right)^{2}}{\gamma^{2}}\right)^{- \alpha}

    Examples
    --------
    .. plot::
        :include-source:

        import numpy as np
        import matplotlib.pyplot as plt

        from astropy.modeling.models import Moffat1D

        plt.figure()
        s1 = Moffat1D()
        r = np.arange(-5, 5, .01)

        for factor in range(1, 4):
            s1.amplitude = factor
            s1.width = factor
            plt.plot(r, s1(r), color=str(0.25 * factor), lw=2)

        plt.axis([-5, 5, -1, 4])
        plt.show()
    r   )r(   r   c             C   s"   d| j  tdd| j  d  S )z
        Moffat full width at half maximum.
        Derivation of the formula is available in
        `this notebook by Yoonsoo Bach <http://nbviewer.jupyter.org/github/ysbach/AO_2017/blob/master/04_Ground_Based_Concept.ipynb#1.2.-Moffat>`_.
        g       @g      ?)gammar6   rT   r   )r-   r1   r1   r2   r5     s    zMoffat1D.fwhmc             C   s   |d| | | d  |   S )z%One dimensional Moffat model functionr   r'   r1   )r8   r9   r   r   r   r1   r1   r2   r:     s    zMoffat1D.evaluatec       
      C   s   d| | d |d   }||  }d| | | |  | ||d   }d| | | | d  | ||d   }| | t | }	||||	gS )zBOne dimensional Moffat model derivative with respect to parametersr   r'   r;   )r6   r   )
r8   r9   r   r   r   Zfacd_Ar   d_gammad_alphar1   r1   r2   r=     s    
$zMoffat1D.fit_derivc             C   s    | j jd krd S d| j jiS d S )Nr8   )r   r>   )r-   r1   r1   r2   r?     s    zMoffat1D.input_unitsc             C   s&   t d|d fd|d fd|d fgS )Nr   r8   r   r9   r@   )r   )r-   rA   rB   r1   r1   r2   rC     s    
z(Moffat1D._parameter_units_for_data_unitsN)rD   rE   rF   rG   r   r9   r   r   r   rI   r5   rJ   r:   r=   r?   rC   r1   r1   r1   r2   r     s   0



	c               @   sz   e Zd Z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ed	d
 Ze
dd Zdd ZdS )r   ak  
    Two dimensional Moffat model.

    Parameters
    ----------
    amplitude : float
        Amplitude of the model.
    x_0 : float
        x position of the maximum of the Moffat model.
    y_0 : float
        y position of the maximum of the Moffat model.
    gamma : float
        Core width of the Moffat model.
    alpha : float
        Power index of the Moffat model.

    See Also
    --------
    Gaussian2D, Box2D

    Notes
    -----
    Model formula:

    .. math::

        f(x, y) = A \left(1 + \frac{\left(x - x_{0}\right)^{2} +
        \left(y - y_{0}\right)^{2}}{\gamma^{2}}\right)^{- \alpha}
    r   )r(   r   c             C   s"   d| j  tdd| j  d  S )z
        Moffat full width at half maximum.
        Derivation of the formula is available in
        `this notebook by Yoonsoo Bach <http://nbviewer.jupyter.org/github/ysbach/AO_2017/blob/master/04_Ground_Based_Concept.ipynb#1.2.-Moffat>`_.
        g       @g      ?)r   r6   rT   r   )r-   r1   r1   r2   r5   	  s    zMoffat2D.fwhmc             C   s2   | | d || d  |d  }|d| |   S )z%Two dimensional Moffat model functionr'   r   r1   )r8   r@   r9   r   r   r   r   rr_ggr1   r1   r2   r:   #	  s     zMoffat2D.evaluatec             C   s   | | d || d  |d  }d| |  }d| | | | |  |d d|   }	d| | | ||  |d d|   }
| | t d|  }d| | | | |d d|   }||	|
||gS )zBTwo dimensional Moffat model derivative with respect to parametersr'   r   r;   )r6   r   )r8   r@   r9   r   r   r   r   r   r   r   Zd_y_0r   r   r1   r1   r2   r=   *	  s     zMoffat2D.fit_derivc             C   s&   | j jd krd S | j j| jjdS d S )N)r8   r@   )r   r>   r   )r-   r1   r1   r2   r?   9	  s    zMoffat2D.input_unitsc             C   sH   |d |d krt dtd|d fd|d fd|d fd|d fgS )	Nr8   r@   z(Units of 'x' and 'y' inputs should matchr   r   r   r9   rm   )r   r   )r-   rA   rB   r1   r1   r2   rC   A	  s    

z(Moffat2D._parameter_units_for_data_unitsN)rD   rE   rF   rG   r   r9   r   r   r   r   rI   r5   rJ   r:   r=   r?   rC   r1   r1   r1   r2   r     s   




	c               @   sz   e Zd Z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Zedd Zed	d
 Zdd ZdS )r    a  
    Two dimensional Sersic surface brightness profile.

    Parameters
    ----------
    amplitude : float
        Surface brightness at r_eff.
    r_eff : float
        Effective (half-light) radius
    n : float
        Sersic Index.
    x_0 : float, optional
        x position of the center.
    y_0 : float, optional
        y position of the center.
    ellip : float, optional
        Ellipticity.
    theta : float, optional
        Rotation angle in radians, counterclockwise from
        the positive x-axis.

    See Also
    --------
    Gaussian2D, Moffat2D

    Notes
    -----
    Model formula:

    .. math::

        I(x,y) = I(r) = I_e\exp\left\{-b_n\left[\left(\frac{r}{r_{e}}\right)^{(1/n)}-1\right]\right\}

    The constant :math:`b_n` is defined such that :math:`r_e` contains half the total
    luminosity, and can be solved for numerically.

    .. math::

        \Gamma(2n) = 2\gamma (b_n,2n)

    Examples
    --------
    .. plot::
        :include-source:

        import numpy as np
        from astropy.modeling.models import Sersic2D
        import matplotlib.pyplot as plt

        x,y = np.meshgrid(np.arange(100), np.arange(100))

        mod = Sersic2D(amplitude = 1, r_eff = 25, n=4, x_0=50, y_0=50,
                       ellip=.5, theta=-1)
        img = mod(x, y)
        log_img = np.log10(img)


        plt.figure()
        plt.imshow(log_img, origin='lower', interpolation='nearest',
                   vmin=-1, vmax=2)
        plt.xlabel('x')
        plt.ylabel('y')
        cbar = plt.colorbar()
        cbar.set_label('Log Brightness', rotation=270, labelpad=25)
        cbar.set_ticks([-1, 0, 1, 2], update_ticks=True)
        plt.show()

    References
    ----------
    .. [1] http://ned.ipac.caltech.edu/level5/March05/Graham/Graham2.html
    r   )r(   r   r   Nc
             C   s   | j dkr>yddlm}
 |
| _ W n tk
r<   tdY nX |  d| d}|d| |  }}t|	t|	 }}|| | || |  }||  | || |  }t|| d || d  }|t	| |d|  d   S )	z(Two dimensional Sersic profile function.Nr   )r   z%Sersic2D model requires scipy > 0.11.g       @g      ?r   r'   )
r   r   r   rS   r   r6   r`   ra   rT   r7   )r   r8   r@   r9   r   r   r   r   elliprO   r   Zbnr]   r^   Z	cos_thetaZ	sin_thetaZx_majZx_minrm   r1   r1   r2   r:   	  s    

zSersic2D.evaluatec             C   s&   | j jd krd S | j j| jjdS d S )N)r8   r@   )r   r>   r   )r-   r1   r1   r2   r?   	  s    zSersic2D.input_unitsc             C   sP   |d |d krt dtd|d fd|d fd|d fdtjfd|d	 fgS )
Nr8   r@   z(Units of 'x' and 'y' inputs should matchr   r   r   rO   r9   rm   )r   r   rn   ro   )r-   rA   rB   r1   r1   r2   rC   	  s    

z(Sersic2D._parameter_units_for_data_units)rD   rE   rF   rG   r   r9   r   r   r   r   r   rO   r   r   r:   rI   r?   rC   r1   r1   r1   r2   r    M	  s   G






)<rG   collectionsr   Znumpyr6   Zcorer   r   r   Z
parametersr   r   Zutilsr	   Zastropyr
   rn   Zastropy.unitsr   r   __all__r   r   floatZfinfoZfloat32ZtinyrH   rT   r   r4   r   r   r!   r   r   r   r   r"   r   r   r   r&   r   r   r   r   r%   r   r   r   r   r#   r$   r   r   r   r   r   r    r1   r1   r1   r2   <module>   sb   

   09%(_V;/ciM1 Ql^YbNX?e_X