U
    f»{j…Ð  ã                   @   sˆ  d dl Z d dlmZ d dlZddlmZ ddlmZm	Z	m
Z
mZmZmZmZ ddlmZmZmZmZ e  d¡dd	„ ƒZd
d„ ZdHdd„ZdIdd„Zdd„ Zdd„ Ze	dJdd„ƒZe	dKdd„ƒZdd„ Ze	dLd$d%„ƒZe	dMd&d'„ƒZe	dNd)d*„ƒZ d+d,„ Z!d-d.„ Z"G d/d0„ d0e#ƒZ$G d1d2„ d2e#ƒZ%dOd3d4„Z&d5d6„ Z'dPd8d9„Z(dQd:d;„Z)dRd<d=„Z*dSd>d?„Z+e	dTd@dA„ƒZ,e	dUdDdE„ƒZ-e	dVdFdG„ƒZ.dS )Wé    N)Úsqrté   )Úcompute_biasé   )ÚloggerÚverboseÚsum_squaredÚwarnÚ_get_blas_funcsÚ_validate_typeÚ_check_option)Ú
stft_norm1Ú
stft_norm2ÚstftÚistftc                   C   s   t tjdƒS )NZgemm)r
   ÚnpÚfloat64© r   r   ú\/var/www/html/bwave/python/venv/lib/python3.8/site-packages/mne/inverse_sparse/mxne_optim.pyÚ
_get_dgemm   s    r   c                 C   s.   | j d | }tjt | d| ¡ |d¡dd�S )z+Compute squared L2 norms of groups inplace.r   r   éÿÿÿÿr   ©Zaxis)Úshaper   ÚsumÚpowerÚreshape)ÚAÚn_orientÚn_positionsr   r   r   Úgroups_norm2   s    r   Tc                 C   s.   | j dkrdS |r|  ¡ } tt t| |ƒ¡ƒS )zL2-inf norm.r   ç        )ÚsizeÚcopyr   r   Úmaxr   ©r   r   r"   r   r   r   Ú
norm_l2inf   s
    
r%   c                 C   s0   | j dkrdS |r|  ¡ } t t t| |ƒ¡¡S )z	L21 norm.r   r    )r!   r"   r   r   r   r   r$   r   r   r   Únorm_l21%   s
    
r&   c                 C   sR   t  |dd…|f |¡}| | }t||dd�}t|ƒ}	d|	 ||  }
|
||	|fS )a,  Primal objective for the mixed-norm inverse problem.

    See :footcite:`GramfortEtAl2012`.

    Parameters
    ----------
    M : array, shape (n_sensors, n_times)
        The data.
    G : array, shape (n_sensors, n_active)
        The gain matrix a.k.a. lead field.
    X : array, shape (n_active, n_times)
        Sources.
    active_set : array of bool, shape (n_sources,)
        Mask of active sources.
    alpha : float
        The regularization parameter.
    n_orient : int
        Number of dipoles per locations (typically 1 or 3).

    Returns
    -------
    p_obj : float
        Primal objective.
    R : array, shape (n_sensors, n_times)
        Current residual (M - G * X).
    nR2 : float
        Data-fitting term.
    GX : array, shape (n_sensors, n_times)
        Forward prediction.
    NT©r"   ç      à?)r   Údotr&   r   )ÚMÚGÚXÚ
active_setÚalphar   ÚGXÚRZpenaltyÚnR2Úp_objr   r   r   Ú_primal_l21.   s    r3   c                 C   s~   t | |||||ƒ\}}}}	tt |j|¡|dd�}
||
 }t|dƒ}|d|d   | |t ||	 ¡  }|| }||||fS )aP  Duality gap for the mixed norm inverse problem.

    See :footcite:`GramfortEtAl2012`.

    Parameters
    ----------
    M : array, shape (n_sensors, n_times)
        The data.
    G : array, shape (n_sensors, n_active)
        The gain matrix a.k.a. lead field.
    X : array, shape (n_active, n_times)
        Sources.
    active_set : array of bool, shape (n_sources, )
        Mask of active sources.
    alpha : float
        The regularization parameter.
    n_orient : int
        Number of dipoles per locations (typically 1 or 3).

    Returns
    -------
    gap : float
        Dual gap.
    p_obj : float
        Primal objective.
    d_obj : float
        Dual objective. gap = p_obj - d_obj.
    R : array, shape (n_sensors, n_times)
        Current residual (M - G * X).

    References
    ----------
    .. footbibilography::
    Fr'   ç      ð?r(   r   )r3   r%   r   r)   ÚTÚminr   )r*   r+   r,   r-   r.   r   r2   r0   r1   r/   Ú	dual_normÚscalingÚd_objÚgapr   r   r   Údgap_l21U   s    #
&r;   é'  ç:Œ0âŽyE>é
   c
                 C   sÐ   ddl m}
 | j|jkr,| jd |jd ks0t‚|
|t| ƒ |t| ƒ d|dd�}|dk	rd|j|_nt	 
|jd | jd f¡j|_| || ¡ |jj}t	j|dd�}|| }t| |||||ƒ\}}}}|||fS )	z2Solve L21 inverse problem with coordinate descent.r   ©ÚMultiTaskLassoFT)r.   ÚtolZfit_interceptZmax_iterZ
warm_startNr   r   )Úsklearn.linear_modelr@   Úndimr   ÚAssertionErrorÚlenr   r5   Zcoef_r   ÚzerosÚfitÚanyr;   )r*   r+   r.   Úlipschitz_constantÚmaxitrA   r   Úinitr   Ú	dgap_freqr@   Zclfr,   r-   r:   r2   r9   Ú_r   r   r   Ú_mixed_norm_solver_cd‚   s     $  ÿ
rN   éÈ   é   c           *   
   C   sŒ  | j \}}|j \}}|| }|dkr<t ||f¡}|  ¡ }n|}| t ||¡ }g }tj }tj|td�}|| }|
