U
    KvfD                     @   s  d Z ddlmZmZmZ ddlZedZG dd dZ	G dd dZ
G d	d
 d
Zeejd ZG dd dZdNddZdOddZdPddZG dd dZdQddZedkrdddgZdZddlmZ ddlmZmZ ed d!d"ed#d$d"fZed%d&geej ej ged'Z!e Z"d(ekrZe!e!d)ke!dk @  d Z!ee!ed*dd+\Z#Z$Z%Z&e#Z'e(e#e$Z)e*d,e#+  e#e#+  Z#e(e#e$Z,e*d-e)e, e#e, Z#dZ-e-rej.e!d.d/d0d1 ej/e$e#dd2d3 ej/e$e'dd4d3 e0  e1e&dd D ]D\Z2Z3e1e&dd D ](\Z4Z5e*e2e4e6d5d6 d7d#d  q
qe&D ]Z3e*e6d8d6 d7d# q<dekr"e j7e!ed*d9Z8e9e!+ e!: Z$e8e$Z;ej6e8fe8j< d Z=e*d:e= e"j>e$d%d&gej ej ged;Z?d#Z-e-r"e@  ej.e!d.d/d0d1 ej/e$e;dd2d3 ej/e$e?dd<d3 eAd= dekr(e Z8d!e8_Be8j7e!e
d>d9Z8e9e!+ e!: Z$e8e$Z;ej6e8fe8j< d Z=e*d:e= e"j>e$d%d&gej ej ged;Z?d#Z-e-re@  ej.e!d.d/d0d1 eAd? ej/e$e;dd2d3 ej/e$e?dd<d3 e*e:eCee8j&dd dd#d eDd  dekr6e Z8de8_Be8j7e!ed*d9Z8e9e!+ e!: Z$e8e$Z;ej6e8fe8j< d Z=e*d:e= e"j>e$d%d&gej ej ged;Z?d#Z-e-re@  ej.e!d.d/d0d1 ej/e$e;dd2d3 ej/e$e?dd<d3 eAd@ e0  e*e:eCee8j&dd dd#d eDd  dAdB eEdD ZFeeFdCdDd ZGe*e:eCeGeDd  e*eGdE HeI ddFlJmKZKmLZL dGdB eEdD ZMeeMdHdId ZNe*eNdE HeI dJdB eEdKD ZOeeOd7d#dLd6 dM\ZPZQe*e:eCePeReReP  dS )Ra  density estimation based on orthogonal polynomials


Author: Josef Perktold
Created: 2011-05017
License: BSD

2 versions work: based on Fourier, FPoly, and chebychev T, ChebyTPoly
also hermite polynomials, HPoly, works
other versions need normalization


TODO:

* check fourier case again:  base is orthonormal,
  but needs offsetfact = 0 and does not integrate to 1, rescaled looks good
* hermite: works but DensityOrthoPoly requires currently finite bounds
  I use it with offsettfactor 0.5 in example
* not implemented methods:
  - add bonafide density correction
  - add transformation to domain of polynomial base - DONE
    possible problem: what is the behavior at the boundary,
    offsetfact requires more work, check different cases, add as option
    moved to polynomial class by default, as attribute
* convert examples to test cases
* need examples with large density on boundary, beta ?
* organize poly classes in separate module, check new numpy.polynomials,
  polyvander
* MISE measures, order selection, ...

enhancements:
  * other polynomial bases: especially for open and half open support
  * wavelets
  * local or piecewise approximations


    )stats	integratespecialN       @c                   @   s    e Zd ZdZdd Zdd ZdS )FPolyaB  Orthonormal (for weight=1) Fourier Polynomial on [0,1]

    orthonormal polynomial but density needs corfactor that I do not see what
    it is analytically

    parameterization on [0,1] from

    Sam Efromovich: Orthogonal series density estimation,
    2010 John Wiley & Sons, Inc. WIREs Comp Stat 2010 2 467-476


    c                 C   s   || _ d| _| j| _d S )N)r      )orderdomain	intdomainselfr    r   V/tmp/pip-unpacked-wheel-2v6byqio/statsmodels/sandbox/nonparametric/densityorthopoly.py__init__=   s    zFPoly.__init__c                 C   s2   | j dkrt|S tttj| j  |  S d S Nr   )r   np	ones_likesqr2cospir   xr   r   r   __call__B   s    

