U
    f»{jýI  ã                   @   s°   d dl Z d dlZddlmZmZmZ ddlmZ ddl	m
Z
 ddlmZmZmZ eG dd	„ d	eƒƒZddd„Zdd„ Zdd„ Zdd„ Zdd„ Zddd„Zddd„ZeedœZdS )é    Né   )Úget_coefÚBaseEstimatorÚ_check_estimator)ÚTimeDelayingRidgeé   )Úis_regressor)Ú_validate_typeÚverboseÚfill_docc                	   @   sR   e Zd ZdZeddd„ƒZdd	„ Zdd
d„Zdd„ Zdd„ Z	dd„ Z
ddd„ZdS )ÚReceptiveFieldaR  Fit a receptive field model.

    This allows you to fit an encoding model (stimulus to brain) or a decoding
    model (brain to stimulus) using time-lagged input features (for example, a
    spectro- or spatio-temporal receptive field, or STRF)
    :footcite:`TheunissenEtAl2001,WillmoreSmyth2003,CrosseEtAl2016,HoldgrafEtAl2016`.

    Parameters
    ----------
    tmin : float
        The starting lag, in seconds (or samples if ``sfreq`` == 1).
    tmax : float
        The ending lag, in seconds (or samples if ``sfreq`` == 1).
        Must be >= tmin.
    sfreq : float
        The sampling frequency used to convert times into samples.
    feature_names : array, shape (n_features,) | None
        Names for input features to the model. If None, feature names will
        be auto-generated from the shape of input data after running `fit`.
    estimator : instance of sklearn.base.BaseEstimator | float | None
        The model used in fitting inputs and outputs. This can be any
        scikit-learn-style model that contains a fit and predict method. If a
        float is passed, it will be interpreted as the ``alpha`` parameter
        to be passed to a Ridge regression model. If `None`, then a Ridge
        regression model with an alpha of 0 will be used.
    fit_intercept : bool | None
        If True (default), the sample mean is removed before fitting.
        If ``estimator`` is a :class:`sklearn.base.BaseEstimator`,
        this must be None or match ``estimator.fit_intercept``.
    scoring : ['r2', 'corrcoef']
        Defines how predictions will be scored. Currently must be one of
        'r2' (coefficient of determination) or 'corrcoef' (the correlation
        coefficient).
    patterns : bool
        If True, inverse coefficients will be computed upon fitting using the
        covariance matrix of the inputs, and the cross-covariance of the
        inputs/outputs, according to :footcite:`HaufeEtAl2014`. Defaults to
        False.
    n_jobs : int | str
        Number of jobs to run in parallel. Can be 'cuda' if CuPy
        is installed properly and ``estimator is None``.

        .. versionadded:: 0.18
    edge_correction : bool
        If True (default), correct the autocorrelation coefficients for
        non-zero delays for the fact that fewer samples are available.
        Disabling this speeds up performance at the cost of accuracy
        depending on the relationship between epoch length and model
        duration. Only used if ``estimator`` is float or None.

        .. versionadded:: 0.18
    %(verbose)s

    Attributes
    ----------
    coef_ : array, shape ([n_outputs, ]n_features, n_delays)
        The coefficients from the model fit, reshaped for easy visualization.
        During :meth:`mne.decoding.ReceptiveField.fit`, if ``y`` has one
        dimension (time), the ``n_outputs`` dimension here is omitted.
    patterns_ : array, shape ([n_outputs, ]n_features, n_delays)
        If fit, the inverted coefficients from the model.
    delays_ : array, shape (n_delays,), dtype int
        The delays used to fit the model, in indices. To return the delays
        in seconds, use ``self.delays_ / self.sfreq``
    valid_samples_ : slice
        The rows to keep during model fitting after removing rows with
        missing values due to time delaying. This can be used to get an
        output equivalent to using :func:`numpy.convolve` or
        :func:`numpy.correlate` with ``mode='valid'``.

    See Also
    --------
    mne.decoding.TimeDelayingRidge

    Notes
    -----
    For a causal system, the encoding model will have significant
    non-zero values only at positive lags. In other words, lags point
    backward in time relative to the input, so positive lags correspond
    to previous input time samples, while negative lags correspond to
    future input time samples.

    References
    ----------
    .. footbibliography::
    NÚr2FTc                 C   sP   || _ t|ƒ| _|| _|| _|d kr(dn|| _|| _|| _|| _|	| _	|
| _
d S )Ng        )Úfeature_namesÚfloatÚsfreqÚtminÚtmaxÚ	estimatorÚfit_interceptÚscoringÚpatternsÚn_jobsÚedge_correction)Úselfr   r   r   r   r   r   r   r   r   r   r
   © r   ú[/var/www/html/bwave/python/venv/lib/python3.8/site-packages/mne/decoding/receptive_field.pyÚ__init__j   s    
zReceptiveField.__init__c                 C   sº   d| j | jf }| j}t|tƒs*t| jƒ}|d|f 7 }t| dƒr’| jd k	rˆ| j}t|ƒdkrp|d|d  7 }n|d|d |d f 7 }|d	7 }n|d
7 }t| dƒr²|d| j	 7 }d| S )Nztmin, tmax : (%.3f, %.3f), zestimator : %s, Úcoef_r   zfeature: %s, r   zfeatures : [%s, ..., %s], éÿÿÿÿz	fit: Truez
fit: FalseZscores_zscored (%s)z<ReceptiveField | %s>)
r   r   r   Ú
isinstanceÚstrÚtypeÚhasattrr   Úlenr   )r   Úsr   Zfeatsr   r   r   Ú__repr__y   s     





