Esempio n. 1
0
def coherence(X, window=128, overlap=0.75, fmin=None, fmax=None, fs=None):
    """Compute coherence."""
    n_chan = X.shape[0]
    overlap = int(overlap * window)
    ij = []
    if fs is None:
        fs = window
    for i in range(n_chan):
        for j in range(i + 1, n_chan):
            ij.append((i, j))
    Cxy, Phase, freqs = mlab.cohere_pairs(X.T,
                                          ij,
                                          NFFT=window,
                                          Fs=fs,
                                          noverlap=overlap)

    if fmin is None:
        fmin = freqs[0]
    if fmax is None:
        fmax = freqs[-1]

    index_f = (freqs >= fmin) & (freqs <= fmax)
    freqs = freqs[index_f]

    # reshape coherence
    coh = numpy.zeros((n_chan, n_chan, len(freqs)))
    for i in range(n_chan):
        coh[i, i] = 1
        for j in range(i + 1, n_chan):
            coh[i, j] = coh[j, i] = Cxy[(i, j)][index_f]
    return coh
Esempio n. 2
0
def coherence(X, nfft=256, fs=2, noverlap=0):
    """Compute coherence."""
    n_chan = X.shape[0]
    ij = []
    for i in range(n_chan):
        for j in range(i + 1, n_chan):
            ij.append((i, j))
    Cxy, Phase, freqs = mlab.cohere_pairs(X, ij, NFFT=nfft, Fs=fs, noverlap=noverlap)
    coh = numpy.zeros((n_chan, n_chan, len(freqs)))
    for i in range(n_chan):
        coh[i, i] = 1
        for j in range(i + 1, n_chan):
            coh[i, j] = coh[j, i] = Cxy[(i, j)]
    return coh
Esempio n. 3
0
def coherence(X, nfft=256, fs=2, noverlap=0):
    """Compute coherence."""
    n_chan = X.shape[0]
    ij = []
    for i in range(n_chan):
        for j in range(i + 1, n_chan):
            ij.append((i, j))
    Cxy, Phase, freqs = mlab.cohere_pairs(X,
                                          ij,
                                          NFFT=nfft,
                                          Fs=fs,
                                          noverlap=noverlap)
    coh = numpy.zeros((n_chan, n_chan, len(freqs)))
    for i in range(n_chan):
        coh[i, i] = 1
        for j in range(i + 1, n_chan):
            coh[i, j] = coh[j, i] = Cxy[(i, j)]
    return coh