rœt |d ||f¡}t ||| f¡}t |¡}|j	tj
ks¶t‚|j	tj
ksÆt‚d| }|jjjsÜt‚|jjjsêt‚|jjsöt‚g }t|ƒD ]8}t|| |d | ƒ}| t |dd…|f ¡¡ �qt|ƒD �]2}t||||||||ƒ |d |	 dk�ròt| ||| |||ƒ\}}}}t||ƒ}|| }| |¡ t d|d ||t |¡| f ¡ ||k �ròt d||f ¡  �qz|
�rD||||d  < ||d  |k�rDt|ƒD ]&} || d   ¡ ||   ¡  || < �q"||j }!tjj|!dd	�\}"}#}|#d
 d|#d  k�r–t d|d  ¡ �qD|"d |# |"j  d¡}$|$|$ ¡  }%tj|dd
… |%dd…ddf  dd�}&t|&|ƒ}'|'dk}(|dk�rt |(tj|td�¡}(t| ||| |||ƒd }t| ||&|( |(||ƒd })|)|k �rD|&}|(}| |dd…|f ||   }�qD|| }|||fS )z8Solve L21 inverse problem with block coordinate descent.N©Údtyper   r4   r   z2Iteration %d :: p_obj %f :: dgap %f :: n_active %dú$Convergence reached ! (gap: %s < %s)T)Z	hermitianr   g�íµ ÷Æ°>zIteration %d: LinAlg Errorr   ) r   r   rF   r"   r)   ÚinfÚboolÚemptyÚasfortranarrayrR   r   rD   r5   ÚflagsÚf_contiguousÚrangeÚsliceÚappendÚascontiguousarrayÚ_bcdr;   r#   r   Údebugr   ÚravelÚlinalgZsvdr   ZkronÚonesr3   )*r*   r+   r.   rI   rJ   rA   r   rK   r   rL   Z	use_accelÚKrM   Ún_timesÚ	n_sourcesr   r,   r0   ÚEÚhighest_d_objr-   Úalpha_lcZlast_K_XÚUÚ
one_ovr_lcÚ
list_G_j_cÚjÚidxÚir2   r9   r:   ÚkÚCÚuÚsÚzÚcZX_accZ_grp_norm2_accZactive_set_accZ	p_obj_accr   r   r   Ú_mixed_norm_solver_bcdš   sª    



  ÿ

ÿ
ÿ$
 ÿ

 ÿÿÿ  ÿÿ
 ru   c              	   C   s.  t j|d|…dd…f dd�}tƒ }	t|ƒD ]ü\}
}t|
| |
d | ƒ}| dd…|f }|| }|	||
 d|j||jdd� |d d	k}|r°|	d
d
|j|j|jdd� ||7 }tt|ƒƒ}|||
 krÜ| d¡ d||< q,t	d
||
 |  dƒ}||9 }|	dd
|j|j|jdd� ||dd…< d||< q,dS )a^  Implement one full pass of BCD.

    BCD stands for Block Coordinate Descent.
    This function make use of scipy.linalg.get_blas_funcs to speed reasons.

    Parameters
    ----------
    G : array, shape (n_sensors, n_active)
        The gain matrix a.k.a. lead field.
    X : array, shape (n_sources, n_times)
        Sources, modified in place.
    R : array, shape (n_sensors, n_times)
        The residuals: R = M - G @ X, modified in place.
    active_set : array of bool, shape (n_sources, )
        Mask of active sources, modified in place.
    one_ovr_lc : array, shape (n_positions, )
        One over the lipschitz constants.
    n_orient : int
        Number of dipoles per positions (typically 1 or 3).
    n_positions : int
        Number of source positions.
    alpha_lc: array, shape (n_positions, )
        alpha * (Lipschitz constants).
    Nrp   ©Úorderr   r    T)r.   ÚbetaÚaÚbrt   Zoverwrite_c)r   r   r   r4   Fç      ð¿)