zFPoly.__call__N__name__
__module____qualname____doc__r   r   r   r   r   r   r   /   s   r   c                   @   s    e Zd ZdZdd Zdd ZdS )F2Polya  Orthogonal (for weight=1) Fourier Polynomial on [0,pi]

    is orthogonal but first component does not square-integrate to 1
    final result seems to need a correction factor of sqrt(pi)
    _corfactor = sqrt(pi) from integrating the density

    Parameterization on [0, pi] from

    Peter Hall, Cross-Validation and the Smoothing of Orthogonal Series Density
    Estimators, JOURNAL OF MULTIVARIATE ANALYSIS 21, 189-206 (1987)

    c                 C   s$   || _ dtjf| _| j| _d| _d S r   )r   r   r   r	   r
   offsetfactorr   r   r   r   r   V   s    zF2Poly.__init__c                 C   sD   | j dkr t|ttj S tt| j |  ttj S d S r   )r   r   r   sqrtr   r   r   r   r   r   r   r   \   s    
zF2Poly.__call__Nr   r   r   r   r   r   H   s   r   c                   @   s    e Zd ZdZdd Zdd ZdS )
ChebyTPolyaL  Orthonormal (for weight=1) Chebychev Polynomial on (-1,1)


    Notes
    -----
    integration requires to stay away from boundary, offsetfactor > 0
    maybe this implies that we cannot use it for densities that are > 0 at
    boundary ???

    or maybe there is a mistake close to the boundary, sometimes integration works.

    c                 C   s2   || _ ddlm} ||| _d| _d| _d| _d S )Nr   chebyt)r   )g!g!?g{Gz?)r   scipy.specialr#   polyr	   r
   r   )r   r   r#   r   r   r   r   p   s    
zChebyTPoly.__init__c                 C   sd   | j dkr0t|d|d  d  ttj S | |d|d  d  ttj td S d S )Nr   r      g      ?)r   r   r   r    r   r&   r   r   r   r   r   z   s    
&zChebyTPoly.__call__Nr   r   r   r   r   r!   b   s   
r!   r'   c                   @   s    e Zd ZdZdd Zdd ZdS )HPolyzOrthonormal (for weight=1) Hermite Polynomial, uses finite bounds

    for current use with DensityOrthoPoly domain is defined as [-6,6]

    c                 C   s,   || _ ddlm} ||| _d| _d| _d S )Nr   hermite)         ?)r   r%   r*   r&   r	   r   )r   r   r*   r   r   r   r      s
    
zHPoly.__init__c                 C   sN   | j }d|td t|d  t  || d  }t|}| || S )N      r   r   r'   )r   r   logr   Zgammalnlogpi2expr&   )r   r   kZlnfactZfactr   r   r   r      s    0
zHPoly.__call__Nr   r   r   r   r   r(      s   r(      c                    s"   t  fddt|D }|S )Nc                    s   g | ]} |qS r   r   .0ipolybaser   r   r   
<listcomp>   s     zpolyvander.<locals>.<listcomp>)r   Zcolumn_stackrange)r   r8   r   Zpolyarrr   r7   r   
polyvander   s    r;   c                    s   t | }t||f}|tj t||f}t|D ]}t|d D ]}| |  | | dk	rt fdd||\}	}
nt fdd||\}	}
|	|||f< |
|||f< ||ksH|	|||f< |
|||f< qHq8||fS )a  inner product of continuous function (with weight=1)

    Parameters
    ----------
    polys : list of callables
        polynomial instances
    lower : float
        lower integration limit
    upper : float
        upper integration limit
    weight : callable or None
        weighting function

    Returns
    -------
    innp : ndarray
        symmetric 2d square array with innerproduct of all function pairs
    err : ndarray
        numerical error estimate from scipy.integrate.quad, same dimension as innp

    Examples
    --------
    >>> from scipy.special import chebyt
    >>> polys = [chebyt(i) for i in range(4)]
    >>> r, e = inner_cont(polys, -1, 1)
    >>> r
    array([[ 2.        ,  0.        , -0.66666667,  0.        ],
           [ 0.        ,  0.66666667,  0.        , -0.4       ],
           [-0.66666667,  0.        ,  0.93333333,  0.        ],
           [ 0.        , -0.4       ,  0.        ,  0.97142857]])

    r   Nc                    s    | |  |  S Nr   r   p1p2weightr   r   <lambda>       zinner_cont.<locals>.<lambda>c                    s    | |  S r<   r   r=   r?   r@   r   r   rB      rC   )	lenr   emptyfillnanzerosr:   r   quad)polyslowerupperrA   Zn_polys	innerprodZinterrr6   jZinnperrr   r>   r   