Esempio n. 4
0
def calculate_coherence(signalArray,
                        sampFq,
                        tFrame=10,
                        tSlide='None',
                        tAxis='default',
                        fqBands='default',
                        PhaseRan=True,
                        nRand=1):
    """
    Calculates signal coherence between all electrode pairs, over defined frequency bands
        - signalArray: np.array, ecog signals array (n electrodes x t timepoints)
        - sampFq: float, sampling frequency
        - tFrame: int, time bin in seconds for calculating coherence
        - tSlide: int or 'None', sliding window for moving coherence time bin
        - tAxis: np.array or 'default', time axis corresponding to signalArray time points
        - fqBands: dict eg fqBands['alpha'] = (8, 13) or 'default' to use pre-defined bands (in electrodeinfo.fqBands)
        - PhaseRan: bool. Perform phase randomization if True
        - nRand: number of phase randomizations to perform
    """

    nElectrodes = len(signalArray)

    if tSlide == 'None':
        tSlide = tFrame

    # Split up recording into time chuncks over which to calculate coherence
    tFrame = float(tFrame)
    tSlide = float(tSlide)

    # Select [:-1] in tAxis_split so that final time point has width >tFrame rather than <tFrame (cannot compute coherence if have too few time points)
    if tAxis == 'default':
        tDuration = np.floor(len(signalArray[0]) / float(sampFq))
        tAxis = np.linspace(0, tDuration, len(signalArray[0]))
        tMax = tDuration - tFrame + tSlide
        tAxis_split = np.arange(0, tMax, tSlide)[:-1]
        tAxis_split_inds = tAxis_split[:-1]
    else:
        tDuration = np.floor(tAxis[-1] - tAxis[0])
        tMax = tDuration - tFrame + tSlide
        tAxis_split = np.arange(tAxis[0], (tAxis[-1] - tFrame + tSlide),
                                tSlide)[:-1]
        tAxis_split_inds = np.arange(0, tMax, tSlide)[:-1]
    nTimepoints = len(tAxis_split)

    print('Recording duration: %0.0f sec (%0.2f mins)' % (tDuration,
                                                          (tDuration / 60.0)))
    print('Frame duration: %0.0f sec (%0.2f mins)' % (tFrame, (tFrame / 60.0)))
    print('Sliding window: %0.0f sec (%0.2f mins)' % (tSlide, (tSlide / 60.0)))
    print('Number of frames: %d\n' % (nTimepoints))

    # Define frequency bands
    if fqBands == 'default':
        fqBands = electrodeinfo.fq_bands()

    bands = fqBands.keys()

    # Initialize output matrices:
    Coherence = collections.OrderedDict()
    Phase = collections.OrderedDict()

    for band in bands:
        Coherence[band] = np.zeros((nElectrodes, nElectrodes, nTimepoints))

    for band in bands:
        Phase[band] = np.zeros((nElectrodes, nElectrodes, nTimepoints))

    # Define pairs over which to calculate coherences (list of tuples)
    ijPairs = []

    for i in range(nElectrodes):
        for j in range(i + 1, nElectrodes):
            ijPairs.append((i, j))

    # Calculate coherence for those pairs
    # Loop through time index array:
    for nn, tt in enumerate(tAxis_split_inds[:-1]):

        if nn == 0:
            print('Loop ' + str(nn + 1) + ' out of ' + str(nTimepoints))
        elif nn % 250 == 0 and nn >= 250:
            print('Loop ' + str(nn + 1) + ' out of ' + str(nTimepoints))
        elif nn == (nTimepoints - 1):
            print('Loop ' + str(nn + 1) + ' out of ' + str(nTimepoints))

        tStart = tt + tAxis[0]
        tEnd = tAxis_split_inds[nn + 1] + tAxis[0]
        ttInds = np.where((tAxis >= tStart) & (tAxis < tEnd))[0]

        # Only perform coherence calculation if have > 1 second of data
        if len(ttInds) > int(sampFq):
            if (ttInds[-1] + 1) <= len(tAxis):
                signalChunk = signalArray[0:nElectrodes,
                                          ttInds[0]:(ttInds[-1] + 1)]
            else:
                signalChunk = signalArray[0:nElectrodes, ttInds[0]:]

            signalChunk = np.float32(signalChunk)

            Cxy, phase, fqs = mlab.cohere_pairs(signalChunk.T,
                                                ijPairs,
                                                Fs=sampFq,
                                                NFFT=int(sampFq / 2))

            # Create numpy array of keys and values:
            ijCxyKeys = np.array(Cxy.keys())

            if PhaseRan == True:
                Coherence_surr = collections.OrderedDict(
                )  # Create the empty dictionary
                for X in bands:
                    Coherence_surr[X] = np.zeros(
                        (nElectrodes, nElectrodes, nTimepoints))

                # Perform randomization several times (added: 25 July 2017)
                Cxy_surr_all = np.zeros(
                    (np.array(Cxy.values()).shape[0],
                     np.array(Cxy.values()).shape[1], nRand))

                for nr in range(nRand):
                    signalChunk_surr = phaseran(signalChunk.T)
                    Cxy_surr, P0, F = mlab.cohere_pairs(signalChunk_surr.T,
                                                        ijPairs,
                                                        Fs=sampFq,
                                                        NFFT=int(sampFq / 2))
                    Cxy_surr_all[:, :, nr] = np.array(Cxy_surr.values())

                Cxy_surr_mean = np.mean(Cxy_surr_all, axis=-1)
                ijCxyValues = np.array(np.squeeze(
                    Cxy.values())) - Cxy_surr_mean

            else:
                ijCxyValues = np.array(np.squeeze(Cxy.values()))

            ijphaseKeys = np.array(phase.keys())
            ijphaseValues = np.array(np.squeeze(phase.values()))

            # Extract frequency indices and calculate mean coherence over those bands:

            Indices = collections.OrderedDict()
            for X in bands:
                Indices[X] = list(
                    np.where((fqs >= fqBands[X][0])
                             & (fqs <= fqBands[X][1]))[0])

            if len(np.shape(np.squeeze(ijCxyValues))) == 2:

                MeansCoh = {}
                MeansPhase = {}
                for X in bands:
                    MeansCoh[X] = np.mean(np.squeeze(ijCxyValues)[:,
                                                                  Indices[X]],
                                          axis=1)
                    MeansPhase[X] = np.mean(
                        np.squeeze(ijphaseValues)[:, Indices[X]], axis=1)

            elif len(np.shape(np.squeeze(ijCxyValues))) == 3:

                MeansCoh = {}
                MeansPhase = {}
                for X in bands:
                    MeansCoh[X] = np.mean(ijCxyValues[:, Indices[X]], axis=2)
                    MeansPhase[X] = np.mean(ijphaseValues[:, Indices[X]],
                                            axis=2)

            # Fill coherence matrices:
            diagIndices = range(nElectrodes)
            for X in bands:
                # Set diagonals = 1
                Coherence[X][diagIndices, diagIndices, nn] = 1

                for pp, pair in enumerate(ijCxyKeys):
                    Coherence[X][pair[0], pair[1], nn] = MeansCoh[X][pp]
                    Coherence[X][pair[1], pair[0], nn] = MeansCoh[X][pp]

            # Fill phase matrices:
            diagIndices = range(nElectrodes)
            for X in bands:
                # Set diagonals = 1
                Phase[X][diagIndices, diagIndices, nn] = 1

                for pp, pair in enumerate(ijphaseKeys):
                    Phase[X][pair[0], pair[1], nn] = MeansPhase[X][pp]
                    Phase[X][pair[1], pair[0], nn] = MeansPhase[X][pp]

        # If no data for that timepoint:
        elif len(ttInds) == 0:

            # Fill coherence matrices:
            diagIndices = range(nElectrodes)
            for X in bands:
                # Set diagonals = 1
                Coherence[X][diagIndices, diagIndices, nn] = np.nan

                for pp, pair in enumerate(ijCxyKeys):
                    Coherence[X][pair[0], pair[1], nn] = np.nan
                    Coherence[X][pair[1], pair[0], nn] = np.nan

            # Fill phase matrices:
            diagIndices = range(nElectrodes)
            for X in bands:
                # Set diagonals = 1
                Phase[X][diagIndices, diagIndices, nn] = np.nan

                for pp, pair in enumerate(ijphaseKeys):
                    Phase[X][pair[0], pair[1], nn] = np.nan
                    Phase[X][pair[1], pair[0], nn] = np.nan

    # Remove Nans and infs:

    for X in bands:
        Coherence[X] = np.nan_to_num(Coherence[X])
        Phase[X] = np.nan_to_num(Phase[X])

    print('Done\n')

    return {
        'Coherence': Coherence,
        'Phase': Phase,
        'deltaT': tFrame,
        'tAxis': tAxis_split
    }