a
    ;gh+                     @   s   d Z ddlmZ ddlmZ ddlZddlmZ ddl	m
Z
mZ g 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dZd!ddZd"ddZdS )#z`
This provides a small set of utilities in NumPyro that are used to diagnose posterior samples.
    )OrderedDict)productN)
device_get)tree_flattentree_map)autocorrelationautocovarianceeffective_sample_sizegelman_rubinhpdisplit_gelman_rubinprint_summaryc                 C   sz   | j d d \}}| jddd}|jdd}||d  | }| j d dkrn| jdd}|jddd}|| }n|}||fS )N      axisZddofr   r   )shapevarmean)xCNZ	chain_var
var_withinvar_estimatorZ
chain_meanZvar_between r   c/mounts/lovelace/software/anaconda3/envs/metaDMG/lib/python3.9/site-packages/numpyro/diagnostics.py_compute_chain_variance_stats   s    
r   c                 C   s~   | j dksJ | jd dks J | jd dks2J t| \}}tjddd t|| }W d   n1 sp0    Y  |S )aO  
    Computes R-hat over chains of samples ``x``, where the first dimension of
    ``x`` is chain dimension and the second dimension of ``x`` is draw dimension.
    It is required that ``x.shape[0] >= 2`` and ``x.shape[1] >= 2``.

    :param numpy.ndarray x: the input array.
    :return: R-hat of ``x``.
    :rtype: numpy.ndarray
    r   r   r   ignoreinvaliddivideN)ndimr   r   nperrstatesqrt)r   r   r   Zrhatr   r   r   r
   +   s    
,r
   c                 C   sn   | j dksJ | jd dks J | jd d }tj| ddd|f | dd| df gdd}t|}|S )aC  
    Computes split R-hat over chains of samples ``x``, where the first dimension
    of ``x`` is chain dimension and the second dimension of ``x`` is draw dimension.
    It is required that ``x.shape[1] >= 4``.

    :param numpy.ndarray x: the input array.
    :return: split R-hat of ``x``.
    :rtype: numpy.ndarray
    r   r      Nr   r   )r"   r   r#   concatenater
   )r   ZN_halfZ	new_inputZ
split_rhatr   r   r   r   >   s    
4r   c                 C   sl   | dkr| S | }|d dkr&|d }q|d dkr<|d }q&|d dkrR|d }q<|dkr^| S | d7 } qd S )Nr   r         r   r   )targetmr   r   r   _fft_next_fast_lenQ   s    


r,   c           	      C   s   | j | }t|}d| }t| |d} | | jddd }tjj||dd}|t| }tjj||dd}|dd|f }|t	|dd }tj
d	d	d
$ ||dddf  }W d   n1 s0    Y  t||dS )z
    Computes the autocorrelation of samples at dimension ``axis``.

    :param numpy.ndarray x: the input array.
    :param int axis: the dimension to calculate autocorrelation.
    :return: autocorrelation of ``x``.
    :rtype: numpy.ndarray
    r   Tr   Zkeepdims)nr   .Ng        r   r   r   )r   r,   r#   swapaxesr   ZfftZrfft	conjugateZirfftZaranger$   )	r   r   r   MZM2Zcentered_signalZfreqvecZfreqvec_gramZautocorrr   r   r   r   c   s    
2r   c                 C   s   t | || j|dd S )z
    Computes the autocovariance of samples at dimension ``axis``.

    :param numpy.ndarray x: the input array.
    :param int axis: the dimension to calculate autocovariance.
    :return: autocovariance of ``x``.
    :rtype: numpy.ndarray
    Tr.   )r   r   )r   r   r   r   r   r      s    	r   c           	      C   s   | j dksJ | jd dks J t| dd}t| \}}d||jdd |  }d|d< |ddddf |ddddf  }|dd }tj|tjjtj	|dddf ddd	ddgdd}d
d|j
dd  }t| jdd | }|S )a  
    Computes effective sample size of input ``x``, where the first dimension of
    ``x`` is chain dimension and the second dimension of ``x`` is draw dimension.

    **References:**

    1. *Introduction to Markov Chain Monte Carlo*,
       Charles J. Geyer
    2. *Stan Reference Manual version 2.18*,
       Stan Development Team

    :param numpy.ndarray x: the input array.
    :return: effective sample size of ``x``.
    :rtype: numpy.ndarray
    r   r   r   g      ?r   Nr-   .)Za_minZa_maxg      g       @)r"   r   r   r   r   r#   r'   minimum
accumulateZclipsumprod)	r   Z	gamma_k_cr   r   Zrho_kZRho_kZRho_inittaun_effr   r   r   r	      s"    $&r	   ?c                 C   s   t | |d} t j| dd}| jd }t|| }|d||  }||d }|| }|jdd}	|	| }
t j||	d dd}t ||d}t j||
d dd}t ||d}t j||g|dS )a  
    Computes "highest posterior density interval" (HPDI) which is the narrowest
    interval with probability mass ``prob``.

    :param numpy.ndarray x: the input array.
    :param float prob: the probability mass of samples within the interval.
    :param int axis: the dimension to calculate hpdi.
    :return: quantiles of ``x`` at ``(1 - prob) / 2`` and
        ``(1 + prob) / 2``.
    :rtype: numpy.ndarray
    r   r   NN.)r#   r0   sortr   intZargminZtake_along_axisr'   )r   probr   Zsorted_xZmassZindex_lengthZintervals_leftZintervals_rightZintervals_lengthZindex_startZ	index_endZhpd_leftZ	hpd_rightr   r   r   r      s    