zReceptiveField.__repr__c                 C   sT   t | jtƒsLt|| j| j| j| jd�}t|ƒ}|dk	rL|j	d|j
d dd�}||fS )z Delay and reshape the variables.)Ú	fill_meanNr   ÚF©Úorder)r   Ú
estimator_r   Ú_delay_time_seriesr   r   r   r   Ú_reshape_for_estÚreshapeÚshape)r   ÚXÚyr   r   r   Ú_delay_and_reshape�   s    ÿz!ReceptiveField._delay_and_reshapec              	   C   sè  ddl m} | jt ¡ kr4tdtt ¡ ƒ| jf ƒ‚ddlm} |  	||¡\}}}| _
| j| jkrvtd| j| jf ƒ‚t| j| j| jƒ| _t| jƒ| _t| jtjƒrÚ| jdkr´d| _t| j| j| j| j| j| j| jd�}n`t| jƒ�r(|| jƒ}| jdk	�r|j| jk�rtd	|j| jf ƒ‚|j| _ntd
t| jƒ ƒ‚|| _~t| jƒ |j\}}}	|jd }
t| jƒ}| j dk	�ržt| j ƒ|	k�ržtd|	t| j ƒf ƒ‚|  !||¡\}}| j "||¡ t#| jdƒ}|	|g}| j
dk�rè| $dd¡ | %|¡| _&| j'�rät| jtƒ�r:| jj(t)|| d ƒ }|j%d|jd dd�}n||j*ddd� }t+ ,|j-¡}~|j.dk�rœ|jd dk�rœ||j*ddd� }| /t+ ,|j-¡¡}ndt)|| d ƒ }~t+ %| j&|	| |
f¡}| 0| 0|¡¡}| %|¡| _1| S )a�  Fit a receptive field model.

        Parameters
        ----------
        X : array, shape (n_times[, n_epochs], n_features)
            The input features for the model.
        y : array, shape (n_times[, n_epochs][, n_outputs])
            The output features for the model.

        Returns
        -------
        self : instance
            The instance so you can chain operations.
        r   )Úlinalgz!scoring must be one of %s, got%s )Úclonez#tmin (%s) must be at most tmax (%s)NT)Úalphar   r   r   z˜Estimator fit_intercept (%s) != initialization fit_intercept (%s), initialize ReceptiveField with the same fit_intercept value or use fit_intercept=NonezK`estimator` must be a float or an instance of `BaseEstimator`, got type %s.r   z7n_features in X does not match feature names (%s != %s)r   r   r'   r(   )Zkeepdimsr   g      ð?)2Zscipyr2   r   Ú_SCORERSÚkeysÚ
ValueErrorÚsortedZsklearn.baser3   Ú_check_dimensionsÚ_y_dimr   r   Ú_times_to_delaysr   Údelays_Ú_delays_to_sliceÚvalid_samples_r   r   ÚnumbersÚRealr   r   r   r   r   r!   r*   r   r.   r#   r   r1   Úfitr   Úinsertr-   r   r   Úcov_r   ÚmeanÚnpZcovÚTÚndimZpinvÚdotZ	patterns_)r   r/   r0   r2   r3   Ú_r   Ún_timesÚn_epochsÚn_featsÚ	n_outputsÚn_delaysZcoefr.   rC   Zinv_Yr   r   r   r   rA   ™   s”    ÿ
ÿ
    ý

ÿ
ýÿ
þ


ÿÿzReceptiveField.fitc                 C   sÆ   t | dƒstdƒ‚| j|ddd�dd… \}}}~|jdd… }| jdkr\|| jjd	 f }|  |¡\}}| j |¡}|j	|d
d�}t
|jƒ}|dkr¦| d¡ d	}nd}|d| j| … }||_|S )aô  Generate predictions with a receptive field.

        Parameters
        ----------
        X : array, shape (n_times[, n_epochs], n_channels)
            The input features for the model.

        Returns
        -------
        y_pred : array, shape (n_times[, n_epochs][, n_outputs])
            The output predictions. "Note that valid samples (those
            unaffected by edge artifacts during the time delaying step) can
            be obtained using ``y_pred[rf.valid_samples_]``.
        r<   zEstimator has not been fit yet.NT©Úpredicté   r   r   r   r'   r(   r   )r"   r7   r9   r.   r:   r   r1   r*   rP   r-   ÚlistÚpop)r   r/   rI   ÚX_dimZ
pred_shapeÚy_predr.   Úextrar   r   r   rP      s$    



zReceptiveField.predictc           	      C   s–   t | j }| j||dd�dd… \}}|j\}}}|  |¡}|| j }|| j }|jd|gdd�}|jd|gdd�}|j|jks„t‚|||dd	�}|S )
a°  Score predictions generated with a receptive field.

        This calls ``self.predict``, then masks the output of this
        and ``y` with ``self.valid_samples_``. Finally, it passes
        this to a :mod:`sklearn.metrics` scorer.

        Parameters
        ----------
        X : array, shape (n_times[, n_epochs], n_channels)
            The input features for the model.
        y : array, shape (n_times[, n_epochs][, n_outputs])
            Used for scikit-learn compatibility.

        Returns
        -------
        scores : list of float, shape (n_outputs,)
            The scores estimated by the model for each output (e.g. mean
            R2 of ``predict(X)``).
        TrO   Nr   r   r'   r(   Ú