inner_cont   s(    ! 
rQ   :0yE>c                    sr   t t| D ]`}t |d D ]N}| |  | | t fdd||d }tj|||k||ds  dS qqdS )aZ  check whether functions are orthonormal

    Parameters
    ----------
    polys : list of polynomials or function

    Returns
    -------
    is_orthonormal : bool
        is False if the innerproducts are not close to 0 or 1

    Notes
    -----
    this stops as soon as the first deviation from orthonormality is found.

    Examples
    --------
    >>> from scipy.special import chebyt
    >>> polys = [chebyt(i) for i in range(4)]
    >>> r, e = inner_cont(polys, -1, 1)
    >>> r
    array([[ 2.        ,  0.        , -0.66666667,  0.        ],
           [ 0.        ,  0.66666667,  0.        , -0.4       ],
           [-0.66666667,  0.        ,  0.93333333,  0.        ],
           [ 0.        , -0.4       ,  0.        ,  0.97142857]])
    >>> is_orthonormal_cont(polys, -1, 1, atol=1e-6)
    False

    >>> polys = [ChebyTPoly(i) for i in range(4)]
    >>> r, e = inner_cont(polys, -1, 1)
    >>> r
    array([[  1.00000000e+00,   0.00000000e+00,  -9.31270888e-14,
              0.00000000e+00],
           [  0.00000000e+00,   1.00000000e+00,   0.00000000e+00,
             -9.47850712e-15],
           [ -9.31270888e-14,   0.00000000e+00,   1.00000000e+00,
              0.00000000e+00],
           [  0.00000000e+00,  -9.47850712e-15,   0.00000000e+00,
              1.00000000e+00]])
    >>> is_orthonormal_cont(polys, -1, 1, atol=1e-6)
    True

    r   c                    s    | |  S r<   r   r=   rD   r   r   rB     rC   z%is_orthonormal_cont.<locals>.<lambda>r   )rtolatolFT)r:   rE   r   rJ   r   Zallclose)rK   rL   rM   rS   rT   r6   rO   rN   r   rD   r   is_orthonormal_cont   s    ,rU   c                   @   sN   e Zd ZdZdddZdddZddd	Zd
d Zdd Zdd Z	dd Z
dS )DensityOrthoPolya  Univariate density estimation by orthonormal series expansion


    Uses an orthonormal polynomial basis to approximate a univariate density.


    currently all arguments can be given to fit, I might change it to requiring
    arguments in __init__ instead.
    Nr3   c                    s:    d k	r* | _  fddt|D  | _}d| _d| _d S )Nc                    s   g | ]} |qS r   r   r4   r8   r   r   r9     s     z-DensityOrthoPoly.__init__.<locals>.<listcomp>r   r   )r8   r:   rK   
_corfactor	_corshift)r   r8   r   rK   r   rW   r   r     s
    zDensityOrthoPoly.__init__c                    s   dkr| j d| }n" | _ fddt|D  | _ }t| dsP|d j| _   }}|dkr|| | j  | _}|| || f }| _	|d |d  }	|| }
d|	 | _
|	|
 d }|| | _|  | _fd	d|D }|| _|| _ |   | S )
zIestimate the orthogonal polynomial approximation to the density

        Nc                    s   g | ]} |qS r   r   r4   rW   r   r   r9   .  s     z(DensityOrthoPoly.fit.<locals>.<listcomp>	offsetfacr   r         ?r   c                    s   g | ]}|   qS r   Zmeanr5   pr=   r   r   r9   C  s     )rK   r8   r:   hasattrr   rZ   minmaxoffsetlimitsshrinkshift
_transformr   coeffs_verify)r   r   r8   r   rc   rK   ZxminZxmaxrb   Zinterval_lengthZ	xintervalrg   r   r7   r   fit&  s*    


zDensityOrthoPoly.fitc                    sV   |    |d krt| j}t fddtt| j| jd | D }| |}|S )Nc                 3   s   | ]\}}||  V  qd S r<   r   r5   cr^   xevalr   r   	<genexpr>N  s     z,DensityOrthoPoly.evaluate.<locals>.<genexpr>)rf   rE   rK   sumlistziprg   _correction)r   rm   r   resr   rl   r   evaluateJ  s    

,
zDensityOrthoPoly.evaluatec                 C   s
   |  |S )z,alias for evaluate, except no order argument)rt   )r   rm   r   r   r   r   R  s    zDensityOrthoPoly.__call__c                 C   s(   | j }dtj| jf| d  | _| jS )zcheck for bona fide density correction

        currently only checks that density integrates to 1

`       non-negativity - NotImplementedYet
        r[   r   )rc   r   rJ   rt   rX   )r   r
   r   r   r   rh   V  s    