r   Tc              
   C   s  |st dd | } t| ts6dd tt| d D } i }|  D ]\}}t|}t|d|j	dd  }|j
dd	}|jdd
d}tj|dd	}	t||d}
t|}t|}ddd
|  }ddd
|  }td|fd|fd|	f||
d f||
d
 fd|fd|fg||< qB|S )ay  
    Returns a summary table displaying diagnostics of ``samples`` from the
    posterior. The diagnostics displayed are mean, standard deviation, median,
    the 90% Credibility Interval :func:`~numpyro.diagnostics.hpdi`,
    :func:`~numpyro.diagnostics.effective_sample_size`, and
    :func:`~numpyro.diagnostics.split_gelman_rubin`.

    :param samples: a collection of input samples with left most dimension is chain
        dimension and second to left most dimension is draw dimension.
    :type samples: dict or numpy.ndarray
    :param float prob: the probability mass of samples within the HPDI interval.
    :param bool group_by_chain: If True, each variable in `samples` will be treated
        as having shape `num_chains x num_samples x sample_shape`. Otherwise, the
        corresponding shape will be `num_samples x sample_shape` (i.e. without
        chain dimension).
    c                 S   s   | d S Nr:   r   r   r   r   r   <lambda>       zsummary.<locals>.<lambda>c                 S   s   i | ]\}}d  ||qS zParam:{}format.0ivr   r   r   
<dictcomp>   s   zsummary.<locals>.<dictcomp>r   )r-   r   Nr   r   r   )r=   z{:.1f}%2   r   stdmedianr8   r_hat)r   
isinstancedict	enumerater   itemsr   r#   Zreshaper   r   rK   rL   r   r	   r   rD   r   )samplesr=   group_by_chainsummary_dictnamevalueZ
value_flatr   rK   rL   Zhpdr8   rM   Z	hpd_lowerZ	hpd_upperr   r   r   summary   s:    



rW   c              	      sl  |st dd | } t| ts6dd tt| d D } t| |dd}dd |  D }tttd	d |	 d
}dt
| d }|d }dgtt|	 d   }t  t|j|  |d }	| D ]\}
}|d j}t|dkrt|	j|
g|	 R   qttt| D ]H ddtt
 }t|	j|
| g fdd|	 D R   qqt  dS )ax  
    Prints a summary table displaying diagnostics of ``samples`` from the
    posterior. The diagnostics displayed are mean, standard deviation, median,
    the 90% Credibility Interval :func:`~numpyro.diagnostics.hpdi`,
    :func:`~numpyro.diagnostics.effective_sample_size`, and
    :func:`~numpyro.diagnostics.split_gelman_rubin`.

    :param samples: a collection of input samples with left most dimension is chain
        dimension and second to left most dimension is draw dimension.
    :type samples: dict or numpy.ndarray
    :param float prob: the probability mass of samples within the HPDI interval.
    :param bool group_by_chain: If True, each variable in `samples` will be treated
        as having shape `num_chains x num_samples x sample_shape`. Otherwise, the
        corresponding shape will be `num_samples x sample_shape` (i.e. without
        chain dimension).
    c                 S   s   | d S r>   r   r?   r   r   r   r@   #  rA   zprint_summary.<locals>.<lambda>c                 S   s   i | ]\}}d  ||qS rB   rC   rE   r   r   r   rI   %  s   z!print_summary.<locals>.<dictcomp>r   T)rS   c                 S   s<   i | ]4\}}||d  d tdd |jdd  d qS )[,c                 S   s   t | d S )Nr   )strr?   r   r   r   r@   +  rA   z*print_summary.<locals>.<dictcomp>.<lambda>r   N])joinmapr   )rF   krH   r   r   r   rI   *  s   c                 S   s   t | S )N)lenr?   r   r   r   r@   .  rA   
   z{:>}z* {:>9} {:>9} {:>9} {:>9} {:>9} {:>9} {:>9} z? {:>9.2f} {:>9.2f} {:>9.2f} {:>9.2f} {:>9.2f} {:>9.2f} {:>9.2f}r   z[{}]rY   c                    s   g | ]}|  qS r   r   )rF   rH   idxr   r   
<listcomp>@  rA   z!print_summary.<locals>.<listcomp>N)r   rN   rO   rP   r   rW   rQ   maxr]   valuesrZ   listkeysprintrD   r   r_   r   ranger\   )rR   r=   rS   rT   Z	row_namesmax_lenZname_formatZheader_formatcolumnsZ
row_formatrU   Z
stats_dictr   Zidx_strr   rc   r   r     s>    


r   )r   )r   )r9   r   )r9   T)r9   T)__doc__collectionsr   	itertoolsr   numpyr#   Zjaxr   Zjax.tree_utilr   r   __all__r   r
   r   r,   r   r   r	   r   rW   r   r   r   r   r   <module>   s    
%
/

2