U
    f»{j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	 ddl
mZmZmZmZ dd„ Zd$d	d
„Zd%dd„Zed&dd„ƒZdd„ Zdd„ Zdej Zddej  Zdd„ Zedd„ ƒZdd„ Zdd„ Zed d!„ ƒZd"d#„ ZdS )'é    N)Úlegendreé   )Úparallel_func)ÚloggerÚverboseÚ_get_extra_data_pathÚfill_docc                 C   sZ   |}|}d|  d | | | d |  |  }| | ||  }| d | ||  }|||fS )z9Compute the next Legendre polynomial and its derivatives.r   é   © )ÚnÚxÚp0Zp01Zp0dZp0ddZold_p0Zold_p0dr
   r
   úU/var/www/html/bwave/python/venv/lib/python3.8/site-packages/mne/forward/_lead_dots.pyÚ_next_legen_der   s    $r   éd   c                 C   s   t  | |d ¡S )z*Get Legendre polynomials expanded about x.r	   )r   Z	legvander)r   Ún_coeffr
   r
   r   Ú
_get_legen"   s    r   c           	      C   sä   t  t| ƒ|df¡}t|| ƒD ]À\}}|dd…df |dd…df |dd…df   }}}d|g|dd…< ddg|dd…< ddg|dd…< td|ƒD ]H}t||||d  ||d  ||d  ||d  ƒ\||< ||< ||< q”q|S )z5Get Legendre polynomial derivatives expanded about x.é   Nr   r	   r   ç      ð?g        )ÚnpÚemptyÚlenÚzipÚranger   )	Zxxr   ÚcoeffsÚcr   Zp0sZp0dsZp0ddsr   r
   r
   r   Ú_get_legen_der'   s     4  
 
 
 
ÿr   Fé N  c              	   C   sN  |d dkrt dƒ‚t tƒ d¡}t |¡s6t |¡ | dkrjt |d||f ¡}t}d}|d |d	f}	n(t |d
||f ¡}t}d}|d |f}	t 	|¡r |rüt
 d| ¡ t dd|d ¡}
||
|ƒ tj¡}|sút|dƒ�}| | ¡ ¡ W 5 Q R X n6t
 d| ¡ t|ddd��}t |tj¡}W 5 Q R X |	|_tjd|td�}| dk�rtƒ }|�r‚| |d| d d| d   ¡ n| |d| d  ¡ | |d |d  ¡ | |d |d  ¡ |dd…dd…ddddgf }t |¡ddddgdd…f j}t |¡}|}n4d| d d| d  | }|dd…dd…f  ¡ }||fS )zDReturn a (generated) LUT of Legendre (derivative) polynomial coeffs.r   r   zn_interp must be evenZtablesÚmegzlegder_%s_%s.binz derivativer	   r   zlegval_%s_%s.binÚ zGenerating Legendre%s table...éÿÿÿÿÚwbzReading Legendre%s table...Úrb)Ú	buffering)Zdtypeç       @r   g      @N)ÚRuntimeErrorÚopÚjoinr   ÚisdirÚosÚmakedirsr   r   Úisfiler   Úinfor   ZlinspaceZastypeZfloat32ÚopenÚwriteÚtobytesÚfromfileÚshapeÚarangeÚfloatÚlistÚappendÚarrayÚTZascontiguousarrayÚcopy)Úch_typeÚvolume_integralr   Zn_interpZ
force_calcr   ÚfnameZleg_funZ	extra_strZ	lut_shapeZx_interpÚlutZfidÚn_factZn_factsr
   r
   r   Ú_get_legen_table5   sT    



ÿ
 