r   Ú
zeros_liker   Ú	enumerater[   r5   r   r   Úfillr#   )r+   r,   r0   r-   rj   r   rh   rk   ÚX_j_newZdgemmrl   ZG_j_crm   ÚG_jÚX_jZwas_non_zeroZ
block_normÚshrinkr   r   r   r^      s4    ÿÿ

ÿr^   é¸  é2   ÚautoFc           +      C   s,  |j d }|| }| j \}}tt |j| ¡|dd�}t d| ¡ t|ƒ}tj||f|j	d�}d}zddl
m} W n tk
rŠ   d}Y nX t|	td	ƒ td	|	d
ƒ |	dkrÂ|r¾|dkr¾d}	nd}	|	dkrö|dkrâ|sâtdƒ d}	|dkrötdƒ d}	|	dk�rt d¡ t}d}nœ|	dk�s"t‚t d¡ t}t |¡}|dk�rXtj|| dd�}nXt |¡}t|ƒD ]D}|dd…|| |d | …f }tjjt |j|¡dd�||< �qj|dk	�rvtƒ }tj }|dk	�rê|j ||fk�rêtdƒ‚|dk	�rø|ntj|td�}t tt |j| ¡|ƒ¡}|| d… }|dk�rf||dd…df  t  |¡ddd…f   !¡ }d||< t |¡}tj} t|ƒD �]Ú}!|	dk�rª||dd|…  }"n4|	dk�rºd}"n$dtjj|dd…|f dd�d  }"|| |dd…|f ||"|||||d�	\}}#}|# "¡ ||< t #|¡d }$t$| |||||ƒ\}}%}&}'t%|&|ƒ}|%| } | &|%¡ t d|!d |%| || t |¡| f ¡ | |k �r¦t d| |f ¡  �q°|!|d k �r†t tt |j|'¡|ƒ¡}|| d… }|dk�r||dd…df  t  |¡ddd…f  }| !¡ }d||< t #|¡d }(t |¡}tj||f|j	d�}t '|(|$¡})|||)< �q†td| |f ƒ n:|| ||||||dd�\}}}|
�r°t$| |||||ƒd } t (|¡�rô|�rôt)| |dd…|f ||d�}*||*dd…tj*f 9 }t dt |¡|  ¡ |
�r|||| fS |||fS dS )a%  Solve L1/L2 mixed-norm inverse problem with active set strategy.

    See references :footcite:`GramfortEtAl2012,StrohmeierEtAl2016,
    BertrandEtAl2020`.

    Parameters
    ----------
    M : array, shape (n_sensors, n_times)
        The data.
    G : array, shape (n_sensors, n_dipoles)
        The gain matrix a.k.a. lead field.
    alpha : float
        The regularization parameter. It should be between 0 and 100.
        A value of 100 will lead to an empty active set (no active source).
    maxit : int
        The number of iterations.
    tol : float
        Tolerance on dual gap for convergence checking.
    %(verbose)s
    active_set_size : int
        Size of active set increase at each iteration.
    debias : bool
        Debias source estimates.
    n_orient : int
        The number of orientation (1 : fixed or 3 : free or loose).
    solver : 'cd' | 'bcd' | 'auto'
        The algorithm to use for the optimization. Block Coordinate Descent
        (BCD) uses Anderson acceleration for faster convergence.
    return_gap : bool
        Return final duality gap.
    dgap_freq : int
        The duality gap is computed every dgap_freq iterations of the solver on
        the active set.
    active_set_init : array, shape (n_dipoles,) or None
        The initial active set (boolean array) used at the first iteration.
        If None, the usual active set strategy is applied.
    X_init : array, shape (n_dipoles, n_times) or None
        The initial weight matrix used for warm starting the solver. If None,
        the weights are initialized at zero.

    Returns
    -------
    X : array, shape (n_active, n_times)
        The source estimates.
    active_set : array, shape (new_active_set_size,)
        The mask of active sources. Note that new_active_set_size is the size
        of the active set after convergence of the solver.
    E : list
        The value of the objective function over the iterations.
    gap : float
        Final duality gap. Returned only if return_gap is True.

    References
    ----------
    .. footbibliography::
    r   Fr'   z-- ALPHA MAX : %srQ   Tr   r?   Úsolver)ÚcdÚbcdr…   r…   r‡   rˆ   zcScikit-learn >= 0.12 cannot be found. Using block coordinate descent instead of coordinate descent.zxCoordinate descent is only available for fixed orientation. Using block coordinate descent instead of coordinate descentzUsing coordinate descentNzUsing block coordinate descentr   r   ©Úordz'Wrong dim for initialized coefficients.g)\�Âõ(ð?)rJ   rA   rK   r   rL   zKIteration %d :: p_obj %f :: dgap %f :: n_active_start %d :: n_active_end %drS   z!Did NOT converge ! (gap: %s > %s))rJ   rA   r   rK   ©r   zFinal active set size: %s)+r   r%   r   r)   r5   r   ÚinfoÚfloatrF   rR   rB   r@   ÚImportErrorr   Ústrr   r	   rN   rD   ru   rW   r   rV   rZ   ra   ÚnormÚlistrT   Ú
ValueErrorrU   Úargsortr   Úaranger`   r"   Úwherer;   r#   r\   ZsearchsortedrH   r   Únewaxis)+r*   r+   r.   rJ   rA   r   Úactive_set_sizeÚdebiasr   r†   Ú
return_gaprL   Zactive_set_initZX_initZ	n_dipolesr   rM   rd   Z	alpha_maxr,   Zhas_sklearnr@   Z
l21_solverÚlcrl   ÚG_tmprf   rg   r-   Zidx_large_corrZnew_active_idxZas_sizer:   ro   Zlc_tmpÚas_Zidx_old_active_setr2   r9   r0   Zidx_active_setrm   Úbiasr   r   r   Úmixed_norm_solver9  sò    =








 "
ÿ
ÿ


$   þÿ

   þÿ
ÿÿ
ÿ
  ÿrž   c                    sÆ  ‡fdd„‰ ‡ ‡fdd„}t ƒ }|dk	rT|j|jd fkrTtd|j|jd ff ƒ‚|dk	r`|nt |jd ¡}|dk}|| }t |jd | jd f¡}t|ƒD �]Ò}| ¡ }| ¡ }|dd…|f |tjdd…f  }|dk	�rDt 	|¡|ˆ k�rt
| ||d	ˆ||||
||d
�\}}}n$t
| ||d	ˆ||d|
||d
�\}}}n$t
| ||d	ˆ||d|
||d
�\}}}t d| 	¡ ˆ  ¡ | 	¡ dk�rH|||< ||| dd…tjf 9 }||ƒ}dtj | t |dd…|f |¡ d¡d  |t 	ˆ |ƒ¡  }| |¡ |dk�rvt ||k¡�rvt t || ¡|k ¡�rvtd| ƒ  �qxq¢t |¡}dtj | ¡d  }| |¡  �qxq¢t |¡�r¼|�r¼t| |dd…|f |ˆd�}||dd…tjf 9 }|||fS )a(  Solve L0.5/L2 mixed-norm inverse problem with active set strategy.

    See reference :footcite:`StrohmeierEtAl2016`.

    Parameters
    ----------
    M : array, shape (n_sensors, n_times)
        The data.
    G : array, shape (n_sensors, n_dipoles)
        The gain matrix a.k.a. lead field.
    alpha : float
        The regularization parameter. It should be between 0 and 100.
        A value of 100 will lead to an empty active set (no active source).
    n_mxne_iter : int
        The number of MxNE iterations. If > 1, iterative reweighting
        is applied.
    maxit : int
        The number of iterations.
    tol : float
        Tolerance on dual gap for convergence checking.
    %(verbose)s
    active_set_size : int
        Size of active set increase at each iteration.
    debias : bool
        Debias source estimates.
    n_orient : int
        The number of orientation (1 : fixed or 3 : free or loose).
    dgap_freq : int or np.inf
        The duality gap is evaluated every dgap_freq iterations.
    solver : 'cd' | 'bcd' | 'auto'
        The algorithm to use for the optimization.
    weight_init : array, shape (n_dipoles,) or None
        The initial weight used for reweighting the gain matrix. If None, the
        weights are initialized with ones.

    Returns
    -------
    X : array, shape (n_active, n_times)
        The source estimates.
    active_set : array
        The mask of active sources.
    E : list
        The value of the objective function over the iterations.

    References
    ----------
    .. footbibliography::
    c                    s   t  t  t|  ¡ ˆ ƒ¡¡S )N)r   r   r   r"   ©Úwr‹   r   r   Úg*  s    z&iterative_mixed_norm_solver.<locals>.gc                    s   dt  ˆ | ƒˆ¡ ¡  S ©Nç       @)r   Úrepeatr`   rŸ   ©r¡   r   r   r   Úgprime-  s    z+iterative_mixed_norm_solver.<locals>.gprimeNr   z?Wrong dimension for weight initialization. Got %s. Expected %s.r   F)r˜   r   rJ   rA   r—   rL   r†   r   zactive set size %dr(   Úfror£   ú*Convergence reached after %d reweightings!r‹   )r‘   r   r’   r   rb   rF   rZ   r"   r–   r   rž   r   rŒ   ra   r�   r)   r\   ÚallÚabsÚprintr|   rH   r   )r*   r+   r.   Zn_mxne_iterrJ   rA   r   r—   r˜   r   rL   r†   Zweight_initr¦   rf   Úweightsr-   r,   ro   ZX0Úactive_set_0r›   Z_active_setrM   r2   r�   r   r¥   r   Úiterative_mixed_norm_solverõ  s¤    5ÿ"
        ý        ý        ý"ÿÿÿ