raw_values©Úmultioutput)r5   r   r9   r.   rP   r>   r-   ÚAssertionError)	r   r/   r0   Zscorer_rJ   rK   rM   rU   Zscoresr   r   r   Úscore$  s    



zReceptiveField.scorec                 C   sŽ  |j }|d k	r|j nd}|dkr”|d d …tjd d …f }|d k	rî|dkr`|d d …tjtjf }qî|dkr‚|d d …tjd d …f }qîtd|jf ƒ‚nZ|j dkrÞ|d k	rî|j dkrÊ|d d …d d …tjf }qî|j dkrîtdƒ‚ntd|jf ƒ‚|d k	�r‚|jd |jd k�r*td|jd |jd f ƒ‚|jd |jd k�r\td	|jd |jd f ƒ‚|�r‚|jd
 t| jjƒk�r‚tdƒ‚||||fS )Nr   r   r   z8y must be shape (n_times[, n_epochs][,n_outputs], got %srQ   z4If X has 3 dimensions, y must have 2 or 3 dimensionsz9X must be shape (n_times[, n_epochs], n_features), got %sz-X and y do not have the same n_times
%s != %sz.X and y do not have the same n_epochs
%s != %sr   zBNumber of outputs does not match estimator coefficients dimensions)rG   rE   Únewaxisr7   r.   r#   r*   r   )r   r/   r0   rP   rT   Zy_dimr   r   r   r9   I  sB    ÿ



ÿ
ÿÿz ReceptiveField._check_dimensions)NNNr   FNTN)N)F)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r
   r   r%   r1   rA   rP   r[   r9   r   r   r   r   r      s    W           þ
g$%r   Fc                 C   s  t |||ƒ t|||ƒ}t | jt|ƒf ¡}|rp| jdd�}| jdkrVtj|dd�}|dd…tjf |dd…< t	|ƒD ]œ\}}	|	dk rª|d|	…d|f }
| |	 d… }n:|	dkrÔ||	d…d|f }
| d|	 … }n|d|f }
| }||
dd…< |rx|
dd…  ||jdd� 7  < qx|S )a³  Return a time-lagged input time series.

    Parameters
    ----------
    X : array, shape (n_times[, n_epochs], n_features)
        The time series to delay. Must be 2D or 3D.
    tmin : int | float
        The starting lag.
    tmax : int | float
        The ending lag.
        Must be >= tmin.
    sfreq : int | float
        The sampling frequency of the series. Defaults to 1.0.
    fill_mean : bool
        If True, the fill value will be the mean along the time dimension
        of the feature, and each cropped and delayed segment of data
        will be shifted to have the same mean value (ensuring that mean
        subtraction works properly). If False, the fill value will be zero.

    Returns
    -------
    delayed : array, shape(n_times[, n_epochs][, n_features], n_delays)
        The delayed data. It has the same shape as X, with an extra dimension
        appended to the end.

    Examples
    --------
    >>> tmin, tmax = -0.1, 0.2
    >>> sfreq = 10.
    >>> x = np.arange(1, 6)
    >>> x_del = _delay_time_series(x, tmin, tmax, sfreq)
    >>> print(x_del)  # doctest:+SKIP
    [[2. 1. 0. 0.]
     [3. 2. 1. 0.]
     [4. 3. 2. 1.]
     [5. 4. 3. 2.]
     [0. 5. 4. 3.]]
    r   )ZaxisrQ   N.)
Ú_check_delayer_paramsr;   rE   Zzerosr.   r#   rD   rG   r\   Ú	enumerate)r/   r   r   r   r&   ÚdelaysZdelayedZ
mean_valueÚiiZix_delayÚoutZuse_Xr   r   r   r+   n  s*    '
"r+   c                 C   s0   t  tt  | | ¡ƒtt  || ¡d ƒ¡}|S )z)Convert a tmin/tmax in seconds to delays.r   )rE   ZarangeÚintÚround)r   r   r   rc   r   r   r   r;   ¯  s    ÿr;   c                 C   s:   | d dkrdn| d }| d dkr(dn| d }t ||ƒS )z=Find the slice to be taken in order to remove missing values.r   r   N)Úslice)rc   Z	min_delayZ	max_delayr   r   r   r=   ·  s    r=   c                 C   s:   t |ddƒ | |fD ]}t |ddƒ q| |ks6tdƒ‚dS )z@Check delayer input parameters. For future custom delay support.Únumericz`sfreq`z	tmin/tmaxztmin must be <= tmaxN)r	   r7   )r   r   r   Ztlimr   r   r   ra   À  s
    ra   c                 C   s4   | j \}}}}|  ||d¡} | j|| ddd�} | S )z,Convert X_del to a sklearn-compatible shape.r   r'   r(   )r.   r-   )ZX_delrJ   rK   rL   rN   r   r   r   r,   Ê  s    r,   c                    sf   ddl m‰  |dkst‚ˆˆfD ]}|jdkr td|jf ƒ‚q t ‡ ‡‡fdd„tˆjd ƒD ƒ¡S )	Nr   )ÚpearsonrrW   r   z/inputs must be shape (samples, outputs), got %sc                    s2   g | ]*}ˆ ˆd d …|f ˆd d …|f ƒd ‘qS )Nr   r   )Ú.0rd   ©rj   r0   Úy_truer   r   Ú
<listcomp>Ú  s   ÿz_corr_score.<locals>.<listcomp>r   )	Zscipy.statsrj   rZ   rG   r7   r.   rE   ÚarrayÚrange)rm   r0   rY   Zthis_yr   rl   r   Ú_corr_scoreÓ  s    
ÿÿrq   c                 C   s   ddl m} || ||d�S )Nr   )Úr2_scorerX   )Zsklearn.metricsrr   )rm   r0   rY   rr   r   r   r   Ú	_r2_scoreÞ  s    rs   )r   Zcorrcoef)F)N)N)r?   ÚnumpyrE   Úbaser   r   r   Ztime_delaying_ridger   Úfixesr   Úutilsr	   r
   r   r   r+   r;   r=   ra   r,   rq   rs   r5   r   r   r   r   Ú<module>   s"     ^
A	
	