r>   c                 C   sÐ   ddt |jƒ d  }t t d| j|¡| jgg¡}t | j¡}t|dd… |dd… ƒD ]p\}}||||… ƒ}	t | ||… dd…tj	f d|jd f¡}
tj
|
d|
d� |	|
9 }	t |	|¡|||…< qZ|S )	z?Lead field dot products using Legendre polynomial (P_n) series.é€ðúé   r   r   Nr    r	   ©ÚaxisÚout)Úmaxr1   r   Úconcatenater2   Úsizer   r   ÚtileÚnewaxisÚcumprodÚdot)ÚbetaÚcthetaÚlut_funr=   Ún_chunkÚlimsÚs0ÚstartÚstopr   Zbetansr
   r
   r   Ú_comp_sum_eegn   s    ",rS   c              
   C   sð   t  |jd t| ƒf¡}ddt|jƒ d  }t  t  d| j|¡| jgg¡}t|dd… |dd… ƒD ]„\}}	t  	| ||	… t j
 |jd df¡}
|
d  | ||	… 9  < t j|
d|
d� t jd	|
|||||	… ƒ|dd…||	…f d
� qf|S )ai  Lead field dot products using Legendre polynomial (P_n) series.

    Parameters
    ----------
    beta : array, shape (n_points * n_points, 1)
        Coefficients of the integration.
    ctheta : array, shape (n_points * n_points, 1)
        Cosine of the angle between the sensor integration points.
    lut_fun : callable
        Look-up table for evaluating Legendre polynomials.
    n_fact : array
        Coefficients in the integration sum.
    volume_integral : bool
        If True, compute volume integral.

    Returns
    -------
    sums : array, shape (4, n_points * n_points)
        The results.
    r	   r?   r@   r   r   Nr    rA   zji,jk,ijk->ki)rC   )r   r   r1   r   rD   rE   r2   rF   r   rG   rH   rI   Úeinsum)rK   rL   rM   r=   r:   ÚsumsrN   rO   rQ   rR   Zbbetar
   r
   r   Ú_comp_sums_meg   s    ""$ÿrV   g›+¡†›„&=r   g      @c           #      C   s„  |dkrt |ƒt |ƒf}d}nt |ƒf}d}t |¡}t |¡}t |¡}t |¡}t d||¡}t |dd|¡ |dd…tjdd…f }|tjdd…dd…f }|dd…tjf |tjdd…f  }| |  | }|dk�rÖt| ¡ | ¡ |
||	ƒ}d|j	 |_	t d||¡}t d||¡}t d||¡}t d||¡}t d||¡}|| | }|| ||  }|| |d	  d
| | |d   || | |d   |||  |||   |d   }|t
| 9 }|	�r|| 9 }n.t| ¡ | ¡ |
|ƒ}|j	|_	|t9 }|| }d	} |t |¡9 }|dk	�r6||dd…tjf 9 }t|ƒD ]@\}!}"tj|dd…| | t |"ƒ …f |d�||!< | t |"ƒ7 } �q>|S )a=  Lead field dot product computation for M/EEG in the sphere model.

    Parameters
    ----------
    r : float
        The integration radius. It is used to calculate beta as:
        beta = (r * r) / (lr1 * lr2).
    rr1 : array, shape (n_points x 3)
        Normalized position vectors of integrations points in first sensor.
    rr2s : list
        Normalized position vector of integration points in second sensor.
    lr1 : array, shape (n_points x 1)
        Magnitude of position vector of integration points in first sensor.
    lr2s : list
        Magnitude of position vector of integration points in second sensor.
    cosmags1 : array, shape (n_points x 1)
        Direction of integration points in first sensor.
    cosmags2s : list
        Direction of integration points in second sensor.
    w1 : array, shape (n_points x 1) | None
        Weights of integration points in the first sensor.
    w2s : list
        Weights of integration points in the second sensor.
    volume_integral : bool
        If True, compute volume integral.
    lut : callable
        Look-up table for evaluating Legendre polynomials.
    n_fact : array
        Coefficients in the integration sum.
    ch_type : str
        The channel type. It can be 'meg' or 'eeg'.

    Returns
    -------
    result : float
        The integration sum.
    Nr	   z	ik,jk->ijr    r   )é   z