ÿ

r®   çü©ñÒMbP?c                 C   s¸   | j d }|j d }tj||ftjd�}||ƒ}	d}
tdƒD ]v}|
}t d| ¡ t ||	ƒ¡}t ||¡}t |j	|¡}||ƒ}t 
t |¡¡}
||
 }	t|
| | ƒ|k r< q´q<|
S )zQCompute lipschitz constant for FISTA.

    It uses a power iteration method.
    r   rQ   g}Ã”%­I²Téd   z$Lipschitz estimation: iteration = %d)r   r   rb   r   rZ   r   rŒ   Úrealr)   r5   r#   rª   )r*   r+   ÚphiÚphiTrA   r   rd   Zn_pointsZivÚvÚLÚitZL_oldZGvZGtGvr    r   r   r   Útf_lipschitz_constantq  s"    

r·   c                 C   s&   t  |¡rt  t  | | ¡¡S dS dS )z4Compute np.max(np.abs(A[ia])) possible with empty A.r    N©r   r   r#   rª   )r   Úiar   r   r   Úsafe_max_absŠ  s    
rº   c                 C   s@   t  |¡r| | nd} t  |¡r(|| nd}t  t  | | ¡¡S )z0Compute np.max(np.abs(A)) possible with empty A.r    r¸   )r   r¹   ÚBZibr   r   r   Úsafe_max_abs_diff’  s    r¼   c                   @   s*   e Zd ZdZdd„ Zdd„ Zd
dd„Zd	S )Ú_PhizBHave phi stft as callable w/o using a lambda that does not pickle.c              	   C   sš   t  |¡| _t  |¡| _t  |¡| _t|ƒ| _|d d | _| j| j | _|| _	t
ƒ | _t| j| jƒD ].\}}| j tt  |¡||dd� |d¡¡ qfd S )Nr   r   F)r   r   )r   Ú
atleast_1dÚwsizeÚtstepÚn_coefsrE   Ún_dictsÚn_freqsÚn_stepsrd   r‘   ÚopsÚzipr\   r   Úeyer   )Úselfr¿   rÀ   rÁ   rd   ÚwsÚtsr   r   r   Ú__init__œ  s"    
ÿ ÿÿz_Phi.__init__c                    sB   | j dkrˆ | jd  S t ‡ fdd„| jD ƒ¡t | j ¡ S d S )Nr   r   c                    s   g | ]}ˆ | ‘qS r   r   )Ú.0Úop©Úxr   r   Ú
<listcomp>°  s     z!_Phi.__call__.<locals>.<listcomp>)rÂ   rÅ   r   Zhstackr   )rÈ   rÏ   r   rÎ   r   Ú__call__«  s    
ÿ
ÿz_Phi.__call__r   c              	   C   s¦   |dkrt d| ƒ‚|dkr tnt}d}t| jƒdkr^tjt |¡t | j¡dd… dd�}nt |¡g}t	t|ƒƒD ]*}||||  
d| j| | j| ¡ƒ7 }qv|S )z6Squared L2 norm if ord == 2 and L1 norm if order == 1.)r   r   z3Only supported norm order are 1 and 2. Got ord = %sr   r    Nr   r   )r’   r   r   rE   rÁ   r   Úarray_splitZ
atleast_2dÚcumsumrZ   r   rÃ   rÄ   )rÈ   rs   rŠ   Z	stft_normr�   Úz_rn   r   r   r   r�   ²  s     ÿÿÿz	_Phi.normN)r   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__rË   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 )Ú_PhiTzEHave phi.T istft as callable w/o using a lambda that does not pickle.c           
      C   sÒ   || _ || _|| _|| _t|tjƒr,t|ƒnd| _t	ƒ | _
t	ƒ | _t	ƒ | _t| j| j| j ƒD ]p\}}}|| }| j
 |¡ t |¡ ||||¡}	| j t|	||ƒ ||¡¡ | j t|	d ||ƒ ||¡¡ q\d S )Nr   y              ð?)rÀ   rÃ   rÄ   rd   Ú
