B
    q\
*                 @   s   d dl Z d dlZd dlmZmZ dgZG dd deZG dd deZ	dd	 Z
d
d Zdd Zdd Zd#ddZdd Zdd Zdd Zdd Zd$ddZd%ddZdd  Zd!d" ZdS )&    N)FittableModelcustom_modeldiscretize_modelc               @   s   e Zd ZdZdS )DiscretizationErrorz:
    Called when discretization of models goes wrong.
    N)__name__
__module____qualname____doc__ r
   r
   8lib/python3.7/site-packages/astropy/convolution/utils.pyr   
   s   r   c               @   s   e Zd ZdZdS )KernelSizeErrorz.
    Called when size of kernels is even.
    N)r   r   r   r	   r
   r
   r
   r   r      s   r   c             C   s4   t | ttfrt| d  S tdd | jD S d S )N   c             s   s   | ]}|d   V  qdS )r   Nr
   ).0	axes_sizer
   r
   r   	<genexpr>   s    z has_even_axis.<locals>.<genexpr>)
isinstancelisttuplelenanyshape)arrayr
   r
   r   has_even_axis   s    r   c               C   s   t dd S )Nz$Kernel size must be odd in all axes.)r   r
   r
   r
   r   raise_even_kernel_exception   s    r   c             C   s   | j |j krT|  }| j d }t||j d  ||j d  d }||  |7  < |S |j | j kr| }|j d }t|| j d  || j d  d }||  | 7  < |S ||  S )zw
    Add two 1D kernel arrays of different size.

    The arrays are added with the centers lying upon each other.
    r      )sizecopyslice)array_1array_2	new_arraycenterZslice_r
   r
   r   add_kernel_arrays_1D   s    

r"   c             C   sJ  | j |j kr|  }dd | jD }t|d |jd d  |d |jd d  d }t|d |jd d  |d |jd d  d }|||f  |7  < |S |j | j krB| }dd |jD }t|d | jd d  |d | jd d  d }t|d | jd d  |d | jd d  d }|||f  | 7  < |S ||  S )zw
    Add two 2D kernel arrays of different size.

    The arrays are added with the centers lying upon each other.
    c             S   s   g | ]}|d  qS )r   r
   )r   r   r
   r
   r   
<listcomp>=   s    z(add_kernel_arrays_2D.<locals>.<listcomp>r   r   r   c             S   s   g | ]}|d  qS )r   r
   )r   r   r
   r
   r   r#   F   s    )r   r   r   r   )r   r   r    r!   Zslice_xZslice_yr
   r
   r   add_kernel_arrays_2D5   s&    r$   r!   
   c             C   s  t | stdt| ts$t|  } | j}|dkr:tdtt	|
 sTtd|rrtt	|
 srtd|dkr|dkrtd|dkr|dk	rtd	|d
kr|dkrt| |S |dkrt| ||S n|dkr|dkrt| |S |dkr~t| ||S nx|dkr@|dkr&t| ||S |dkr~t| |||S n>|dkrv|dkr^t| |S |dkr~t| ||S ntddS )a
  
    Function to evaluate analytical model functions on a grid.

    So far the function can only deal with pixel coordinates.

    Parameters
    ----------
    model : `~astropy.modeling.FittableModel` or callable.
        Analytic model function to be discretized. Callables, which are not an
        instances of `~astropy.modeling.FittableModel` are passed to
        `~astropy.modeling.custom_model` and then evaluated.
    x_range : tuple
        x range in which the model is evaluated. The difference between the
        upper an lower limit must be a whole number, so that the output array
        size is well defined.
    y_range : tuple, optional
        y range in which the model is evaluated. The difference between the
        upper an lower limit must be a whole number, so that the output array
        size is well defined. Necessary only for 2D models.
    mode : str, optional
        One of the following modes:
            * ``'center'`` (default)
                Discretize model by taking the value
                at the center of the bin.
            * ``'linear_interp'``
                Discretize model by linearly interpolating
                between the values at the corners of the bin.
                For 2D models interpolation is bilinear.
            * ``'oversample'``
                Discretize model by taking the average
                on an oversampled grid.
            * ``'integrate'``
                Discretize model by integrating the model
                over the bin using `scipy.integrate.quad`.
                Very slow.
    factor : float or int
        Factor of oversampling. Default = 10.

    Returns
    -------
    array : `numpy.array`
        Model value array

    Notes
    -----
    The ``oversample`` mode allows to conserve the integral on a subpixel
    scale. Here is the example of a normalized Gaussian1D:

    .. plot::
        :include-source:

        import matplotlib.pyplot as plt
        import numpy as np
        from astropy.modeling.models import Gaussian1D
        from astropy.convolution.utils import discretize_model
        gauss_1D = Gaussian1D(1 / (0.5 * np.sqrt(2 * np.pi)), 0, 0.5)
        y_center = discretize_model(gauss_1D, (-2, 3), mode='center')
        y_corner = discretize_model(gauss_1D, (-2, 3), mode='linear_interp')
        y_oversample = discretize_model(gauss_1D, (-2, 3), mode='oversample')
        plt.plot(y_center, label='center sum = {0:3f}'.format(y_center.sum()))
        plt.plot(y_corner, label='linear_interp sum = {0:3f}'.format(y_corner.sum()))
        plt.plot(y_oversample, label='oversample sum = {0:3f}'.format(y_oversample.sum()))
        plt.xlabel('pixels')
        plt.ylabel('value')
        plt.legend()
        plt.show()


    zModel must be callable.r   z2discretize_model only supports 1-d and 2-d models.zTThe difference between the upper an lower limit of 'x_range' must be a whole number.zTThe difference between the upper an lower limit of 'y_range' must be a whole number.Nz'y range not specified, but model is 2-dr   z)y range specified, but model is only 1-d.r!   Zlinear_interpZ