ik,ijk->ijz
jk,ijk->ijr   r$   r   r   ©rB   )r   r   r   rE   rT   ZcliprH   rV   Úflattenr1   Ú
_meg_constrS   Ú
_eeg_constÚ	enumerateÚsum)#ÚrZrr1_origZrr2sZlr1Zlr2sÚcosmags1Z	cosmags2sZw1Zw2sr:   r<   r=   r9   Z	out_shapeZsum_axisrC   Zrr2Zlr2Úcosmags2ÚctZrr1Zlr1lr2rK   rU   Zn1c1Zn1c2Zn2c1Zn2c2Zn1n2Zpart1Zpart2ÚresultÚoffsetÚiiZw2r
   r
   r   Ú_fast_sphere_dot_r0¶   sb    '




$
ÿ
ÿþý

*re   c                    s¼   ˆ dkrˆd ‰‡fdd„|D ƒ‰dd„ ˆD ƒ‰dd„ t ˆˆƒD ƒ‰dd„ |D ƒ‰dd„ |D ƒ‰
tt|ƒ\}‰}|‡ ‡‡‡‡‡‡‡‡	‡
f
d	d
„t t tˆƒ¡|¡D ƒƒ}	tj|	dd�}
|
S )aË  Perform the lead field dot product integrations.

    Parameters
    ----------
    intrad : float
        The integration radius. It is used to calculate beta as:
        beta = (intrad * intrad) / (r1 * r2).
    volume : bool
        If True, perform volume integral.
    coils : list of dict
        The coils.
    r0 : array, shape (3 x 1)
        The origin of the sphere.
    ch_type : str
        The channel type. It can be 'meg' or 'eeg'.
    lut : callable
        Look-up table for evaluating Legendre polynomials.
    n_fact : array
        Coefficients in the integration sum.
    %(n_jobs)s

    Returns
    -------
    products : array, shape (n_coils, n_coils)
        The integration products.
    Úeegçffffffæ?c                    s&   g | ]}|d  ˆ t jdd…f  ‘qS ©ZrmagN©r   rH   ©Ú.0Zcoil©Úr0r
   r   Ú
<listcomp>@  s     z!_do_self_dots.<locals>.<listcomp>c                 S   s$   g | ]}t  t j|| d d�¡‘qS ©r	   rX   ©r   Úsqrtr]   ©rk   r^   r
   r
   r   rn   A  s     c                 S   s&   g | ]\}}||d d …t jf  ‘qS ©Nri   ©rk   r^   Zrlr
   r
   r   rn   B  s     c                 S   s   g | ]}|d  ‘qS ©Zcosmagr
   rj   r
   r
   r   rn   C  s     c                 S   s   g | ]}|d  ‘qS ©Úwr
   rj   r
   r
   r   rn   D  s     c                 3   s(   | ] }ˆˆˆˆˆˆ	ˆˆˆˆ |ƒ
V  qd S rs   r
   ©rk   Úidx)
r9   ÚcosmagsÚintradr<   r=   Úp_funÚrlensÚrmagsÚvolumeÚwsr
   r   Ú	<genexpr>F  s   þ
     ÿz _do_self_dots.<locals>.<genexpr>r   rX   )r   r   Ú_do_self_dots_subsetr   Úarray_splitr2   r   r]   )r{   r   Úcoilsrm   r9   r<   r=   Ún_jobsÚparallelÚprodsÚproductsr
   )r9   rz   r{   r<   r=   r|   rm   r}   r~   r   r€   r   Ú_do_self_dots!  s    þr‰   c
                 C   sœ   t  t|ƒt|ƒf¡}