zDensityOrthoPoly._verifyc                 C   s,   | j dkr|| j 9 }| jdkr(|| j7 }|S )zhbona fide density correction

        affine shift of density to make it into a proper density

        r   r   )rX   rY   r   r   r   r   rr   h  s
    



zDensityOrthoPoly._correctionc                 C   sJ   | j d j}|d |d  }| j|d | j |  }| j| }|| | S )ztransform observation to the domain of the density


        uses shrink and shift attribute which are set in fit to stay


        r   r   )rK   r	   re   rd   )r   r   r	   Zilenre   rd   r   r   r   rf   v  s
    
zDensityOrthoPoly._transform)Nr3   )Nr3   N)N)r   r   r   r   r   ri   rt   r   rh   rr   rf   r   r   r   r   rV     s   


$
rV   c                    sn   d krt   d fddt|D }fdd|D }tfddt||D }|||fS )N2   c                    s   g | ]} |qS r   r   r4   rW   r   r   r9     s     z%density_orthopoly.<locals>.<listcomp>c                    s   g | ]}|   qS r   r\   r]   r=   r   r   r9     s     c                 3   s   | ]\}}||  V  qd S r<   r   rj   rl   r   r   rn     s     z$density_orthopoly.<locals>.<genexpr>)r   linspacer`   ra   r:   ro   rq   )r   r8   r   rm   rK   rg   rs   r   )r8   r   rm   r   density_orthopoly  s    rw   __main__r#   Zfourierr*   i'  )mixture_rvsMixtureDistributionr.   r-   )locZscaler   g?gUUUUUU?gUUUUUU?)sizedistkwargsZchebyt_   )r   rm   zf_hat.min()fint2ru   TZred)ZbinsnormedcolorZblack)Zlwr   gc                 C   s   t | t|  S r<   )r^   r@   r=   r   r   r   rB     rC   rB   r$   c                 C   s   t | d S )Nr'   )r^   r=   r   r   r   rB     rC   )r   zdop F integral)r}   r~   Zgreenzusing Chebychev polynomials   zusing Fourier polynomialszusing Hermite polynomialsc                 C   s   g | ]}t |qS r   )r(   r4   r   r   r   r9   %  s     r9   r+   r,   i )r*   r#   c                 C   s   g | ]}t |qS r   r)   r4   r   r   r   r9   +  s     i
   c                 C   s   g | ]}t |qS r   r"   r4   r   r   r   r9   /  s        c                 C   s   d| |   d S )Nr   r.   r   r=   r   r   r   rB   0  rC   )rA   )r3   )N)r   rR   )r3   N)Sr   Zscipyr   r   r   Znumpyr   r    r   r   r   r!   r/   r   r0   r(   r;   rQ   rU   rV   rw   r   ZexamplesZnobsZmatplotlib.pyplotZpyplotZpltZ%statsmodels.distributions.mixture_rvsry   rz   dictZmix_kwdsZnormZobs_distZmixZf_hatZgridrg   rK   Zf_hat0ZtrapzZfintprintr`   r   ZdoplothistZplotshow	enumerater6   r^   rO   r@   rJ   ri   Zdoprv   ra   Zxfrc   ZdopintZpdfZmpdffiguretitlerZ   absZeyer:   ZhpolysZinnZastypeintr%   r*   r#   ZhtpolysZinntZpolyscreZdiagr   r   r   r   <module>   s   %
 

8
;{



&





4


4