U
    ÃmœdîD  ã                   @   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-�râe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
�qòe&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-�rôe @¡  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   úk/home/sam/Atlas/atlas_env/lib/python3.8/site-packages/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{®Gáz„?)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 )ÚHPolyzŽOrthonormal (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	r„t ‡ ‡‡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ÚnanZzerosr:   r   Úquad)ÚpolysÚlowerÚupperrA   Zn_polysÚ	innerprodZinterrr6   ÚjZinnpÚerrr   r>   r   Ú
inner_cont�   s(    ! ÿ
rP   ç:Œ0âŽyE>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   rI   r   Zallclose)rJ   rK   rL   rR   rS   r6   rN   rM   r   rD   r   Úis_orthonormal_contÕ   s    ,rT   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:   rJ   Ú
_corfactorÚ	_corshift)r   r8   r   rJ   r   rV   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   rV   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     )rJ   r8   r:   Úhasattrr   rY   ÚminÚmaxÚoffsetÚlimitsÚshrinkÚshiftÚ
_transformr   ÚcoeffsÚ_verify)r   r   r8   r   rb   rJ   ZxminZxmaxra   Zinterval_lengthZ	xintervalrf   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>)re   rE   rJ   ÚsumÚlistÚziprf   Ú_correction)r   rl   r   Úresr   rk   r   ÚevaluateJ  s    

,
zDensityOrthoPoly.evaluatec                 C   s
   |   |¡S )z,alias for evaluate, except no order argument)rs   )r   rl   r   r   r   r   R  s    zDensityOrthoPoly.__call__c                 C   s(   | j }dtj| jf|žŽ d  | _| jS )z—check for bona fide density correction

        currently only checks that density integrates to 1

`       non-negativity - NotImplementedYet
        rZ   r   )rb   r   rI   rs   rW   )r   r
   r   r   r   rg   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   )rW   rX   r   r   r   r   rq   h  s
    



zDensityOrthoPoly._correctionc                 C   sJ   | j d j}|d |d  }| j|d | j |  }| j| }|| | S )z„transform observation to the domain of the density


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


        r   r   )rJ   r	   rd   rc   )r   r   r	   Zilenrd   rc   r   r   r   re   v  s
    
zDensityOrthoPoly._transform)Nr3   )Nr3   N)N)r   r   r   r   r   rh   rs   r   rg   rq   re   r   r   r   r   rU     s   


$
rU   c                    sn   ˆd krt  ˆ ¡ ˆ ¡ d¡‰‡ fdd„t|ƒD ƒ}‡fdd„|D ƒ}t‡fdd„t||ƒD ƒƒ}|ˆ||fS )Né2   c                    s   g | ]}ˆ |ƒ‘qS r   r   r4   rV   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   ri   rk   r   r   rm   ›  s     z$density_orthopoly.<locals>.<genexpr>)r   Úlinspacer_   r`   r:   rn   rp   )r   r8   r   rl   rJ   rf   rr   r   )r8   r   rl   r   Údensity_orthopoly‹  s    rv   Ú__main__r#   Zfourierr*   i'  )Úmixture_rvsÚMixtureDistributionr.   r-   )ÚlocÚscaler   gš™™™™™É?gUUUUUUÕ?gUUUUUUå?)ÚsizeÚdistÚkwargsZchebyt_éþÿÿÿé   )r   rl   zf_hat.min()Úfint2rt   TÚred)ZbinsÚnormedÚcolorÚ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~   Ú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   rQ   )r3   N)Sr   Zscipyr   r   r   Únumpyr   r    r   r   r   r!   r/   r   r0   r(   r;   rP   rT   rU   rv   r   ZexamplesZnobsZmatplotlib.pyplotZpyplotZpltZ%statsmodels.distributions.mixture_rvsrx   ry   ÚdictZmix_kwdsZnormZobs_distZmixZf_hatÚgridrf   rJ   Zf_hat0ZtrapzZfintÚprintr_   r�   ZdoplotÚhistZplotÚshowÚ	enumerater6   r]   rN   r@   rI   rh   Zdopru   r`   Zxfrb   ZdopintZpdfZmpdfZfigureÚtitlerY   ÚabsÚeyer:   ZhpolysZinnZastypeÚintr%   r*   r#   ZhtpolysZinntZpolyscÚrÚeZdiagr   r   r   r   Ú<module>   sÜ   %
 

8
;{


ÿ
&

ÿ


ÿ
4

ÿ
4