|	D ]|}|d }t| || |d|… || |d|… || |d|… || |d|… ||||ƒ}||
|d|…f< ||
d|…|f< q|
S )zParallelize.r	   N)r   Úzerosr   re   )r{   r~   r}   rz   r€   r   r<   r=   r9   ry   rˆ   Úci1Zci2Úresr
   r
   r   r‚   M  s*      
  
 
  
   ýr‚   c                    s  |dkr| d } ‡ fdd„|D ƒ}‡ fdd„|D ƒ}	dd„ |D ƒ}
dd„ |	D ƒ}dd„ t ||
ƒD ƒ}d	d„ t |	|ƒD ƒ}	d
d„ |D ƒ}dd„ |D ƒ}dd„ |D ƒ}dd„ |D ƒ}t t|ƒt|	ƒf¡}tt|ƒƒD ]D}t| || |	|
| ||| ||| |||||ƒ}|||dd…f< qÒ|S )a€  Compute lead field dot product integrations between two coil sets.

    The code is a direct translation of MNE-C code found in
    `mne_map_data/lead_dots.c`.

    Parameters
    ----------
    intrad : float
        The integration radius. It is used to calculate beta as:
        beta = (intrad * intrad) / (r1 * r2).
    volume : bool
        If True, compute volume integral.
    coils1 : list of dict
        The original coils.
    coils2 : list of dict
        The coils to which data is being mapped.
    r0 : array, shape (3 x 1).
        The origin of the sphere.
    ch_type : str
        The channel type. It can be 'meg' or 'eeg'
    lut : callable
        Look-up table for evaluating Legendre polynomials.
    n_fact : array
        Coefficients in the integration sum.

    Returns
    -------
    products : array, shape (n_coils, n_coils)
        The integration products.
    rf   rg   c                    s&   g | ]}|d  ˆ t jdd…f  ‘qS rh   ri   rj   rl   r
   r   rn     s     z"_do_cross_dots.<locals>.<listcomp>c                    s&   g | ]}|d  ˆ t jdd…f  ‘qS rh   ri   rj   rl   r
   r   rn   €  s     c                 S   s$   g | ]}t  t j|| d d�¡‘qS ro   rp   rr   r
   r
   r   rn   ‚  s     c                 S   s$   g | ]}t  t j|| d d�¡‘qS ro   rp   rr   r
   r
   r   rn   ƒ  s     c                 S   s&   g | ]\}}||d d …t jf  ‘qS rs   ri   rt   r
   r
   r   rn   …  s     c                 S   s&   g | ]\}}||d d …t jf  ‘qS rs   ri   rt   r
   r
   r   rn   †  s     c                 S   s   g | ]}|d  ‘qS rv   r
   rj   r
   r
   r   rn   ˆ  s     c                 S   s   g | ]}|d  ‘qS rv   r
   rj   r
   r
   r   rn   ‰  s     c                 S   s   g | ]}|d  ‘qS ru   r
   rj   r
   r
   r   rn   ‹  s     c                 S   s   g | ]}|d  ‘qS ru   r
   rj   r
   r
   r   rn   Œ  s     N)r   r   rŠ   r   r   re   )r{   r   Zcoils1Zcoils2rm   r9   r<   r=   Zrmags1Zrmags2Zrlens1Zrlens2Zws1Zws2r_   r`   rˆ   r‹   rŒ   r
   rl   r   Ú_do_cross_dots]  s>                þr�   c
                    s&  ‡fdd„|D ƒ‰
dd„ ˆ
D ƒ‰	dd„ t ˆ
ˆ	ƒD ƒ‰
dd„ |D ƒ‰dd„ |D ƒ‰d‰d‰ˆ dkrhˆd	 ‰|d
 | ˆtjdd…f  ‰t tjˆˆ dd�¡‰ˆˆdd…tjf  ‰|d | ‰tt|	ƒ\}
‰}	|
‡ ‡‡‡‡‡‡‡‡	‡
‡‡‡‡‡fdd„t t t	ˆ
ƒ¡|	¡D ƒƒ}tj|dd�}|S )aB  Compute the map construction products.

    Parameters
    ----------
    intrad : float
        The integration radius. It is used to calculate beta as:
        beta = (intrad * intrad) / (r1 * r2)
    volume : bool
        If True, compute a volume integral.
    coils : list of dict
        The coils.
    surf : dict
        The surface on which the field is interpolated.
    sel : array
        Indices of the surface vertices to select.
    r0 : array, shape (3 x 1)
        The origin of the sphere.
    ch_type : str
        The channel type. It can be 'meg' or 'eeg'.
    lut : callable
        Look-up table for Legendre polynomials.
    n_fact : array
        Coefficients in the integration sum.
    %(n_jobs)s

    Returns
    -------
    products : array, shape (n_coils, n_coils)
        The integration products.
    c                    s&   g | ]}|d  ˆ t jdd…f  ‘qS rh   ri   rj   rl   r
   r   rn   ¹  s     z$_do_surface_dots.<locals>.<listcomp>c                 S   s$   g | ]}t  t j|| d d�¡‘qS ro   rp   rr   r
   r
   r   rn   º  s     c                 S   s&   g | ]\}}||d d …t jf  ‘qS rs   ri   rt   r
   r
   r   rn   »  s     c                 S   s   g | ]}|d  ‘qS ru   r
   rj   r
   r
   r   rn   ¼  s     c                 S   s   g | ]}|d  ‘qS rv   r
   rj   r
   r
   r   rn   ½  s     Nrf   rg   Zrrr	   rX   Únnc                 3   s2   | ]*}ˆˆˆˆ	ˆ
ˆˆˆˆˆˆˆˆˆˆ |ƒV  qd S rs   r
   rx   )r9   rz   r{   Úlsurfr<   r=   r|   Úreflr}   r~   ÚrrefÚrsurfÚthis_nnr   r€   r
   r   r�   Ñ  s   ý      þz#_do_surface_dots.<locals>.<genexpr>r   )
r   r   rH   rq   r]   r   Ú_do_surface_dots_subsetrƒ   r2   r   )r{   r   r„   ZsurfÚselrm   r9   r<   r=   r…   r†   r‡   rˆ   r
   )r9   rz   r{   r�   r<   r=   r|   rm   r�   r}   r~   r‘   r’   r“   r   r€   r   Ú_do_surface_dots—  s&    "(ýr–   c                 C   s2   t | ||||||d|	|
|||ƒj}|dk	r.t‚|S )aË  Parallelize.

    Parameters
    ----------
    refl : array | None
        If ch_type is 'eeg', the magnitude of position vector of the
        virtual reference (never used).
    lsurf : array
        Magnitude of position vector of the surface points.
    rlens : list of arrays of length n_coils
        Magnitude of position vector.
    this_nn : array, shape (n_vertices, 3)
        Surface normals.
    cosmags : list of array.
        Direction of the integration points in the coils.
    ws : list of array
        Integration weights of the coils.
    volume : bool
        If True, compute volume integral.
    lut : callable
        Look-up table for evaluating Legendre polynomials.
    n_fact : array
        Coefficients in the integration sum.
    ch_type : str
        'meg' or 'eeg'
    idx : array, shape (n_coils x 1)
        Index of coil.

    Returns
    -------
    products : array, shape (n_coils, n_coils)
        The integration products.
    N)re   r7   ÚNotImplementedError)r{   r’   r~   r‘   r�   r�   r}   r“   rz   r€   r   r<   r=   r9   ry   rˆ   r
   r
   r   r”   Ù  s$    $           þr”   )r   )r   )Fr   r   FN)r)   Úos.pathÚpathr&   Únumpyr   Znumpy.polynomialr   r†   r   Úutilsr   r   r   r   r   r   r   r>   rS   rV   ÚpirZ   r[   re   r‰   r‚   r�   r–   r”   r
   r
   r
   r   Ú<module>
   s4   

      ÿ83
k
+:
A