isinstancer   ZndarrayrE   rÂ   r‘   rÁ   Úop_reÚop_imrÆ   r\   rÇ   r   r   )
rÈ   rÀ   rÃ   rÄ   rd   ÚnfÚnsrÊ   ÚncrÇ   r   r   r   rË   Ç  s8      ÿ ÿ  ÿ ÿz_PhiT.__init__c                 C   s¨   | j dkr*|j| jd  |j| jd   S t |jd | jf¡}tj	|t 
| j¡d d… dd�}t|| j| jƒD ]"\}}}||j| |j|  7 }qp|t | j ¡ S d S )Nr   r   r   r   )rÂ   r±   rÛ   ÚimagrÜ   r   rF   r   rd   rÒ   rÓ   rÁ   rÆ   r   )rÈ   rs   Zx_outrÔ   Zthis_zrÛ   rÜ   r   r   r   rÑ   Ù  s    
  z_PhiT.__call__N)rÕ   rÖ   r×   rØ   rË   rÑ   r   r   r   r   rÙ   Ä  s   rÙ   c                 C   sP   | j d rHt |j| dd� d|¡jdd�¡}|dk	r>||9 }| ¡ }nd}|S )	zL21 norm for TF.r   r   r‰   r   r   r   Nr    )r   r   r   r�   r   r   )ÚZr²   r   Úw_spaceZl21_normr   r   r   Únorm_l21_tfä  s    
ÿ
rã   c                 C   s‚   | j d rz| j d | }t tjt | ¡d j|dfdd�dd�¡}|j|dfdd�}|dk	rf||9 }|j|dd	� ¡ }nd
}|S )zL1 norm for TF.r   r£   r   ÚFrv   r   Nr   r‰   r    )r   r   r   r   rª   r   r�   )rá   r²   r   Úw_timer   ZZ_Zl1_normr   r   r   Ú
norm_l1_tfñ  s    
 ÿræ   r4   c                 C   s:  t  t| ƒd¡}tt  |t  |j¡dd… ¡ƒD ].\}}d|d|j| …< d||j|  d…< q0|dk	rˆ|dk}| | } || }|| }|dk	ržt  | | ¡nt  | ¡}	|dkr´|	S |dkràt  	|j
| ddd…f dd� ¡ ¡S |	dkrìdS |dk�r| ||	 k}
n&| |t  | |d|  ||   ¡ k}
|
 ¡ dk�r<|	S |dk	�rtt  | |
 ||
  ¡ddd… }||
 | }nt  | |
 ¡ddd… }| |
 | } ||
 | }t  | |¡} |dk	�rÆt  ||¡}| jd }|dk�r t  | d ¡}t  d|d ¡}t  | ¡}|| d  d	| |   | }nNt  | d ¡}t  |d ¡}t  | | ¡}|| | d  d	| | |   | }t  ||d d| d  |d  k¡d }|j�r¬|d d n|d }|| }|| }|| }|d | |d d| d   }t  |¡d
k �r|d	| |  S || d ||  }|| t  	|¡ | S dS )aÃ  Weighted epsilon norm.

    The weighted epsilon norm is the dual norm of::

    w_{space} * (1. - l1_ratio) * ||Y||_2 + l1_ratio * ||Y||_{1, w_{time}}.

    where `||Y||_{1, w_{time}} = (np.abs(Y) * w_time).sum()`

    Warning: it takes into account the fact that Y only contains coefficients
    corresponding to the positive frequencies (see `stft_norm2()`): some
    entries will be counted twice. It is also assumed that all entries of both
    Y and w_time are non-negative. See
    :footcite:`NdiayeEtAl2016,BurdakovMerkulov2001`.

    Parameters
    ----------
    Y : array, shape (n_coefs,)
        The input data.
    l1_ratio : float between 0 and 1
        Tradeoff between L2 and L1 regularization. When it is 0, no temporal
        regularization is applied.
    phi : instance of _Phi
        The TF operator.
    w_space : float
        Scalar weight of the L2 norm. By default, it is taken equal to 1.
    w_time : array, shape (n_coefs, ) | None
        Weights of each TF coefficient in the L1 norm. If None, weights equal
        to 1 are used.


    Returns
    -------
    nu : float
        The value of the dual norm evaluated at Y.

    References
    ----------
    .. footbibliography::
    r   Nr   r   r    r4   r‰   r   r£   g»½×Ùß|Û=)r   ÚfullrE   r}   rÒ   rÓ   rÁ   rÄ   r#   r   r�   r   r“   r¤   r   r”   r•   r!   rª   )ÚYÚl1_ratior²   râ   rå   Zfreqs_countrn   ÚfcZnonzero_weightsZ
norm_inf_Yrm   Zidx_sortrc   Zp_sum_Y2Zp_sum_w2Zp_sum_YwÚupperZupper_greaterZi0ÚdenomÚdeltar   r   r   Únorm_epsilon   s|    ,ÿ $
ÿ
 



ÿÿÿÿ rî   c                 C   s¾   | j d | }t |t | j|¡ƒ¡}|j|dfdd�}tjj|dd�}|j|dfdd�}d}	t|ƒD ]R}
||
 }|dk	r‚||
 nd}|dk	r–||
 nd	}t	|||||d
�}||	krf|}	qf|	S )aü  Weighted epsilon-inf norm of phi(np.dot(G.T, R)).

    Parameters
    ----------
    G : array, shape (n_sensors, n_sources)
        Gain matrix a.k.a. lead field.
    R : array, shape (n_sensors, n_times)
        Residual.
    phi : instance of _Phi
        The TF operator.
    l1_ratio : float between 0 and 1
        Parameter controlling the tradeoff between L21 and L1 regularization.
        0 corresponds to an absence of temporal regularization, ie MxNE.
    n_orient : int
        Number of dipoles per location (typically 1 or 3).
    w_space : array, shape (n_positions,) or None.
        Weights for the L2 term of the epsilon norm. If None, weights are
        all equal to 1.
    w_time : array, shape (n_positions, n_coefs) or None
        Weights for the L1 term of the epsilon norm. If None, weights are
        all equal to 1.

    Returns
    -------
    nu : float
        The maximum value of the epsilon norms over groups of n_orient dipoles
        (consecutive rows of phi(np.dot(G.T, R))).
    r   r   rä   rv   r   r   r    Nr4   ©râ   rå   )
