nbara / python-meegkit

🔧🧠 MEEGkit: MEG & EEG processing toolkit in Python
https://nbara.github.io/python-meegkit/
BSD 3-Clause "New" or "Revised" License
181 stars 49 forks source link

'float' object has no attribute 'ppf' when executing `normfit()` #38

Closed jinglescode closed 3 years ago

jinglescode commented 3 years ago

Hi @gferraro2019, I tried running example_trca.py, and encounter this error:

Block 0: accuracy = 97.5,   ITR = 301.3
Block 1: accuracy = 100.0,  ITR = 319.3
Block 2: accuracy = 95.0,   ITR = 286.3
Block 3: accuracy = 95.0,   ITR = 286.3
Block 4: accuracy = 95.0,   ITR = 286.3
Block 5: accuracy = 100.0,  ITR = 319.3
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-9-7ca177a962e5> in <module>
    124 
    125 # Mean accuracy and ITR computation
--> 126 mu, _, muci, _ = normfit(accs, alpha_ci)
    127 print()
    128 print(f"Mean accuracy = {mu:.1f}%\t({ci:.0f}% CI: {muci[0]:.1f}-{muci[1]:.1f}%)")  # noqa

<ipython-input-4-769a1af8404d> in normfit(data, ci)
     43     num = len(arr)
     44     avg, std_err = np.mean(arr), scipy.stats.sem(arr)
---> 45     h_int = std_err * t.ppf((1 + ci) / 2., num - 1)
     46     var = np.var(data, ddof=1)
     47     var_ci_upper = var * (num - 1) / (chi2.ppf((1 - ci) / 2, num - 1))

AttributeError: 'float' object has no attribute 'ppf'
nbara commented 3 years ago

Hello, you must have overriden the valuesof t in your workspace.

Try replacing the utils.trca.py file with this:

"""TRCA utils."""
import numpy as np

from scipy.signal import filtfilt, cheb1ord, cheby1
from scipy import stats

def round_half_up(num, decimals=0):
    """Round half up round the last decimal of the number.

    The rules are:
    from 0 to 4 rounds down
    from 5 to 9 rounds up

    Parameters
    ----------
    num : float
        Number to round
    decimals : number of decimals

    Returns
    -------
    num rounded
    """
    multiplier = 10 ** decimals
    return int(np.floor(num * multiplier + 0.5) / multiplier)

def normfit(data, ci=0.95):
    """Compute the mean, std and confidence interval for them.

    Parameters
    ----------
    data : array, shape=()
        Input data.
    ci : float
        Confidence interval (default=0.95).

    Returns
    -------
    m : mean
    sigma : std deviation
    [m - h, m + h] : confidence interval of the mean
    [sigmaCI_lower, sigmaCI_upper] : confidence interval of the std
    """
    arr = 1.0 * np.array(data)
    num = len(arr)
    avg, std_err = np.mean(arr), stats.sem(arr)
    h_int = std_err * stats.t.ppf((1 + ci) / 2., num - 1)
    var = np.var(data, ddof=1)
    var_ci_upper = var * (num - 1) / stats.chi2.ppf((1 - ci) / 2, num - 1)
    var_ci_lower = var * (num - 1) / stats.chi2.ppf(1 - (1 - ci) / 2, num - 1)
    sigma = np.sqrt(var)
    sigma_ci_lower = np.sqrt(var_ci_lower)
    sigma_ci_upper = np.sqrt(var_ci_upper)

    return avg, sigma, [avg - h_int, avg +
                        h_int], [sigma_ci_lower, sigma_ci_upper]

def itr(n, p, t):
    """Compute information transfer rate (ITR).

    Definition in [1]_.

    Parameters
    ----------
    n : int
        Number of targets.
    p : float
        Target identification accuracy (0 <= p <= 1).
    t : float
        Average time for a selection (s).

    Returns
    -------
    itr : float
        Information transfer rate [bits/min]

    References
    ----------
    .. [1] M. Cheng, X. Gao, S. Gao, and D. Xu,
        "Design and Implementation of a Brain-Computer Interface With High
        Transfer Rates", IEEE Trans. Biomed. Eng. 49, 1181-1186, 2002.

    """
    itr = 0

    if (p < 0 or 1 < p):
        raise ValueError('Accuracy need to be between 0 and 1.')
    elif (p < 1 / n):
        raise ValueError('ITR might be incorrect because accuracy < chance')
        itr = 0
    elif (p == 1):
        itr = np.log2(n) * 60 / t
    else:
        itr = (np.log2(n) + p * np.log2(p) + (1 - p) *
               np.log2((1 - p) / (n - 1))) * 60 / t

    return itr

def bandpass(eeg, sfreq, Wp, Ws):
    """Filter bank design for decomposing EEG data into sub-band components.

    Parameters
    ----------
    eeg : np.array, shape=(n_samples, n_chans[, n_trials])
        Training data.
    sfreq : int
        Sampling frequency of the data.
    Wp : 2-tuple
        Passband for Chebyshev filter.
    Ws : 2-tuple
        Stopband for Chebyshev filter.

    Returns
    -------
    y: np.array, shape=(n_trials, n_chans, n_samples)
        Sub-band components decomposed by a filter bank.

    See Also
    --------
    scipy.signal.cheb1ord :
        Chebyshev type I filter order selection.

    """
    # Chebyshev type I filter order selection.
    N, Wn = cheb1ord(Wp, Ws, 3, 40, fs=sfreq)

    # Chebyshev type I filter design
    B, A = cheby1(N, 0.5, Wn, btype="bandpass", fs=sfreq)

    # the arguments 'axis=0, padtype='odd', padlen=3*(max(len(B),len(A))-1)'
    # correspond to Matlab filtfilt : https://dsp.stackexchange.com/a/47945
    y = filtfilt(B, A, eeg, axis=0, padtype='odd',
                 padlen=3 * (max(len(B), len(A)) - 1))
    return y
nbara commented 3 years ago

The code runs fine on my machine as well as the CIs so it must be an issue with your setup.

I have however pushed a hotfix that will solve your issue c64a00d91af316aa33333103a6f620a634307f6a