count_pred_true = 0 count_pred_false = 0 for i in range(0,myclass2.data_notlive.trials.shape[0]): fs = myclass2.data_notlive.sampling_freq label = myclass2.data_notlive.labels[i] trial = myclass2.data_notlive.trials[i] if i < (myclass2.data_notlive.trials.shape[0] - 1): next_trial = myclass2.data_notlive.trials[i+1] X = myclass2.data_notlive.raw_data[trial:next_trial] else: X = myclass2.data_notlive.raw_data[trial:] trial = 0 nst_eeg_live = NST_EEG_LIVE(base_dir, file_name2) nst_eeg_live.load_from_mat(label,trial,X,fs) current_classifier, pred_true, pred_valid = myclass.classify_live(nst_eeg_live) if not pred_valid: continue #print('Classification result: ',current_classifier[0],'\n') if pred_true: #print('This is true!\n') count_pred_true = count_pred_true + 1 else: count_pred_false += 1 #print('This is false!\n') print('Count of true predictions:', count_pred_true)
class RecordData_liveEEG_JB(): def __init__(self, Fs, age, gender="male", with_feedback=False, record_func=record_and_process, control_func=control): ### decide whether control thread should also be started ### currently not used self.docontrol = False ### indizes in X indicating the beginning of a new trial self.trial = [] ### list including all the recorded EEG data self.X = [] ### time stamp indicating the beginning of each trial self.trial_time_stamps = [] ### all time stamps, one is added for each data point self.time_stamps = [] ### label of each trial: 0: left, 1: right, 2: both self.Y = [] ### currently not used # 0 negative_feedback # 1 positive feedback self.feedbacks = [] ### sampling frequency self.Fs = Fs ### trial offset in motor imagery paradigm. Used in get_last_trial() self.trial_offset = 4 self.gender = gender self.age = age self.add_info = "with feedback" if with_feedback else "with no feedback" ### initialise a subfolder where the data is to be saved ### if it does not yet exist, create it self.datapath = os.path.join(os.getcwd(), '00_DATA') if not os.path.exists(self.datapath): os.makedirs(self.datapath) ### stop event used to pause and resume to the recording & processing thread self.stop_event_rec = threading.Event() self.stop_event_con = threading.Event() ### initialise recording thread. It does not run yet. Therefore use start_recording() recording_thread = threading.Thread( target=record_func, args=(self.stop_event_rec, self.X, self.time_stamps), ) recording_thread.daemon = True self.recording_thread = recording_thread ### initialise control thread. if self.docontrol: control_thread = threading.Thread( target=control_func, args=(self.stop_event_con, self.X), ) control_thread.daemon = True self.control_thread = control_thread ############################################################################### def __iter__(self): yield 'trial', self.trial yield 'age', self.age yield 'X', self.X yield 'time_stamps', self.time_stamps yield 'trial_time_stamps', self.trial_time_stamps yield 'Y', self.Y yield 'Fs', self.Fs yield 'gender', self.gender yield 'add_info', self.add_info yield 'feedbacks', self.feedbacks ############################################################################### def add_trial(self, label): ### called whenever a new trial is started self.trial_time_stamps.append(pylsl.local_clock()) self.Y.append(label) ### trial includes the index in X and force, where each trial has begun self.trial.append(len(self.X) - 1) ############################################################################### def add_feedback(self, feedback): self.feedbacks.append(feedback) ############################################################################### def start_recording(self, len_X=0, len_f=0): ### start the recording thread self.recording_thread.start() if self.docontrol: self.control_thread.start() time.sleep(2) ### check whether data arrived, if not raise error if len(self.X) - len_X == 0: raise NoRecordingDataError() ############################################################################### def pause_recording(self): ### raise stop_event to break the loop in record() while the classification of notlive data is done self.stop_event_rec.set() print('Recording has been paused.') ############################################################################### def restart_recording(self): ### newly initialise the recording thread and start it self.stop_event_rec.clear() recording_thread = threading.Thread( target=record, args=(self.stop_event_rec, self.X, self.time_stamps), ) recording_thread.daemon = True self.recording_thread = recording_thread self.start_recording(len_X=len(self.X)) print('Recording has been restarted.') ############################################################################### ### this function is not required anymore, because self.trial is updated in add_trial() ### kept for historical reasons def set_trial_start_indexes(self): ### since it can be called twice during one recording (because of live processing) ### everything done by the first step is deleted before the second step if len(self.trial) > 0: self.trial = [] ### the loop was once used to calculate the index in X that the time stamp of each trial begin relates to ### this is solved by updating self.trial already in add_trial() i = 0 for trial_time_stamp in self.trial_time_stamps: for j in range(i, len(self.time_stamps)): time_stamp = self.time_stamps[j] if trial_time_stamp <= time_stamp: self.trial.append(j - 1) i = j break ############################################################################### def stop_recording_and_dump(self, file_name="EEG_session_" + time_str() + ".mat"): ### finish the recording, save all data to a .mat file self.pause_recording() self.stop_event_con.set() sio.savemat(os.path.join(self.datapath, file_name), dict(self)) print('Recording will shut down.') return file_name, self.datapath ############################################################################### def stop_recording_and_dump_live(self, file_name="EEG_session_live_" + time_str() + ".mat"): ### still there for historic reasons, to support run_session by Mirjam Hemberger return self.continue_recording_and_dump() ############################################################################### def continue_recording_and_dump(self, file_name="EEG_session_live_" + time_str() + ".mat"): ### only save data while still keeping the recording thread alive ### the data can then be used to classify the notlive data sio.savemat(os.path.join(self.datapath, file_name), dict(self)) return file_name, self.datapath ############################################################################### def pause_recording_and_dump(self, file_name="EEG_session_live_" + time_str() + ".mat"): ### save data to .mat and pause the recording such that it can be resumed lateron sio.savemat(os.path.join(self.datapath, file_name), dict(self)) self.pause_recording() return file_name, self.datapath ############################################################################### def get_last_trial(self, filename_live=""): ### generate a NST_EEG_LIVE object and save data of last trial into it ### the dataset can then be used for live classification last_label = self.Y[-1:] ### subtract one trial offset, because add trial is allways called when the moto imagery starts and not in the beginning of each trial last_trial = self.trial[-1:][0] - self.Fs * self.trial_offset X = np.array(self.X[slice(last_trial, None, None)]) if False: ### usefull info for debugging print('last index is: ', last_trial[0]) print('last time is:', self.trial_time_stamps[-1:][0]) print('current time is: ', pylsl.local_clock()) print('current index is:', len(self.X)) ### hand over 0 as index to dataset object, because the new index in the slice of X that will be handed over is 0 last_trial = 0 ### generate an instance of the NST_EEG_LIVE class (inherits from Dataset class) self.nst_eeg_live = NST_EEG_LIVE(self.datapath, filename_live) ### hand over data to the NST_EEG_LIVE instance self.nst_eeg_live.load_from_mat(last_label, last_trial, X, self.Fs) return self.nst_eeg_live ############################################################################### def startAccumulate(self): self.accStart = len(self.X) print("starting accumulation") ############################################################################### def stopAccumulate(self): pass
class RecordData(): def __init__(self, Fs, age, gender="male", with_feedback=False, record_func=record): # timepoints when the subject starts imagination self.trial = [] self.X = [] self.trial_time_stamps = [] self.time_stamps = [] # 0 negative_feedback # 1 positive feedback self.feedbacks = [] # containts the lables of the trials: # 1: left # 2: right # 3: both hands self.Y = [] # sampling frequncy self.Fs = Fs self.trial_offset = 4 self.gender = gender self.age = age self.add_info = "with feedback" if with_feedback else "with no feedback" recording_thread = threading.Thread( target=record_func, args=(self.X, self.time_stamps), ) recording_thread.daemon = True self.recording_thread = recording_thread def __iter__(self): yield 'trial', self.trial yield 'age', self.age yield 'X', self.X yield 'time_stamps', self.time_stamps yield 'trial_time_stamps', self.trial_time_stamps yield 'Y', self.Y yield 'Fs', self.Fs yield 'gender', self.gender yield 'add_info', self.add_info yield 'feedbacks', self.feedbacks def add_trial(self, label): self.trial_time_stamps.append(pylsl.local_clock()) self.Y.append(label) self.trial.append(len(self.X) - 1) def add_feedback(self, feedback): self.feedbacks.append(feedback) def start_recording(self): self.recording_thread.start() time.sleep(2) if len(self.X) == 0: raise NoRecordingDataError() ### this function is not required anymore, because self.trial is updated in add_trial() ### kept for historical reasons def set_trial_start_indexes(self): if len(self.trial) > 0: self.trial = [] i = 0 for trial_time_stamp in self.trial_time_stamps: for j in range(i, len(self.time_stamps)): time_stamp = self.time_stamps[j] if trial_time_stamp <= time_stamp: self.trial.append(j - 1) i = j break def stop_recording_and_dump(self, file_name="session_" + time_str() + ".mat"): #self.set_trial_start_indexes() #solved by collecting index in add_trial() sio.savemat(file_name, dict(self)) return file_name ### used for live processing step 2: dump all data generated so far, another filename than stop_recording_and_dump def stop_recording_and_dump_live(self, file_name="session_live_" + time_str() + ".mat"): #self.set_trial_start_indexes() #solved by collecting index in add_trial() sio.savemat(file_name, dict(self)) return file_name def get_last_trial(self, filename_live): # generate a NST_EEG_LIVE object and save data of last trial into it last_label = self.Y[-1:] ### subtract one trial offset, because add trial is allways called when the moto imagery starts and not in the beginning of each trial last_trial = self.trial[-1:][0] - self.Fs * self.trial_offset X = np.array(self.X[slice(last_trial[0], None, None)]) #print(X.shape) last_trial = 0 #hand over 0 as index to dataset object, because the new index in the slice of X that will be handed over is 0 cwd = os.getcwd() self.nst_eeg_live = NST_EEG_LIVE(cwd, filename_live) self.nst_eeg_live.load_from_mat(last_label, last_trial, X, self.Fs) return self.nst_eeg_live