r   r   rª   r)   r5   r   ra   r�   rZ   rî   )r+   r0   r²   ré   r   râ   rå   r   ZGTRPhiÚnurm   ZGTRPhi_Zw_tZw_sZnorm_epsr   r   r   Únorm_epsilon_infy  s     
ÿrñ   c              	   C   s  ||ƒ}t  |dd…|f |¡}| | }|dk	rD||dd|…  }nd}|
dk	rd|
|dd|…  }nd}t||||ƒ}t||||ƒ}t|ƒ}d| ||  ||  }|||  }t||||||
|d�}td|| | ƒ}|d|d   | |t  || ¡  }t||	ƒ}|| }||||fS )ax  Duality gap for the time-frequency mixed norm inverse problem.

    See :footcite:`GramfortEtAl2012,NdiayeEtAl2016`

    Parameters
    ----------
    M : array, shape (n_sensors, n_times)
        The data.
    G : array, shape (n_sensors, n_sources)
        Gain matrix a.k.a. lead field.
    Z : array, shape (n_active, n_coefs)
        Sources in TF domain.
    active_set : array of bool, shape (n_sources, )
        Mask of active sources.
    alpha_space : float
        The spatial regularization parameter.
    alpha_time : float
        The temporal regularization parameter. The higher it is the smoother
        will be the estimated time series.
    phi : instance of _Phi
        The TF operator.
    phiT : instance of _PhiT
        The transpose of the TF operator.
    n_orient : int
        Number of dipoles per locations (typically 1 or 3).
    highest_d_obj : float
        The highest value of the dual objective so far.
    w_space : array, shape (n_positions, )
        Array of spatial weights.
    w_time : array, shape (n_positions, n_coefs)
        Array of TF weights.

    Returns
    -------
    gap : float
        Dual gap
    p_obj : float
        Primal objective
    d_obj : float
        Dual objective. gap = p_obj - d_obj
    R : array, shape (n_sensors, n_times)
        Current residual (M - G * X)

    References
    ----------
    .. footbibliography::
    Nr(   rï   r4   r   )	r   r)   ræ   rã   r   rñ   r6   r   r#   )r*   r+   rá   r-   Úalpha_spaceÚ
