Source code for metabci.brainda.algorithms.feature_analysis.time_analysis

import numpy as np
import mne
import matplotlib.pyplot as plt


[docs]class TimeAnalysis: Chan_Neuroscan = [ "FP1", "FPZ", "FP2", "AF3", "AF4", "F7", "F5", "F3", "F1", "FZ", "F2", "F4", "F6", "F8", "FT7", "FC5", "FC3", "FC1", "FCZ", "FC2", "FC4", "FC6", "FT8", "T7", "C5", "C3", "C1", "CZ", "C2", "C4", "C6", "T8", "M1", "TP7", "CP5", "CP3", "CP1", "CPZ", "CP2", "CP4", "CP6", "TP8", "M2", "P7", "P5", "P3", "P1", "PZ", "P2", "P4", "P6", "P8", "PO7", "PO5", "PO3", "POZ", "PO4", "PO6", "PO8", "CB1", "O1", "OZ", "O2", "CB2", ] Chan_Standard1020 = [ "Fp1", "Fpz", "Fp2", "AF3", "AF4", "F7", "F5", "F3", "F1", "Fz", "F2", "F4", "F6", "F8", "FT7", "FC5", "FC3", "FC1", "FCz", "FC2", "FC4", "FC6", "FT8", "T7", "C5", "C3", "C1", "Cz", "C2", "C4", "C6", "T8", "M1", "TP7", "CP5", "CP3", "CP1", "CPz", "CP2", "CP4", "CP6", "TP8", "M2", "P7", "P5", "P3", "P1", "Pz", "P2", "P4", "P6", "P8", "PO7", "PO5", "PO3", "POz", "PO4", "PO6", "PO8", "I1", "O1", "Oz", "O2", "I2", ] def __init__(self, data, meta, dataset, event, latency=0.0, channel=[0]): """ -author: Wujieyu -Created on: 2022-8-8 -updata log: 2022-8-15 by Wu Jieyu Args: data(ndarray):the EEG data meta(dataframe): information of the selected data dataset(dataset): BaseDataset event(string): event trigger latency(float): start moment of the epoch, by default 0 channel(list): selected channels, by default [0] """ sub_meta = meta[meta["event"] == event] event_id = sub_meta.index.to_numpy() self.data_length = np.round(data.shape[2] / dataset.srate) if isinstance(channel[0], str): self.chan_ID = self.get_chan_id(channel, dataset.channels) elif isinstance(channel[0], int): self.chan_ID = channel self.data = data[event_id, :, :] self.latency = latency self.fs = dataset.srate self.All_channel = dataset.channels self.event = event
[docs] def stacking_average(self, data=[], _axis=[0]): # data:trials*channels*time """ -author: Jiang Hanzhe -Created on: 2022-8-8 -updata log: 2022-8-15 by Jiang Hanzhe Args: data(ndarray): the EEG data, by default [] _axis(list): selected the dimensions, by default [0] Returns: data_mean(ndarray): array of averaged signals """ if isinstance(_axis, int): _axis = [_axis] axis = tuple(_axis) if data == []: data = self.data data_mean = data.mean(axis=axis) return data_mean
[docs] def peak_amplitude(self, data=[], time_start=0, time_end=1): """ -author: Jiang Hanzhe -Created on: 2022-8-8 -updata log: 2022-8-15 by Jiang Hanzhe Args: data(ndarray): the EEG data, by default [] time_start(int): beginning of peak seeking, by default 0 time_end(int): end of peak seeking, by default 1 Returns: peak_amp(float): signal peak amplitude within the specified time quantum """ if data == []: data1 = self.stacking_average() data = np.squeeze(data1[self.chan_ID, :]) peak_amp = np.max(data[time_start:time_end]) return peak_amp
[docs] def average_amplitude(self, data=[], time_start=0, time_end=1): """ -author: Jiang Hanzhe -Created on: 2022-8-8 -updata log: 2022-8-15 by Jiang Hanzhe Args: data(ndarray): the EEG data, by default [] time_start(int): beginning of peak seeking, by default 0 time_end(int): end of peak seeking, by default 1 Returns: ave_amp(float): signal average amplitude within the specified time quantum """ if data == []: data1 = self.stacking_average() data = np.squeeze(data1[self.chan_ID, :]) ave_amp = np.mean(data[time_start:time_end]) return ave_amp
[docs] def peak_latency(self, data=[], time_start=0, time_end=1): """ -author: Wu Jieyu -Created on: 2022-8-8 -updata log: 2022-8-15 by Wu Jieyu Args: data(ndarray): the EEG data, by default [] time_start(int): beginning of peak seeking, by default 0 time_end(int): end of peak seeking, by default 1 Returns: peak_loc(int): location of peak amplitude peak_amp(float): signal peak amplitude within the specified time quantum """ if data == []: data1 = self.stacking_average() data = np.squeeze(data1[self.chan_ID, :]) peak_amp = self.peak_amplitude(data, time_start, time_end) peak_loc = np.argmax(data[time_start:time_end]) + time_start return peak_loc, peak_amp
[docs] def average_latency(self, data=[], time_start=0, time_end=1): """ -author: Wu Jieyu -Created on: 2022-8-8 -updata log: 2022-8-15 by Wu Jieyu Args: data(ndarray): the EEG data, by default [] time_start(int): beginning of peak seeking, by default 0 time_end(int): end of peak seeking, by default 1 Returns: ave_loc(int): location of average amplitude ave_amp(float): signal average amplitude within the specified time quantum """ if data == []: data1 = self.stacking_average() data = np.squeeze(data1[self.chan_ID, :]) ave_amp = self.average_amplitude(data, time_start, time_end) sample = time_end - time_start - 1 half_average = np.sum(data) / 2 integal = [] for samp_i in range(sample): integal.append(np.abs(np.sum(data[0:samp_i]) - half_average)) ave_loc = np.argmin(integal) + time_start return ave_loc, ave_amp
[docs] def plot_single_trial( self, data, sample_num, axes=None, amp_mark=False, time_start=0, time_end=1 ): """ -author: Wu Jieyu -Created on: 2022-8-8 -updata log: 2022-8-15 by Wu Jieyu Args: data(ndarray): the EEG data sample_num(int): total number of sampling points in data axes(axessubplot): drawing area amp_mark(string): 'peak' or 'average', call different peak marking methods, by default False (not marked) time_start(int): beginning of peak seeking, by default 0 time_end(int): end of peak seeking, by default 1 Returns: loc(int): location of amplitude amp(float): signal amplitude within the specified time quantum ax(axessubplot): drawing area """ latency = self.latency data_mean = data import matplotlib.pyplot as plt fs = self.fs ax = axes if axes else plt.gca() t = np.arange(latency, sample_num / fs + latency, 1 / fs) plt.plot(t, data_mean) if amp_mark: func_str = "self." + amp_mark + "_latency" loc, amp = eval(func_str)(data_mean, time_start, time_end) plt.scatter(t[loc], amp, c="r", marker="o", label="振幅") pass plt.rcParams["font.sans-serif"] = ["Microsoft YaHei"] plt.xlabel("time[s]") plt.ylabel("amplitude[μV]") plt.legend() return loc, amp, ax
[docs] def get_chan_id(self, ch_name, channels): """ -author: Wu Jieyu -Created on: 2022-8-8 -updata log: 2022-8-15 by Wu Jieyu Args: ch_name(list): selected channels channels(list): standard channel list Returns: Chan_ID(list): index of ch_name in channels """ Start = 0 End = 64 Chan_ID = [] for i in range(len(ch_name)): Chan_ID.append(channels.index(ch_name[i].upper(), Start, End)) pass return Chan_ID
[docs] def plot_multi_trials(self, data, sample_num, axes=None): """ -author: Wu Jieyu -Created on: 2022-8-8 -updata log: 2022-8-15 by Wu Jieyu Args: data(ndarray): the EEG data sample_num(int): total number of sampling points in data axes(axessubplot): drawing area Returns: ax(axessubplot): drawing area """ data_shape = data.shape # data_sample = data_shape[1] trial_num = data_shape[0] fs = self.fs latency = self.latency t = np.arange(latency, sample_num / fs + latency, 1 / fs) ax = axes if axes else plt.gca() for trial_i in range(trial_num): plt.plot(t, data[trial_i, :], color=[0.7, 0.7, 0.7], linewidth=0.8) data_mean = np.mean(data, 0) plt.plot(t, data_mean, color=[1, 0, 0], linewidth=1.5, label="时域") plt.rcParams["font.sans-serif"] = ["Microsoft YaHei"] plt.legend() plt.xlabel("time[s]") plt.ylabel("amplitude[μV]") plt.legend(loc="lower right") return ax
[docs] def plot_topomap( self, data, point, channels, fig, srate=-1, ch_types="eeg", axes=None ): """ -author: Wu Jieyu -Created on: 2022-8-8 -updata log: 2022-8-15 by Wu Jieyu Args: data(ndarray): the EEG data point(int): selected sampling point channels(list): selected channels fig(figure): figure srate(int): sampling rate, by dafault self.fs ch_types(list of str | str): channel types, by default 'eeg' axes(axessubplot): drawing area, by default none Returns: aximage(axessubplot): drawing area """ ch_names = [] if srate == -1: srate = self.fs if isinstance(channels[0], str): Chan_ID = self.get_chan_id(channels, self.Chan_Neuroscan) elif isinstance(channels[0], int): Chan_ID = channels for i in Chan_ID: ch_names.append(self.Chan_Standard1020[i]) info = mne.create_info(ch_names=ch_names, sfreq=srate, ch_types=ch_types) evoked = mne.EvokedArray(data, info) evoked.set_montage("standard_1005") # ax = axes if axes else plt.gca() left = 0.92 b = 0.2 w = 0.015 h = 0.6 aximage, countour = mne.viz.plot_topomap( evoked.data[:, point], evoked.info, show=False, cmap="jet", vmin=data[:, point].min(), vmax=data[:, point].max(), contours=6, ) rect = [left, b, w, h] cbar_ax = fig.add_axes(rect) plt.colorbar(aximage, cax=cbar_ax) return aximage