oversampleZ	integratezInvalid mode.)callable	TypeErrorr   r   r   Zn_inputs
ValueErrorfloatnpZdiff
is_integerdiscretize_center_1Ddiscretize_center_2Ddiscretize_linear_1Ddiscretize_bilinear_2Ddiscretize_oversample_1Ddiscretize_oversample_2Ddiscretize_integrate_1Ddiscretize_integrate_2Dr   )modelx_rangey_rangemodefactorndimr
   r
   r   r   P   sJ    F












c             C   s   t j| }| |S )zH
    Discretize model by taking the value at the center of the bin.
    )r*   arange)r4   r5   xr
   r
   r   r,      s    
r,   c             C   s.   t j| }t j| }t ||\}}| ||S )zJ
    Discretize model by taking the value at the center of the pixel.
    )r*   r:   meshgrid)r4   r5   r6   r;   yr
   r
   r   r-      s    

r-   c             C   s@   t |d d |d d }| |}d|dd |dd   S )z@
    Discretize model by performing a linear interpolation.
    r   g      ?r   N)r*   r:   )r4   r5   r;   values_intermediate_gridr
   r
   r   r.      s    r.   c             C   s   t |d d |d d }t |d d |d d }t ||\}}| ||}d|ddddf |ddddf   }d|ddddf |ddddf   }|S )zB
    Discretize model by performing a bilinear interpolation.
    r   g      ?r   Nr>   )r*   r:   r<   )r4   r5   r6   r;   r=   r?   valuesr
   r
   r   r/      s    
r/   c             C   sl   t |d ddd|    |d ddd|    d| }| |}t ||j| |f}|jdddd S )zH
    Discretize model by taking the average on an oversampled grid.
    r   g      ?r   g      ?)axisNr>   )r*   r:   reshaper   mean)r4   r5   r8   r;   r@   r
   r
   r   r0      s
     r0   c       
      C   s   t |d ddd|    |d ddd|    d| }t |d ddd|    |d ddd|    d| }t ||\}}| ||}|j| ||j| |f}	t ||	}|jddjddddddf S )	zH
    Discretize model by taking the average on an oversampled grid.
    r   g      ?r   g      ?   )rA   Nr>   )r*   r:   r<   r   rB   rC   )
r4   r5   r6   r8   r;   r=   Zx_gridZy_gridr@   r   r
   r
   r   r1     s      
r1   c          
   C   sr   ddl m} t|d d |d d }tg }x:t|jd D ](}t||| || ||d  d }qBW |S )zM
    Discretize model by integrating numerically the model over the bin.
    r   )quadg      ?r   )scipy.integraterE   r*   r:   r   ranger   append)r4   r5   rE   r;   r@   ir
   r
   r   r2     s    
(r2   c          
      s   ddl m} t|d d |d d }t|d d |d d tjd |jd f}xrt|jd D ]`}xZtjd D ]H |fdd|| ||d   fdd fddd | |f< qW qnW |S )	zC
    Discretize model by integrating the model over the pixel.
    r   )dblquadg      ?r   c                s
    || S )Nr
   )r=   r;   )r4   r
   r   <lambda>0  s    z)discretize_integrate_2D.<locals>.<lambda>c                s     S )Nr
   )r;   )jr=   r
   r   rK   1  s    c                s    d  S )Nr   r
   )r;   )rL   r=   r
   r   rK   1  s    )rF   rJ   r*   r:   emptyr   rG   )r4   r5   r6   rJ   r;   r@   rI   r
   )rL   r4   r=   r   r3   #  s    0r3   )Nr!   r%   )r%   )r%   )ZctypesZnumpyr*   Zastropy.modeling.corer   r   __all__	Exceptionr   r   r   r   r"   r$   r   r,   r-   r.   r/   r0   r1   r2   r3   r
   r
   r
   r   <module>   s$   
s