alpha_timer²   r³   r   rg   râ   rå   r,   r/   r0   Ú	w_time_asÚ
w_space_asZ	penaltyl1Z
penaltyl21r1   r2   ré   r7   r8   r9   r:   r   r   r   Ú
dgap_l21l1©  s.    1 ÿ&
rö   c           5         sâ  |j d }|| }t |¡}t |j ||d¡ ddd¡¡}|  ¡ }t |d d |… ¡d }|D ] }|t 	|| |	ˆ | ƒ¡8 }q`g }|d kr˜|| }n|| |d d …d f  }|
d krÂ|| }n||
 | }d}tj
 }t|ƒD �]ð}|D �]}|| } | | }!|| }"ˆ | }#|| |!… }$t |$¡}%t 	|"j|¡||  }&|& ¡ }'|%�rl|	|#ƒ}(|t 	|"|(¡7 }|'|(7 }'tj |'d¡})|)|| k�r¤|%�rdˆ |< d|$d d …< qì||&ƒ}*|%�r¼|#|* }+n|*}+tjj|+dd�},t |,|| k¡�rúdˆ |< d|$d d …< qìt d	|| t |,|| ¡  d¡}-|d k	�r8d|-|| dk< |+|-tjd d …f 9 }+|+j }.t |j|+dd
� ¡ ¡}/|/|| k�r�dˆ |< d|$d d …< qìt d	|| t |/|| ¡  d¡}-|+|-9 }+|+jd|.dd … žŽ  ¡ ˆ |< d|$d d …< |	ˆ | ƒ}0|t 	|"|0¡8 }qì|d | dk�r t ‡ fdd„t|ƒD ƒ¡}1t| ||1|||||	|||
|d�\}2}3}}4|2|k }| |3¡ t d|d t |¡| f ¡ t d|2|3|f ¡ |�r¬ �qÖ|d k	rât |¡t|ƒ || krâ �qÖqâˆ |||fS )Nr   r   r   r   Fr§   r    r   r4   r‰   Tc                    s"   g | ]}t  ˆ | ¡rˆ | ‘qS r   ©r   rH   ©rÌ   Úpos©rá   r   r   rÐ   V  s    ÿz._tf_mixed_norm_solver_bcd_.<locals>.<listcomp>rï   z 
    Iteration %d :: n_active %dz%    dgap %.2e :: p_obj %f :: d_obj %f)r   )r   r   rW   r]   r5   r   Z	transposer"   r•   r)   rT   rZ   rH   ra   r�   r©   Úmaximumr–   r   r   Úvstackrö   r\   r   rŒ   r�   )5r*   r+   rá   r-   Ú
candidatesrò   ró   rI   r²   r³   râ   rå   r   rJ   rA   rL   ÚpercZtimeitr   re   r   ZGdr0   Úactiverm   rf   Zalpha_time_lcZalpha_space_lcÚ	convergedr9   rn   ZjjZidsZider€   ZZ_jZactive_set_jZ
was_activeZGTRr   r�   Z	rows_normZGTR_phiZZ_j_newZcol_normr‚   Z
shape_initZrow_normZ	Z_j_phi_TÚZdr:   r2   rM   r   rú   r   Ú_tf_mixed_norm_solver_bcd_ù  sÐ    

ÿ




 ÿÿ
ÿþ          þ
 ÿ  ÿr  c           $         s^  | j \}}|j d }||
 }t t |¡d¡‰ tj|td�}g }|d k	rÞ|j ||j ¡ fkrdt	dƒ‚t
|ƒD ]D}t |||
 |d |
 … ¡rld|||
 |d |
 …< | |¡ qlt|ƒrÞˆ  tt|t || t|ƒ¡ƒƒ¡ g }t
|ƒ}tj }t t |¡d¡}| tt|ˆ  ¡ ƒƒ¡ t| |||||||||||	|
d|d |d�\‰ }}}||7 }t |d d |
… ¡d }ttt
t|ƒƒ‡ fdd	„|D ƒƒƒ}t
t|ƒƒ}|d k	�r¼||d d |
…  }nd }|	d k	�rÞ|	|d d |
…  }nd }t| |d d …|f |tjt|ƒ|
 td�|||||d d |
…  |||||
|||d
|d�\‰ }}}t |d d |
… ¡d }| ¡ ||< ||7 }d}|ròt ‡ fdd	„t
tˆ ƒƒD ƒ¡} t| || ||||||
|||	ƒ\}!}"}}t d|!|"|t |¡|
 f ¡ |!|k ròt d¡ �qôqò| ¡ �r(t ‡ fdd	„t
tˆ ƒƒD ƒ¡‰ |ˆ ƒ}#n(tjd|j ¡ ftjd�‰ t d|f¡}#|#ˆ |||!fS )Nr   r    rQ   z@Z_init must be None or an array with shape (n_sources, n_coefs).T)râ   rå   r   rJ   rA   rþ   r   r   c                    s   g | ]}ˆ | ‘qS r   r   )rÌ   rm   rú   r   r   rÐ   ˜  s     z8_tf_mixed_norm_solver_bcd_active_set.<locals>.<listcomp>r(   )râ   rå   r   rJ   rA   rL   rþ   r   c                    s"   g | ]}t  ˆ | ¡rˆ | ‘qS r   r÷   rø   rú   r   r   rÐ   ²  s      z1
dgap %.2e :: p_obj %f :: d_obj %f :: n_active %dz
Convergence reached!
c                    s"   g | ]}t  ˆ | ¡rˆ | ‘qS r   r÷   rø   rú   r   r   rÐ   ½  s      )r   ÚdictÚfromkeysr   r”   rF   rU   rÁ   r   Ú	ExceptionrZ   rH   r\   rE   ÚupdaterÆ   ZvsplitrT   Úvaluesr  r•   rb   r"   rü   rö   r   rŒ   Ú
complex128)$r*   r+   rò   ró   rI   r²   r³   ÚZ_initrâ   rå   r   rJ   rA   rL   r   Ú	n_sensorsrd   re   r   r-   rÿ   Úiirf   rý   r9   ZE_tmprM   Zcandidates_rõ   rô   rœ   r   r  r:   r2   r,   r   rú   r   Ú$_tf_mixed_norm_solver_bcd_active_setl  sÎ    


ÿ              ý$

          ø	           þÿ

 
r  é@   é   c                  C   s¬  | j \}}|j \}}|| }t |¡}t |¡}t|ƒt|ƒkrPtd||f ƒ‚t | j d | t¡ ¡ t¡}|d d }|| }t	||||ƒ}t
||||ƒ}|dkr¼tj|| dd�}nVt |¡}t|ƒD ]B}|dd…|| |d | …f }tjjt |j|¡dd�||< qÎt d¡ t| ||||||d||||dd	�\}}}}}t |¡�rŒ|
�rŒt| |dd…|f ||d
�}||dd…tjf 9 }|�rž||||fS |||fS dS )ac  Solve TF L21+L1 inverse solver with BCD and active set approach.

    See :footcite:`GramfortEtAl2013b,GramfortEtAl2011,BekhtiEtAl2016`.

    Parameters
    ----------
    M : array, shape (n_sensors, n_times)
        The data.
    G : array, shape (n_sensors, n_dipoles)
        The gain matrix a.k.a. lead field.
    alpha_space : float
        The spatial regularization parameter.
    alpha_time : float
        The temporal regularization parameter. The higher it is the smoother
        will be the estimated time series.
    wsize: int or array-like
        Length of the STFT window in samples (must be a multiple of 4).
        If an array is passed, multiple TF dictionaries are used (each having
        its own wsize and tstep) and each entry of wsize must be a multiple
        of 4.
    tstep: int or array-like
        Step between successive windows in samples (must be a multiple of 2,
        a divider of wsize and smaller than wsize/2) (default: wsize/2).
        If an array is passed, multiple TF dictionaries are used (each having
        its own wsize and tstep), and each entry of tstep must be a multiple
        of 2 and divide the corresponding entry of wsize.
    n_orient : int
        The number of orientation (1 : fixed or 3 : free or loose).
    maxit : int
        The number of iterations.
    tol : float
        If absolute difference between estimates at 2 successive iterations
        is lower than tol, the convergence is reached.
    debias : bool
        Debias source estimates.
    return_gap : bool
        Return final duality gap.
    dgap_freq : int or np.inf
        The duality gap is evaluated every dgap_freq iterations.
    %(verbose)s

    Returns
    -------
    X : array, shape (n_active, n_times)
        The source estimates.
    active_set : array
        The mask of active sources.
    E : list
        The value of the objective function every dgap_freq iteration. If
        log_objective is False or dgap_freq is np.inf, it will be empty.
    gap : float
        Final duality gap. Returned only if return_gap is True.

    References
    ----------
    .. footbibliography::
    úWThe same number of window sizes and steps must be passed. Got tstep = %s and wsize = %sr   r   r   r   Nr‰   z7Using block coordinate descent with active set approach)r	  r   rJ   rA   rL   r   r‹   )r   r   r¾   rE   r’   ÚceilÚastyper�   Úintr½   rÙ   r   rV   rZ   ra   r�   r)   r5   r   rŒ   r  rH   r   r–   ) r*   r+   rò   ró   r¿   rÀ   r   rJ   rA   r—   r˜   r™   rL   r   r
  rd   re   r   rÄ   rÃ   rÁ   r²   r³   rš   rl   r›   r,   rá   r-   rf   r:   r�   r   r   r   Útf_mixed_norm_solverÆ  sT    >



þ 
  
          ýr  c           +         sž  | j \}}|j d }|ˆ }t |¡}t |¡}t|ƒt|ƒkrPtd||f ƒ‚t || t¡ ¡ t¡}|d d }|| }t	||||ƒ‰t
||||ƒ}ˆdkr¶tj|| dd�}nVt |¡}t|ƒD ]B}|dd…|ˆ |d ˆ …f }tjjt |j|¡dd�||< qÈ‡‡fdd	„‰ ‡ fd
d„}‡fdd„‰‡fdd„}tƒ }tj|td�}tj|ˆj ¡ ftjd�}t|ƒD �]Ö}| ¡ }| ¡ }|dk�ržd} d}!n4d||ƒ } ||ƒ}!d|!|!dk< d|! }!d|!|!dk < t| |dd…|f ||||ddˆ…  ˆ||| |!ˆ|||dd�\}"}}#}$}%|#||< | ¡ dk�rt ˆ | ¡ ƒ¡}&ˆjˆ| ¡ ƒdd� ¡ }'dtj | t |dd…|f |"¡ d¡d  ||&  ||'  }(| |(¡ t d|d | ¡ ˆ |(f ¡ t ||¡�rJt t || ¡¡})|)|k �rJt d| ƒ  �qNnDdtj | ¡d  }(| |(¡ t d|d | ¡ ˆ |(f ¡  �qN�qt|	�r”| ¡ dk�r”t!| |dd…|f |"ˆd�}*|"|*dd…tj"f 9 }"|"||fS )aV  Solve TF L0.5/L1 + L0.5 inverse problem with BCD + active set approach.

    Parameters
    ----------
    M: array, shape (n_sensors, n_times)
        The data.
    G: array, shape (n_sensors, n_dipoles)
        The gain matrix a.k.a. lead field.
    alpha_space: float
        The spatial regularization parameter. The higher it is the less there
        will be active sources.
    alpha_time : float
        The temporal regularization parameter. The higher it is the smoother
        will be the estimated time series. 0 means no temporal regularization,
        a.k.a. irMxNE.
    n_tfmxne_iter : int
        Number of TF-MxNE iterations. If > 1, iterative reweighting is applied.
    wsize : int or array-like
        Length of the STFT window in samples (must be a multiple of 4).
        If an array is passed, multiple TF dictionaries are used (each having
        its own wsize and tstep) and each entry of wsize must be a multiple
        of 4.
    tstep : int or array-like
        Step between successive windows in samples (must be a multiple of 2,
        a divider of wsize and smaller than wsize/2) (default: wsize/2).
        If an array is passed, multiple TF dictionaries are used (each having
        its own wsize and tstep), and each entry of tstep must be a multiple
        of 2 and divide the corresponding entry of wsize.
    maxit : int
        The maximum number of iterations for each TF-MxNE problem.
    tol : float
        If absolute difference between estimates at 2 successive iterations
        is lower than tol, the convergence is reached. Also used as criterion
        on duality gap for each TF-MxNE problem.
    debias : bool
        Debias source estimates.
    n_orient : int
        The number of orientation (1 : fixed or 3 : free or loose).
    dgap_freq : int or np.inf
        The duality gap is evaluated every dgap_freq iterations.
    %(verbose)s

    Returns
    -------
    X : array, shape (n_active, n_times)
        The source estimates.
    active_set : array
        The mask of active sources.
    E : list
        The value of the objective function over iterations.
    r   r  r   r   r   Nr‰   c                    s*   t  t  ˆj| dd� dˆ ¡jdd�¡¡S )Nr   r‰   r   r   r   )r   r   r�   r   r   rú   )r   r²   r   r   Úg_space  s     ÿÿz/iterative_tf_mixed_norm_solver.<locals>.g_spacec                    s   dˆ | ƒ S r¢   r   rú   )r  r   r   Úg_space_prime_invƒ  s    z9iterative_tf_mixed_norm_solver.<locals>.g_space_prime_invc              	      sF   t  t  t jt  | ¡d jˆ dfdd�dd�¡jd| jd fdd�¡S )Nr£   r   rä   rv   r   r   r   )r   r   r   rª   r   r   rú   r‹   r   r   Úg_time†  s     ÿÿ þz.iterative_tf_mixed_norm_solver.<locals>.g_timec                    s   dˆ | ƒ S r¢   r   rú   )r  r   r   Úg_time_prime_inv‹  s    z8iterative_tf_mixed_norm_solver.<locals>.g_time_prime_invrQ   r4   r{   r    )r	  râ   rå   r   rJ   rA   rL   r   r(   r§   r£   z&Iteration %d: active set size=%d, E=%fr¨   zIteration %d: as_size=%d, E=%fr‹   )#r   r   r¾   rE   r’   r  r  r�   r  r½   rÙ   r   rV   rZ   ra   r�   r)   r5   r‘   rb   rU   rF   rÁ   r  r"   r  r\   r   rŒ   Zarray_equalZamaxrª   r«   r   r–   )+r*   r+   rò   ró   Zn_tfmxne_iterr¿   rÀ   rJ   rA   r˜   r   rL   r   r
  rd   re   r   rÄ   rÃ   rÁ   r³   rš   rl   r›   r  r  rf   r-   rá   ro   r­   ZZ0râ   rå   r,   Zactive_set_ZE_rM   Zl21_penaltyZ
l1_penaltyr2   Zmax_diffr�   r   )r  r  r   r²   r   Úiterative_tf_mixed_norm_solver-  s¸    8



þ
  
           ü"ÿÿÿþ
 
 ÿ

 
 ÿ
r  )T)T)r<   r=   NNr   r>   )rO   r=   NNr   r>   TrP   )rƒ   r=   Nr„   Tr   r…   Fr>   NN)	rƒ   r=   Nr„   Tr   r>   r…   N)r¯   N)N)r4   N)NN)NN)	NNr   rO   r=   r>   NTN)NNNr   rO   r=   r>   N)
r  r  r   rO   r=   NTFr>   N)r  r  rƒ   r=   Tr   r>   N)/Ú	functoolsÚmathr   Únumpyr   Zmxne_debiasingr   Úutilsr   r   r   r	   r
   r   r   Ztime_frequency._stftr   r   r   r   Ú	lru_cacher   r   r%   r&   r3   r;   rN   ru   r^   rž   r®   r·   rº   r¼   Úobjectr½   rÙ   rã   ræ   rî   rñ   rö   r  r  r  r  r   r   r   r   Ú<module>   sØ   $

	
	'-         þ             þe9              ý <              ý{+ 

y
1   ÿ
R               ü
s            ûY              ýf             ý