Update EStiMo_GUI.py
updated comments
This commit is contained in:
		
							parent
							
								
									a97d4e22e6
								
							
						
					
					
						commit
						ad77c22a04
					
				
					 1 changed files with 8 additions and 65 deletions
				
			
		|  | @ -30,10 +30,8 @@ import datetime | ||||||
| import ctypes | import ctypes | ||||||
| import scipy  | import scipy  | ||||||
| import pywt | import pywt | ||||||
| # import queue |  | ||||||
| 
 | 
 | ||||||
| from cycler import cycler | from cycler import cycler | ||||||
| # from matplotlib.backend_bases import MouseButton |  | ||||||
| from PyQt5.QtCore import QTimer, Qt | from PyQt5.QtCore import QTimer, Qt | ||||||
| from PyQt5.QtGui import QImage, QPixmap, QIcon, QFont | from PyQt5.QtGui import QImage, QPixmap, QIcon, QFont | ||||||
| from PyQt5.QtWidgets import (QMainWindow, QFileDialog, QMessageBox, QCheckBox, QLineEdit, QWidget, QPushButton, | from PyQt5.QtWidgets import (QMainWindow, QFileDialog, QMessageBox, QCheckBox, QLineEdit, QWidget, QPushButton, | ||||||
|  | @ -154,19 +152,13 @@ class NeurOneOffline(): | ||||||
|         eeg_chn = np.arange(0,num_electr,1) |         eeg_chn = np.arange(0,num_electr,1) | ||||||
|         hdr = mne.io.read_raw_brainvision(tmp_path) |         hdr = mne.io.read_raw_brainvision(tmp_path) | ||||||
| 
 | 
 | ||||||
|         # hdr.set_channel_types({'EMGleft': 'emg', 'EOGright': 'eog'}) |  | ||||||
|         # hdr.set_montage(mne.channels.read_custom_montage('easycap-M10_63_NO.txt')) |  | ||||||
|         # mrk_fullpath =  tmp_path[:-4]+'vmrk' |  | ||||||
|         # eeg_fullpath =  tmp_path[:-4]+'eeg'  #this two are made by hand instead of function. |  | ||||||
|                                                 #Maybe there is some func for this |  | ||||||
|         # Annotations returns all events - stimA, stimB, stopA, stopB, start of experiment etc... We chose only stim |         # Annotations returns all events - stimA, stimB, stopA, stopB, start of experiment etc... We chose only stim | ||||||
|         stim = hdr.annotations.onset[np.logical_or(hdr.annotations.description=="Stimulus/A", |         stim = hdr.annotations.onset[np.logical_or(hdr.annotations.description=="Stimulus/A", | ||||||
|                                                    hdr.annotations.description=="Stimulus/B")] |                                                    hdr.annotations.description=="Stimulus/B")] | ||||||
|         # Separate stimA and stimB |         # Separate stimA and stimB | ||||||
|         stimA = hdr.annotations.onset[hdr.annotations.description=="Stimulus/A"] |         stimA = hdr.annotations.onset[hdr.annotations.description=="Stimulus/A"] | ||||||
|         stimB = hdr.annotations.onset[hdr.annotations.description=="Stimulus/B"] |         stimB = hdr.annotations.onset[hdr.annotations.description=="Stimulus/B"] | ||||||
|                                                 #divide for stim A and B |                                     | ||||||
|         #stimR = hdr.annotations.onset[hdr.annotations.description=='Response/R 16'] |  | ||||||
|         npts = hdr.n_times |         npts = hdr.n_times | ||||||
|         nfft = int(hdr.info['sfreq'])    # Sampling rate [Hz] |         nfft = int(hdr.info['sfreq'])    # Sampling rate [Hz] | ||||||
|         fs = int(hdr.info['sfreq'])     # Sampling rate [Hz] |         fs = int(hdr.info['sfreq'])     # Sampling rate [Hz] | ||||||
|  | @ -335,8 +327,7 @@ class AppForm(QMainWindow): | ||||||
|             10: 7.812 - 15.625 Hz |             10: 7.812 - 15.625 Hz | ||||||
|             11: 15.625 - 31.25 Hz |             11: 15.625 - 31.25 Hz | ||||||
|             """ |             """ | ||||||
|             band = band - 9 #weird way, but then call from function works well for particular band |             band = band - 9  | ||||||
|             #but works correctly only for this set of features! |  | ||||||
|             dwt_pw1, dwt_pw2, dwt_pw3, dwt_pw4 = self.dwt[:4] |             dwt_pw1, dwt_pw2, dwt_pw3, dwt_pw4 = self.dwt[:4] | ||||||
|             #sum of squares |             #sum of squares | ||||||
|             dwt_pw1 = np.sum(dwt_pw1**2) |             dwt_pw1 = np.sum(dwt_pw1**2) | ||||||
|  | @ -380,8 +371,7 @@ class AppForm(QMainWindow): | ||||||
|                           'High Gamma FFT Power', 'Spectral entropy', 'Temporal entropy', |                           'High Gamma FFT Power', 'Spectral entropy', 'Temporal entropy', | ||||||
|                           'Line length', 'DWT Power 0-4 Hz', 'DWT 4-8 Hz',  |                           'Line length', 'DWT Power 0-4 Hz', 'DWT 4-8 Hz',  | ||||||
|                           'DWT 8-16 Hz', 'DWT 16-31 Hz','Variance','Correlation'] |                           'DWT 8-16 Hz', 'DWT 16-31 Hz','Variance','Correlation'] | ||||||
|         # One last thing to use your new function is to add string with its name |   | ||||||
|         # to the other First_window.py: variable features_names in class First_window |  | ||||||
|          |          | ||||||
|     def all_params(self, passed_params = None, restarted=''): |     def all_params(self, passed_params = None, restarted=''): | ||||||
|         #reads values from TMS_protocol.txt file |         #reads values from TMS_protocol.txt file | ||||||
|  | @ -562,10 +552,6 @@ class AppForm(QMainWindow): | ||||||
|             self.last_sec = ss.filtfilt(A, B, self.last_sec) |             self.last_sec = ss.filtfilt(A, B, self.last_sec) | ||||||
|         self.last_sec = ss.detrend(self.last_sec, axis=1) |         self.last_sec = ss.detrend(self.last_sec, axis=1) | ||||||
|          |          | ||||||
|         # plt.figure() |  | ||||||
|         # plt.plot(self.last_sec[self.included_ch].T) |  | ||||||
|         # plt.plot(eog) |  | ||||||
|         #that's stupid, move channel selection before!!!!!!!!!!!!! |  | ||||||
|         if self.use_regression: |         if self.use_regression: | ||||||
|             self.last_sec = eye_reg(self.last_sec[self.included_ch], eog) |             self.last_sec = eye_reg(self.last_sec[self.included_ch], eog) | ||||||
|         return self.last_sec |         return self.last_sec | ||||||
|  | @ -593,8 +579,6 @@ class AppForm(QMainWindow): | ||||||
|             else: |             else: | ||||||
|                 self.results[idx] = self.functions[feature]() |                 self.results[idx] = self.functions[feature]() | ||||||
|       |       | ||||||
|         #Checks how many fields were filled already, so we know what stage are we on |  | ||||||
|         #and where to save the data |  | ||||||
|         x = np.where(self.feature1==None)[0][0] |         x = np.where(self.feature1==None)[0][0] | ||||||
|         y = np.where(self.feature1==None)[1][0] |         y = np.where(self.feature1==None)[1][0] | ||||||
|          |          | ||||||
|  | @ -616,9 +600,6 @@ class AppForm(QMainWindow): | ||||||
|         print("Calculation of features: {}".format(times1-times)) |         print("Calculation of features: {}".format(times1-times)) | ||||||
|          |          | ||||||
|          |          | ||||||
|         #if value is not within threshold values then background color is red (salmon), otherwise green |  | ||||||
|          |  | ||||||
|         #checks if there is a need to change a color of the background |  | ||||||
|         old_prv_state = self.previous_state.copy() |         old_prv_state = self.previous_state.copy() | ||||||
|         if not all(np.isnan(self.thr_1)): |         if not all(np.isnan(self.thr_1)): | ||||||
|             if self.results[0]>=self.thr_1[0] and self.results[0]<=self.thr_1[1]: |             if self.results[0]>=self.thr_1[0] and self.results[0]<=self.thr_1[1]: | ||||||
|  | @ -724,9 +705,7 @@ class AppForm(QMainWindow): | ||||||
|             #If there is a need to redraw we do that. draw() option is slower, but more robust |             #If there is a need to redraw we do that. draw() option is slower, but more robust | ||||||
|             if need_redraw: |             if need_redraw: | ||||||
|                 self.canvasMap.draw() |                 self.canvasMap.draw() | ||||||
|             #otherwise we can just update the line, or to be precise, I think it just |             #otherwise we can just update the line, or to be precise,  | ||||||
|             #draws the line on the old one. In this application it's fine. Faster than previous method. |  | ||||||
|             #I can think about blitting, so it could be even faster... |  | ||||||
|             else: |             else: | ||||||
|                 for i in range(3): |                 for i in range(3): | ||||||
|                     for j in range(2): |                     for j in range(2): | ||||||
|  | @ -740,8 +719,7 @@ class AppForm(QMainWindow): | ||||||
|     def update(self): |     def update(self): | ||||||
|         """Updates data, checks if something should be plotted""" |         """Updates data, checks if something should be plotted""" | ||||||
|         time_start = time.time() |         time_start = time.time() | ||||||
|         # There were some problems with delay. This way it works, but probably it can be done better |   | ||||||
|         # If the queue with data timer is sped up. |  | ||||||
|         if self.q.qsize()>0: |         if self.q.qsize()>0: | ||||||
|             self.timer.setInterval(int(1*self.speed_general*0.97)) |             self.timer.setInterval(int(1*self.speed_general*0.97)) | ||||||
|         if self.q.qsize()<1 and self.timer.interval()!= int(self.speed_general*1.1): |         if self.q.qsize()<1 and self.timer.interval()!= int(self.speed_general*1.1): | ||||||
|  | @ -827,13 +805,6 @@ class AppForm(QMainWindow): | ||||||
|         if len(stim)>0: |         if len(stim)>0: | ||||||
|             for ind in stim[::-1]: |             for ind in stim[::-1]: | ||||||
|                 size = self.data_len - (od+ind-int(int_from*self.Fs)) |                 size = self.data_len - (od+ind-int(int_from*self.Fs)) | ||||||
|                 # print('size:', size) |  | ||||||
|                 # print(len(self.loaded)) |  | ||||||
|                 # Interpolation - pretty long line, but basically it chooses ranges and |  | ||||||
|                 # assign boundary value as a baseline and does that in (I guess) more optimal way than using loops |  | ||||||
|                 # self.loaded[:, od+ind-int(int_from*self.Fs):od+ind+int(int_to*self.Fs)] = np.outer( |  | ||||||
|                 #     self.loaded[:,min(od+ind+int(int_to*self.Fs), 30000-1)], np.ones(min(size, int((int_from+int_to)*self.Fs)))) |  | ||||||
|                 # this way is even easier... |  | ||||||
|                 self.loaded[:, od+ind-int(int_from*self.Fs):od+ind+int(int_to*self.Fs)] = self.loaded[:,min(od+ind+int(int_to*self.Fs), 30000-1)].reshape(-1, 1) |                 self.loaded[:, od+ind-int(int_from*self.Fs):od+ind+int(int_to*self.Fs)] = self.loaded[:,min(od+ind+int(int_to*self.Fs), 30000-1)].reshape(-1, 1) | ||||||
|                 # for i in range(self.loaded.shape[0]): |                 # for i in range(self.loaded.shape[0]): | ||||||
|                 #     self.loaded[i, od+ind-int(int_from*self.Fs):od+ind+int(int_to*self.Fs)] =  np.linspace( |                 #     self.loaded[i, od+ind-int(int_from*self.Fs):od+ind+int(int_to*self.Fs)] =  np.linspace( | ||||||
|  | @ -861,8 +832,6 @@ class AppForm(QMainWindow): | ||||||
|          |          | ||||||
|         step9 = time.time()-time_start |         step9 = time.time()-time_start | ||||||
|          |          | ||||||
|         # If do_calibration is True and there were trigger recently then stop calibration |  | ||||||
|         # TODO: THAT'S CONDITION REQUIRED FOR STARTING MEASURMENTS. PROBABLY IT WON'T WORK FOR SOME MORE EXTREME SETTINGS |  | ||||||
|         # if self.do_calibration and len(stim_where[stim_where>(self.data_len-max( |         # if self.do_calibration and len(stim_where[stim_where>(self.data_len-max( | ||||||
|         #         2000, round(self.Fs*self.time_between_bursts*0.7, -3)))])>0: |         #         2000, round(self.Fs*self.time_between_bursts*0.7, -3)))])>0: | ||||||
|         if self.do_calibration and len(stim_where[stim_where>(self.data_len-max(2000, self.exp_time+1500))])>0: |         if self.do_calibration and len(stim_where[stim_where>(self.data_len-max(2000, self.exp_time+1500))])>0: | ||||||
|  | @ -876,7 +845,6 @@ class AppForm(QMainWindow): | ||||||
|             return 0 #ends run of this function so nothing else happens |             return 0 #ends run of this function so nothing else happens | ||||||
|         step10 = time.time()-time_start |         step10 = time.time()-time_start | ||||||
|         # If set number of stimuli is detected |         # If set number of stimuli is detected | ||||||
|         # doit --> set length of the measurment between bursts |  | ||||||
|         # if self.doit==0 and sum(stim_where>self.data_len-max( |         # if self.doit==0 and sum(stim_where>self.data_len-max( | ||||||
|         #         2000, round(self.Fs*self.time_between_bursts*0.7, -3)))==10: |         #         2000, round(self.Fs*self.time_between_bursts*0.7, -3)))==10: | ||||||
|         print(sum(stim_where>self.data_len-max(2000, self.exp_time+1500))) |         print(sum(stim_where>self.data_len-max(2000, self.exp_time+1500))) | ||||||
|  | @ -900,9 +868,6 @@ class AppForm(QMainWindow): | ||||||
|         elif self.doit>0: |         elif self.doit>0: | ||||||
|             print(self.doit) |             print(self.doit) | ||||||
|             self.last_stim = stim_where[-1] |             self.last_stim = stim_where[-1] | ||||||
|             # In some situations last stimuli might be already from another train, while |  | ||||||
|             # First 100ms of loaded signal belong to previous one. That is why this exception exists |  | ||||||
|             # EDIT: not sure if it's still needed after other changes I made |  | ||||||
|             if any(np.diff(stim_where[stim_where>self.data_len-max( |             if any(np.diff(stim_where[stim_where>self.data_len-max( | ||||||
|                     2000, round(self.Fs*self.time_between_bursts*1.2, -3))])>1000): |                     2000, round(self.Fs*self.time_between_bursts*1.2, -3))])>1000): | ||||||
|                 print('UWAGA NA TO') |                 print('UWAGA NA TO') | ||||||
|  | @ -1015,7 +980,6 @@ class AppForm(QMainWindow): | ||||||
|             self.button4.setText("Start calibration") |             self.button4.setText("Start calibration") | ||||||
|             self.button4.setStyleSheet('') |             self.button4.setStyleSheet('') | ||||||
|             #par = self.thr_parameter |             #par = self.thr_parameter | ||||||
|             #Need to clean the figure to prepare is for a different type of plot |  | ||||||
|             for i in range(6): |             for i in range(6): | ||||||
|                 self.axesMap[i//2,i%2].cla() |                 self.axesMap[i//2,i%2].cla() | ||||||
|              |              | ||||||
|  | @ -1120,8 +1084,7 @@ class AppForm(QMainWindow): | ||||||
|         #calculate fft |         #calculate fft | ||||||
|         self.S = abs(np.fft.rfft(self.second_to_analyze)) |         self.S = abs(np.fft.rfft(self.second_to_analyze)) | ||||||
|          |          | ||||||
|         #this is a bit shady, but should work. check it out if doesn't! | 
 | ||||||
|         #do dwt only if any features requires it |  | ||||||
|         if any(feature_num in self.used_features for feature_num in [8,9,10,11]): |         if any(feature_num in self.used_features for feature_num in [8,9,10,11]): | ||||||
|             self.dwt = pywt.wavedec(self.second_to_analyze, 'db1', level=8) |             self.dwt = pywt.wavedec(self.second_to_analyze, 'db1', level=8) | ||||||
|          |          | ||||||
|  | @ -1152,8 +1115,7 @@ class AppForm(QMainWindow): | ||||||
|         self.cals = [self.f1_cal, self.f2_cal, self.f3_cal, self.f4_cal, self.f5_cal, |         self.cals = [self.f1_cal, self.f2_cal, self.f3_cal, self.f4_cal, self.f5_cal, | ||||||
|                      self.f6_cal] |                      self.f6_cal] | ||||||
|          |          | ||||||
|         #!!! Temporary, it's wrong but it's overwritten later. It's needed to check if all features are used, | 
 | ||||||
|         #but there could be more optimal solution. Remove it at some point! |  | ||||||
|         self.thr_1 = [np.min(self.f1_cal)-0.1*np.min(self.f1_cal),  |         self.thr_1 = [np.min(self.f1_cal)-0.1*np.min(self.f1_cal),  | ||||||
|                               np.max(self.f1_cal)+0.1*np.max(self.f1_cal)] |                               np.max(self.f1_cal)+0.1*np.max(self.f1_cal)] | ||||||
|         self.thr_2 = [np.min(self.f2_cal)-0.1*np.min(self.f2_cal),  |         self.thr_2 = [np.min(self.f2_cal)-0.1*np.min(self.f2_cal),  | ||||||
|  | @ -1246,12 +1208,6 @@ class AppForm(QMainWindow): | ||||||
|             tick.label1.set_visible(False) |             tick.label1.set_visible(False) | ||||||
|             tick.label2.set_visible(False) |             tick.label2.set_visible(False) | ||||||
|          |          | ||||||
|         # for tick in self.axes.yaxis.get_major_ticks(): |  | ||||||
|         #     tick.tick1line.set_visible(False) |  | ||||||
|         #     tick.tick2line.set_visible(False) |  | ||||||
|         #     tick.label1.set_visible(False) |  | ||||||
|         #     tick.label2.set_visible(False) |  | ||||||
|          |  | ||||||
|         self.axes.set_yticks(np.arange(1, (self.num_of_ch)*1.01, 1)) |         self.axes.set_yticks(np.arange(1, (self.num_of_ch)*1.01, 1)) | ||||||
|         self.axes.set_yticklabels(self.ch_names[::-1]) |         self.axes.set_yticklabels(self.ch_names[::-1]) | ||||||
| 
 | 
 | ||||||
|  | @ -1304,14 +1260,6 @@ class AppForm(QMainWindow): | ||||||
|         self.canvas.draw() |         self.canvas.draw() | ||||||
|         self.canvasMap.draw() #update canvas |         self.canvasMap.draw() #update canvas | ||||||
|          |          | ||||||
|         #NOT NEEDED |  | ||||||
|         # for i in range(self.num_of_ch): |  | ||||||
|         #     self.axbackground = self.canvas.copy_from_bbox(self.axes.bbox) |  | ||||||
|          |  | ||||||
|         # texts = [] |  | ||||||
|         # for ind,name in enumerate(self.ch_names): |  | ||||||
|         #     texts.append(self.axes.text(-0.03,1-(ind+1)/(len(self.ch_names)+1),  |  | ||||||
|         #                                 name, transform=self.axes.transAxes, color='r', fontsize=13)) |  | ||||||
|          |          | ||||||
|         self.button1 = QPushButton("&Settings") |         self.button1 = QPushButton("&Settings") | ||||||
|         self.button1.setCheckable(False) |         self.button1.setCheckable(False) | ||||||
|  | @ -1416,8 +1364,3 @@ if __name__ == '__main__': | ||||||
|     form = First_window(AppForm) #AppForm() |     form = First_window(AppForm) #AppForm() | ||||||
|     form.show() |     form.show() | ||||||
|     sys.exit(app.exec_()) |     sys.exit(app.exec_()) | ||||||
| 
 |  | ||||||
| # cut time different from both sides |  | ||||||
| # some deafult settings. Maybe remember last configuration? |  | ||||||
| # EMG and EOG - none, more than one? |  | ||||||
| # change names to final names |  | ||||||
		Loading…
	
		Reference in a new issue