misleep 0.2.2b0__tar.gz → 0.2.4b0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. {misleep-0.2.2b0 → misleep-0.2.4b0}/PKG-INFO +7 -1
  2. {misleep-0.2.2b0 → misleep-0.2.4b0}/README.md +5 -0
  3. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/config.ini +2 -2
  4. misleep-0.2.4b0/misleep/gui/dialog.py +374 -0
  5. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/gui/main_window.py +19 -3
  6. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/gui/uis/main_window_ui.py +5 -4
  7. misleep-0.2.4b0/misleep/gui/uis/state_spectral_dialog_ui.py +82 -0
  8. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/gui/uis/transfer_result_dialog_ui.py +27 -39
  9. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/gui/utils.py +61 -1
  10. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/io/annotation_io.py +75 -47
  11. misleep-0.2.4b0/misleep/preprocessing/signals.py +69 -0
  12. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep.egg-info/PKG-INFO +7 -1
  13. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep.egg-info/SOURCES.txt +1 -0
  14. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep.egg-info/requires.txt +1 -0
  15. {misleep-0.2.2b0 → misleep-0.2.4b0}/setup.py +3 -2
  16. misleep-0.2.2b0/misleep/gui/dialog.py +0 -217
  17. misleep-0.2.2b0/misleep/preprocessing/signals.py +0 -15
  18. {misleep-0.2.2b0 → misleep-0.2.4b0}/LICENSE +0 -0
  19. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/__init__.py +0 -0
  20. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/__main__.py +0 -0
  21. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/gui/__init__.py +0 -0
  22. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/gui/about.py +0 -0
  23. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/gui/resources/__init__.py +0 -0
  24. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/gui/resources/entire_logo.png +0 -0
  25. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/gui/resources/logo.png +0 -0
  26. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/gui/resources/misleep.py +0 -0
  27. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/gui/resources/misleep.qrc +0 -0
  28. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/gui/show.py +0 -0
  29. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/gui/spec_window.py +0 -0
  30. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/gui/thread.py +0 -0
  31. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/gui/uis/__init__.py +0 -0
  32. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/gui/uis/about_ui.py +0 -0
  33. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/gui/uis/label_dialog_ui.py +0 -0
  34. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/gui/uis/save_data_dialog_ui.py +0 -0
  35. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/gui/uis/spec_window_ui.py +0 -0
  36. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/io/__init__.py +0 -0
  37. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/io/base.py +0 -0
  38. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/io/signal_io.py +0 -0
  39. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/preprocessing/__init__.py +0 -0
  40. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/preprocessing/channel.py +0 -0
  41. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/preprocessing/spectral.py +0 -0
  42. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/utils/__init__.py +0 -0
  43. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/utils/annotation.py +0 -0
  44. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/utils/signals.py +0 -0
  45. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/viz/__init__.py +0 -0
  46. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/viz/hypnogram.py +0 -0
  47. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/viz/signals.py +0 -0
  48. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep/viz/spectral.py +0 -0
  49. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep.egg-info/dependency_links.txt +0 -0
  50. {misleep-0.2.2b0 → misleep-0.2.4b0}/misleep.egg-info/top_level.txt +0 -0
  51. {misleep-0.2.2b0 → misleep-0.2.4b0}/setup.cfg +0 -0
  52. {misleep-0.2.2b0 → misleep-0.2.4b0}/test/test_annotation_io.py +0 -0
  53. {misleep-0.2.2b0 → misleep-0.2.4b0}/test/test_loadmat73.py +0 -0
  54. {misleep-0.2.2b0 → misleep-0.2.4b0}/test/test_midata.py +0 -0
  55. {misleep-0.2.2b0 → misleep-0.2.4b0}/test/test_show.py +0 -0
  56. {misleep-0.2.2b0 → misleep-0.2.4b0}/test/test_signal_io.py +0 -0
  57. {misleep-0.2.2b0 → misleep-0.2.4b0}/test/test_signals_viz.py +0 -0
  58. {misleep-0.2.2b0 → misleep-0.2.4b0}/test/test_spectral_viz.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: misleep
3
- Version: 0.2.2b0
3
+ Version: 0.2.4b0
4
4
  Summary: MiSleep: Mice Sleep EEG/EMG visualization, scoring and analysis.
5
5
  Home-page: https://github.com/BryanWang0702/MiSleep/
6
6
  Download-URL: https://github.com/BryanWang0702/MiSleep/
@@ -29,6 +29,7 @@ Requires-Dist: pyqt5
29
29
  Requires-Dist: mat73
30
30
  Requires-Dist: pandas
31
31
  Requires-Dist: openpyxl
32
+ Requires-Dist: yasa
32
33
 
33
34
  # MiSleep
34
35
  MiSleep is for EEG/EMG signal processing and visualization
@@ -40,6 +41,11 @@ MiSleep is for EEG/EMG signal processing and visualization
40
41
  pip install misleep==0.2.2b0
41
42
  ```
42
43
 
44
+ Find the directory where you installed misleep, run
45
+ ```shell
46
+ python -m misleep
47
+ ```
48
+
43
49
  ### New features
44
50
  1. New data structure
45
51
 
@@ -8,6 +8,11 @@ MiSleep is for EEG/EMG signal processing and visualization
8
8
  pip install misleep==0.2.2b0
9
9
  ```
10
10
 
11
+ Find the directory where you installed misleep, run
12
+ ```shell
13
+ python -m misleep
14
+ ```
15
+
11
16
  ### New features
12
17
  1. New data structure
13
18
 
@@ -1,5 +1,5 @@
1
1
  [gui]
2
- version = v0.2.2 Beta
2
+ version = v0.2.4 Beta
3
3
  updatetime = 2024/04/01
4
4
  marker = ['pat', 'add water', 'third']
5
5
  startend = ['SWA', 'SWA', 'start end label', 'start end label', 'start end label', 'start end label', 'start end label']
@@ -8,5 +8,5 @@ statecolor = {"1": "orange", "2": "skyblue", "3": "red", "4": "white"}
8
8
  statecolorbgalpha = 0.1
9
9
  markerlinecolor = "red"
10
10
  startendlinecolor = "blue"
11
- openpath = E:/workplace/EEGProcessing/00_DATA/20240117_0700_WXQ_3mice_24h/mouse2/mouse2_label.txt
11
+ openpath = E:/workplace/EEGProcessing/00_DATA/20240114_17_0700_7pin/female3/female3_label.txt
12
12
 
@@ -0,0 +1,374 @@
1
+ # -*- coding: UTF-8 -*-
2
+ """art_detection
3
+ @Project: MiSleep_v2
4
+ @File: label_dialog.py
5
+ @Author: Xueqiang Wang
6
+ @Date: 2024/3/28
7
+ @Description: Dialog file, label dialog, transfer result dialog
8
+ """
9
+ from PyQt5.QtCore import QCoreApplication, Qt, QStringListModel
10
+ from PyQt5.QtWidgets import QDialog, QMessageBox, QFileDialog
11
+ import datetime
12
+
13
+ from misleep.gui.uis.label_dialog_ui import Ui_Dialog
14
+ from misleep.gui.uis.transfer_result_dialog_ui import Ui_TransferResultDialog
15
+ from misleep.gui.uis.state_spectral_dialog_ui import Ui_StateSpectralDialog
16
+ from misleep.gui.thread import SaveThread
17
+ from misleep.io.annotation_io import transfer_result
18
+ from misleep.utils.signals import signal_filter
19
+ from misleep.utils.annotation import lst2group
20
+ from misleep.gui.utils import cal_draw_spectrum
21
+ from misleep.preprocessing.signals import reject_artifact
22
+ import pandas as pd
23
+ from copy import deepcopy
24
+
25
+
26
+ class label_dialog(QDialog, Ui_Dialog):
27
+ def __init__(self, parent=None, config=None):
28
+ """
29
+ Initialize the Label dialog of MiSleep
30
+ """
31
+ super().__init__(parent)
32
+
33
+ # Enable high dpi devices
34
+ QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
35
+ self.setupUi(self)
36
+
37
+ # Load configuration
38
+ self.config = config
39
+
40
+ # Type representing marker(0) or start_end(1)
41
+ self._type = 0
42
+
43
+ # List view of selected labels
44
+ self.slm = QStringListModel()
45
+ self.LabelListView.setModel(self.slm)
46
+ self.marker_label = [each[1:-1] for each in
47
+ self.config['gui']['marker'][1:-1].split(', ')]
48
+ self.start_end_label = [each[1:-1] for each in
49
+ self.config['gui']['startend'][1:-1].split(', ')]
50
+ self.label_name = ""
51
+ self.closed = False
52
+
53
+ self.OKBt.clicked.connect(self.submit_label)
54
+ self.CancelBt.clicked.connect(self.cancel_event)
55
+ self.AddBt.clicked.connect(self.add_label)
56
+ self.DeleteBt.clicked.connect(self.delete_label)
57
+
58
+ self.slm.dataChanged.connect(self.update_label_list)
59
+ self.add_or_delete = False
60
+
61
+
62
+ def show_contents(self, idx=0):
63
+ """Show label contents"""
64
+ self.closed = False
65
+
66
+ if self._type == 0:
67
+ self.slm.setStringList(self.marker_label)
68
+ self.LabelListView.setModel(self.slm)
69
+
70
+ if self._type == 1:
71
+ self.slm.setStringList(self.start_end_label)
72
+ self.LabelListView.setModel(self.slm)
73
+
74
+ if idx == -1:
75
+ idx = len(self.slm.stringList()) - 1
76
+ idx = self.slm.index(idx)
77
+ self.LabelListView.setCurrentIndex(idx)
78
+
79
+ def submit_label(self):
80
+ """Triggered by Clicking Ok Button"""
81
+
82
+ if self._type == 0:
83
+ self.label_name = self.marker_label[
84
+ self.LabelListView.selectedIndexes()[0].row()
85
+ ]
86
+
87
+ else:
88
+ self.label_name = self.start_end_label[
89
+ self.LabelListView.selectedIndexes()[0].row()
90
+ ]
91
+
92
+ self.hide()
93
+
94
+ def update_label_list(self):
95
+ """Update label list when edited"""
96
+ if not self.add_or_delete:
97
+ string_list = self.slm.stringList()
98
+
99
+ if self._type == 0:
100
+ self.marker_label = string_list
101
+ if self._type == 1:
102
+ self.start_end_label = string_list
103
+ else:
104
+ self.show_contents(idx=-1)
105
+ self.add_or_delete = False
106
+
107
+ self.save_config()
108
+
109
+ def add_label(self):
110
+ if self._type == 0:
111
+ self.marker_label.append('label')
112
+ elif self._type == 1:
113
+ self.start_end_label.append('start end label')
114
+
115
+ self.add_or_delete = True
116
+ self.update_label_list()
117
+
118
+ def delete_label(self):
119
+ if not self.LabelListView.selectedIndexes():
120
+ return
121
+ if len(self.slm.stringList()) == 1:
122
+ QMessageBox.about(self, "Error", "You can't delete all labels!")
123
+ return
124
+ if self._type == 0:
125
+ self.marker_label.pop(
126
+ self.LabelListView.selectedIndexes()[0].row()
127
+ )
128
+ elif self._type == 1:
129
+ self.start_end_label.pop(
130
+ self.LabelListView.selectedIndexes()[0].row()
131
+ )
132
+ self.add_or_delete = True
133
+ self.update_label_list()
134
+
135
+ def save_config(self):
136
+ """When label changed, save configuration to file, open a new thread"""
137
+ self.config.set('gui', 'MARKER', str(self.marker_label))
138
+ self.config.set('gui', 'STARTEND', str(self.start_end_label))
139
+ save_thread = SaveThread(file=self.config,
140
+ file_path='./misleep/config.ini')
141
+ save_thread.save_config()
142
+ save_thread.quit()
143
+
144
+ def cancel_event(self):
145
+ """Triggered by the `cancel` button"""
146
+ self.closed = True
147
+ self.hide()
148
+
149
+ def closeEvent(self, event):
150
+ event.ignore()
151
+ self.closed = True
152
+ self.hide()
153
+
154
+
155
+ class transferResult_dialog(QDialog, Ui_TransferResultDialog):
156
+ def __init__(self, parent=None):
157
+ """
158
+ Initialize the transfer dialog of MiSleep
159
+ """
160
+ super().__init__(parent)
161
+
162
+ # Enable high dpi devices
163
+ QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
164
+ self.setupUi(self)
165
+
166
+ self.ACTimeEditor.setDisabled(True)
167
+ self.TransferStartTimeEdit.setDisabled(True)
168
+ self.ResetTimeCheckBox.clicked.connect(self.ac_time_editor_changed)
169
+ self.ResetTransferStartTimeCheckBox.clicked.connect(self.start_time_editor_changed)
170
+ self.OKBt.clicked.connect(self.okEvent)
171
+ self.CancelBt.clicked.connect(self.cancelEvent)
172
+ self.closed = True
173
+
174
+ def ac_time_editor_changed(self):
175
+ if self.ResetTimeCheckBox.isChecked():
176
+ self.ACTimeEditor.setEnabled(True)
177
+ if not self.ResetTimeCheckBox.isChecked():
178
+ self.ACTimeEditor.setDisabled(True)
179
+
180
+ def start_time_editor_changed(self):
181
+ if self.ResetTransferStartTimeCheckBox.isChecked():
182
+ self.TransferStartTimeEdit.setEnabled(True)
183
+ if not self.ResetTransferStartTimeCheckBox.isChecked():
184
+ self.TransferStartTimeEdit.setDisabled(True)
185
+
186
+ def transfer(self, config, mianno, ac_time):
187
+ """Transfer result to dataframe, triggered by okay button"""
188
+ mianno = deepcopy(mianno)
189
+ ac_time = deepcopy(ac_time)
190
+
191
+ if self.ResetTimeCheckBox.isChecked():
192
+ ac_time = self.ACTimeEditor.dateTime().toPyDateTime()
193
+ else:
194
+ ac_time = datetime.datetime.strptime(ac_time, "%Y%m%d-%H:%M:%S")
195
+
196
+ if self.ResetTransferStartTimeCheckBox.isChecked():
197
+ start_time = self.TransferStartTimeEdit.dateTime().toPyDateTime()
198
+ if start_time > ac_time:
199
+ delay_seconds = (start_time - ac_time).seconds
200
+ mianno._marker = mianno.marker[delay_seconds:]
201
+ mianno._start_end = mianno.start_end[delay_seconds:]
202
+ mianno._sleep_state = mianno.sleep_state[delay_seconds:]
203
+ ac_time = start_time
204
+
205
+
206
+ fd, _ = QFileDialog.getSaveFileName(self, "Save transfered result",
207
+ f"{config['gui']['openpath'].split('/')[0]}/transfer_result.xlsx",
208
+ "*.xlsx;;")
209
+ if fd == '':
210
+ return
211
+
212
+ df, analyse_df = transfer_result(mianno=mianno, ac_time=ac_time)
213
+
214
+ writer = pd.ExcelWriter(fd, datetime_format='yyyy-mm-dd hh:mm:ss')
215
+ pd.concat([df, analyse_df], axis=1).to_excel(
216
+ excel_writer=writer, sheet_name='All', index=False)
217
+
218
+ writer.close()
219
+
220
+ QMessageBox.about(self, "Info", "Transfered result saved")
221
+
222
+ def okEvent(self):
223
+ self.closed = False
224
+ self.hide()
225
+
226
+ def cancelEvent(self):
227
+ """Triggered by the `cancel` button"""
228
+ self.closed = True
229
+ self.hide()
230
+
231
+ def closeEvent(self, event):
232
+ event.ignore()
233
+ self.closed = True
234
+ self.hide()
235
+
236
+
237
+ class stateSpectral_dialog(QDialog, Ui_StateSpectralDialog):
238
+ def __init__(self, parent=None):
239
+ """
240
+ Initialize the state spectral dialog of MiSleep
241
+ """
242
+ super().__init__(parent)
243
+
244
+ # Enable high dpi devices
245
+ QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
246
+ self.setupUi(self)
247
+
248
+ self.BPFilterCheckBox.clicked.connect(self.BP_filter_check_changed)
249
+ self.BPFilterCheckBox.setChecked(True)
250
+ self.RejectArtifactCheckBox.clicked.connect(self.reject_artifact_artifacts_changed)
251
+ self.RejectArtifactCheckBox.setChecked(False)
252
+
253
+ self.OKBt.clicked.connect(self.okEvent)
254
+ self.CancelBt.clicked.connect(self.cancelEvent)
255
+ self.closed = True
256
+
257
+ def BP_filter_check_changed(self):
258
+ if self.BPFilterCheckBox.isChecked():
259
+ self.BPLow.setEnabled(True)
260
+ self.BPHigh.setEnabled(True)
261
+ if not self.BPFilterCheckBox.isChecked():
262
+ self.BPLow.setDisabled(True)
263
+ self.BPHigh.setDisabled(True)
264
+
265
+ def reject_artifact_artifacts_changed(self):
266
+ if self.RejectArtifactCheckBox.isChecked():
267
+ self.ArtThresholdSpinBox.setEnabled(True)
268
+ if not self.RejectArtifactCheckBox.isChecked():
269
+ self.ArtThresholdSpinBox.setDisabled(True)
270
+
271
+ def dialog_show(self, channels):
272
+ """Show state spectral dialog, fill params"""
273
+ self.ChannelSelector.addItems(channels)
274
+ self.ChannelSelector.setCurrentIndex(0)
275
+
276
+ def spectral_analysis(self, midata, mianno, config):
277
+ """Do spectral analysis"""
278
+
279
+ channel_idx = self.ChannelSelector.currentIndex()
280
+ channel_data = midata.signals[channel_idx]
281
+ sleep_state = lst2group([[idx, each] for idx, each in enumerate(mianno.sleep_state)])
282
+ sf = midata.sf[channel_idx]
283
+
284
+ # Do filter if checked
285
+ if self.BPFilterCheckBox.isChecked():
286
+ low = self.BPLow.value()
287
+ high = self.BPHigh.value()
288
+ channel_data, _ = signal_filter(channel_data, sf=sf, btype='bandpass',
289
+ low=low, high=high)
290
+
291
+ # Merge 4 states' data
292
+ NREM_data = [channel_data[int(each[0]*sf): int(each[1]*sf)]
293
+ for each in sleep_state if each[2] == 1]
294
+ NREM_data = [element for sublist in NREM_data for element in sublist]
295
+ REM_data = [channel_data[int(each[0]*sf): int(each[1]*sf)]
296
+ for each in sleep_state if each[2] == 2]
297
+ REM_data = [element for sublist in REM_data for element in sublist]
298
+ Wake_data = [channel_data[int(each[0]*sf): int(each[1]*sf)]
299
+ for each in sleep_state if each[2] == 3]
300
+ Wake_data = [element for sublist in Wake_data for element in sublist]
301
+ Init_data = [channel_data[int(each[0]*sf): int(each[1]*sf)]
302
+ for each in sleep_state if each[2] == 4]
303
+ Init_data = [element for sublist in Init_data for element in sublist]
304
+
305
+ # Reject artifact if checked
306
+ if self.RejectArtifactCheckBox.isChecked():
307
+ threshold = self.ArtThresholdSpinBox.value()
308
+ else:
309
+ threshold = 1.5
310
+ if self.RejectArtifactCheckBox.isChecked():
311
+ NREM_data = reject_artifact(NREM_data, sf=sf, threshold=threshold)
312
+ REM_data = reject_artifact(REM_data, sf=sf, threshold=threshold)
313
+ Wake_data = reject_artifact(Wake_data, sf=sf, threshold=threshold)
314
+ Init_data = reject_artifact(Init_data, sf=sf, threshold=threshold)
315
+
316
+ nperseg = 10*sf
317
+ NREM_spec, NREM_figure = cal_draw_spectrum(data=NREM_data, sf=sf, nperseg=nperseg)
318
+ REM_spec, REM_figure = cal_draw_spectrum(data=REM_data, sf=sf, nperseg=nperseg)
319
+ Wake_spec, Wake_figure = cal_draw_spectrum(data=Wake_data, sf=sf, nperseg=nperseg)
320
+
321
+ name_map = {
322
+ 1: 'NREM',
323
+ 2: 'REM',
324
+ 3: 'Wake',
325
+ 4: 'Init'
326
+ }
327
+
328
+ fd = QFileDialog.getExistingDirectory(self,
329
+ "Select a folder to save 4 stages' data",
330
+ f"{config['gui']['openpath']}")
331
+ if fd == '':
332
+ return
333
+
334
+ # Save figure
335
+ NREM_figure.savefig(fd+'/NREM_spectrum.pdf')
336
+ REM_figure.savefig(fd+'/REM_spectrum.pdf')
337
+ Wake_figure.savefig(fd+'/Wake_spectrum.pdf')
338
+ writer = pd.ExcelWriter(fd+'/power_results.xlsx')
339
+
340
+ # Write to excel file
341
+ for idx, spec in enumerate([NREM_spec, REM_spec, Wake_spec]):
342
+ _df = pd.DataFrame(data=spec.T, columns=['frequency', 'power'])
343
+ _df.to_excel(excel_writer=writer, sheet_name=name_map[idx+1], index=False)
344
+ if len(Init_data) > sf*10:
345
+ Init_spec, Init_figure = cal_draw_spectrum(data=Init_data, sf=sf, nperseg=nperseg)
346
+ _df = pd.DataFrame(data=Init_spec.T, columns=['frequency', 'power'])
347
+ _df.to_excel(excel_writer=writer, sheet_name=name_map[4], index=False)
348
+ Init_figure.savefig(fd + '/Init_spectrum.pdf')
349
+
350
+ writer.close()
351
+
352
+ def okEvent(self):
353
+ self.closed = False
354
+ self.hide()
355
+
356
+ def cancelEvent(self):
357
+ """Triggered by the `cancel` button"""
358
+ self.closed = True
359
+ self.hide()
360
+
361
+ def closeEvent(self, event):
362
+ event.ignore()
363
+ self.closed = True
364
+ self.hide()
365
+
366
+
367
+
368
+
369
+
370
+
371
+
372
+
373
+
374
+
@@ -26,7 +26,7 @@ from misleep.io.annotation_io import load_misleep_anno, load_bio_anno
26
26
  from misleep.gui.utils import create_new_mianno
27
27
  from misleep.utils.annotation import lst2group
28
28
  from misleep.gui.about import about_dialog
29
- from misleep.gui.dialog import label_dialog, transferResult_dialog
29
+ from misleep.gui.dialog import label_dialog, transferResult_dialog, stateSpectral_dialog
30
30
  from misleep.gui.spec_window import SpecWindow
31
31
  from misleep.gui.uis.main_window_ui import Ui_MiSleep
32
32
  from misleep.preprocessing.spectral import spectrogram, spectrum, band_power
@@ -121,6 +121,9 @@ class main_window(QMainWindow, Ui_MiSleep):
121
121
  # Initial transfer result dialog
122
122
  self.transfer_result_dialog = transferResult_dialog()
123
123
 
124
+ # Initial state spectral dialog
125
+ self.state_spectral_dialog = stateSpectral_dialog()
126
+
124
127
  # Check wheher operation done and saved or not
125
128
  self.is_saved = True
126
129
 
@@ -1346,6 +1349,8 @@ class main_window(QMainWindow, Ui_MiSleep):
1346
1349
 
1347
1350
  def tool_bar_dispatcher(self, signal):
1348
1351
  """Triggered by ToolBar action, transfer result"""
1352
+ if signal.text() == "State Spectral":
1353
+ self.state_spectral()
1349
1354
  if signal.text() == "Transfer Result":
1350
1355
  self.transfer_result()
1351
1356
 
@@ -1353,12 +1358,23 @@ class main_window(QMainWindow, Ui_MiSleep):
1353
1358
  """Transfer result into file"""
1354
1359
  self.transfer_result_dialog.ACTimeEditor.setDateTime(self.ac_time)
1355
1360
  self.transfer_result_dialog.TransferStartTimeEdit.setDateTime(self.ac_time)
1356
- self.transfer_result_dialog.exec_()
1357
- if self.label_dialog.closed:
1361
+ self.transfer_result_dialog.exec()
1362
+ if self.transfer_result_dialog.closed:
1358
1363
  return
1359
1364
  self.transfer_result_dialog.transfer(config=self.config,
1360
1365
  mianno=self.mianno,
1361
1366
  ac_time=self.midata.time)
1367
+
1368
+ def state_spectral(self):
1369
+ """Analyze state spectral"""
1370
+ self.state_spectral_dialog.dialog_show(channels=self.midata.channels)
1371
+ self.state_spectral_dialog.exec()
1372
+ if self.state_spectral_dialog.closed:
1373
+ return
1374
+ self.state_spectral_dialog.spectral_analysis(midata=self.midata,
1375
+ mianno=self.mianno,
1376
+ config=self.config)
1377
+
1362
1378
 
1363
1379
  def save_anno(self):
1364
1380
  """Save annotation into file"""
@@ -327,8 +327,8 @@ class Ui_MiSleep(object):
327
327
  self.actionSave_Annotation.setObjectName("actionSave_Annotation")
328
328
  self.actionAbout = QtWidgets.QAction(MiSleep)
329
329
  self.actionAbout.setObjectName("actionAbout")
330
- self.actionMerge_Data = QtWidgets.QAction(MiSleep)
331
- self.actionMerge_Data.setObjectName("actionMerge_Data")
330
+ self.actionState_Spectral = QtWidgets.QAction(MiSleep)
331
+ self.actionState_Spectral.setObjectName("actionState_Spectral")
332
332
  self.actionTransfer_Result = QtWidgets.QAction(MiSleep)
333
333
  self.actionTransfer_Result.setObjectName("actionTransfer_Result")
334
334
  self.LoadBar.addAction(self.actionLoad_Data)
@@ -342,7 +342,7 @@ class Ui_MiSleep(object):
342
342
  self.SaveBar.addAction(self.actionSave_Annotation)
343
343
  self.SaveBar.addSeparator()
344
344
  self.AboutBar.addAction(self.actionAbout)
345
- self.ToolBar.addAction(self.actionMerge_Data)
345
+ self.ToolBar.addAction(self.actionState_Spectral)
346
346
  self.ToolBar.addSeparator()
347
347
  self.ToolBar.addAction(self.actionTransfer_Result)
348
348
  self.ToolBar.addSeparator()
@@ -404,7 +404,8 @@ class Ui_MiSleep(object):
404
404
  self.actionSave_data.setText(_translate("MiSleep", "Save Data"))
405
405
  self.actionSave_Annotation.setText(_translate("MiSleep", "Save Annotation"))
406
406
  self.actionAbout.setText(_translate("MiSleep", "About"))
407
- self.actionMerge_Data.setText(_translate("MiSleep", "Merge Data"))
407
+ self.actionState_Spectral.setText(_translate("MiSleep", "State Spectral"))
408
+ self.actionState_Spectral.setToolTip(_translate("MiSleep", "State Spectral"))
408
409
  self.actionTransfer_Result.setText(_translate("MiSleep", "Transfer Result"))
409
410
  self.actionTransfer_Result.setToolTip(_translate("MiSleep", "Transfer Result"))
410
411
  from misleep.gui.resources import misleep
@@ -0,0 +1,82 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # Form implementation generated from reading ui file 'misleep/gui/uis/state_spectral_dialog.ui'
4
+ #
5
+ # Created by: PyQt5 UI code generator 5.15.10
6
+ #
7
+ # WARNING: Any manual changes made to this file will be lost when pyuic5 is
8
+ # run again. Do not edit this file unless you know what you are doing.
9
+
10
+
11
+ from PyQt5 import QtCore, QtGui, QtWidgets
12
+
13
+
14
+ class Ui_StateSpectralDialog(object):
15
+ def setupUi(self, StateSpectralDialog):
16
+ StateSpectralDialog.setObjectName("StateSpectralDialog")
17
+ StateSpectralDialog.resize(261, 255)
18
+ self.gridLayout_2 = QtWidgets.QGridLayout(StateSpectralDialog)
19
+ self.gridLayout_2.setObjectName("gridLayout_2")
20
+ self.groupBox = QtWidgets.QGroupBox(StateSpectralDialog)
21
+ self.groupBox.setObjectName("groupBox")
22
+ self.gridLayout = QtWidgets.QGridLayout(self.groupBox)
23
+ self.gridLayout.setSpacing(10)
24
+ self.gridLayout.setObjectName("gridLayout")
25
+ self.label = QtWidgets.QLabel(self.groupBox)
26
+ self.label.setObjectName("label")
27
+ self.gridLayout.addWidget(self.label, 0, 0, 1, 1)
28
+ self.BPHigh = QtWidgets.QDoubleSpinBox(self.groupBox)
29
+ self.BPHigh.setDecimals(1)
30
+ self.BPHigh.setMaximum(10000.0)
31
+ self.BPHigh.setSingleStep(0.1)
32
+ self.BPHigh.setProperty("value", 30.0)
33
+ self.BPHigh.setObjectName("BPHigh")
34
+ self.gridLayout.addWidget(self.BPHigh, 5, 1, 1, 1)
35
+ self.BPFilterCheckBox = QtWidgets.QCheckBox(self.groupBox)
36
+ self.BPFilterCheckBox.setObjectName("BPFilterCheckBox")
37
+ self.gridLayout.addWidget(self.BPFilterCheckBox, 4, 0, 1, 1)
38
+ self.ChannelSelector = QtWidgets.QComboBox(self.groupBox)
39
+ self.ChannelSelector.setObjectName("ChannelSelector")
40
+ self.gridLayout.addWidget(self.ChannelSelector, 1, 0, 1, 2)
41
+ self.BPLow = QtWidgets.QDoubleSpinBox(self.groupBox)
42
+ self.BPLow.setDecimals(1)
43
+ self.BPLow.setMaximum(100000.0)
44
+ self.BPLow.setSingleStep(0.1)
45
+ self.BPLow.setProperty("value", 0.5)
46
+ self.BPLow.setObjectName("BPLow")
47
+ self.gridLayout.addWidget(self.BPLow, 5, 0, 1, 1)
48
+ self.RejectArtifactCheckBox = QtWidgets.QCheckBox(self.groupBox)
49
+ self.RejectArtifactCheckBox.setObjectName("RejectArtifactCheckBox")
50
+ self.gridLayout.addWidget(self.RejectArtifactCheckBox, 7, 0, 1, 1)
51
+ self.RelativeCheckBox = QtWidgets.QCheckBox(self.groupBox)
52
+ self.RelativeCheckBox.setObjectName("RelativeCheckBox")
53
+ self.gridLayout.addWidget(self.RelativeCheckBox, 6, 0, 1, 1)
54
+ self.MergeDataCheckBox = QtWidgets.QCheckBox(self.groupBox)
55
+ self.MergeDataCheckBox.setObjectName("MergeDataCheckBox")
56
+ self.gridLayout.addWidget(self.MergeDataCheckBox, 8, 0, 1, 1)
57
+ self.ArtThresholdSpinBox = QtWidgets.QDoubleSpinBox(self.groupBox)
58
+ self.ArtThresholdSpinBox.setDecimals(1)
59
+ self.ArtThresholdSpinBox.setObjectName("ArtThresholdSpinBox")
60
+ self.gridLayout.addWidget(self.ArtThresholdSpinBox, 7, 1, 1, 1)
61
+ self.gridLayout_2.addWidget(self.groupBox, 0, 0, 1, 2)
62
+ self.OKBt = QtWidgets.QPushButton(StateSpectralDialog)
63
+ self.OKBt.setObjectName("OKBt")
64
+ self.gridLayout_2.addWidget(self.OKBt, 1, 0, 1, 1)
65
+ self.CancelBt = QtWidgets.QPushButton(StateSpectralDialog)
66
+ self.CancelBt.setObjectName("CancelBt")
67
+ self.gridLayout_2.addWidget(self.CancelBt, 1, 1, 1, 1)
68
+
69
+ self.retranslateUi(StateSpectralDialog)
70
+ QtCore.QMetaObject.connectSlotsByName(StateSpectralDialog)
71
+
72
+ def retranslateUi(self, StateSpectralDialog):
73
+ _translate = QtCore.QCoreApplication.translate
74
+ StateSpectralDialog.setWindowTitle(_translate("StateSpectralDialog", "Dialog"))
75
+ self.groupBox.setTitle(_translate("StateSpectralDialog", "State spectral analysis options"))
76
+ self.label.setText(_translate("StateSpectralDialog", "Channel:"))
77
+ self.BPFilterCheckBox.setText(_translate("StateSpectralDialog", "Bandpass filter"))
78
+ self.RejectArtifactCheckBox.setText(_translate("StateSpectralDialog", "Reject artifact"))
79
+ self.RelativeCheckBox.setText(_translate("StateSpectralDialog", "Relative"))
80
+ self.MergeDataCheckBox.setText(_translate("StateSpectralDialog", "Merge data"))
81
+ self.OKBt.setText(_translate("StateSpectralDialog", "OK"))
82
+ self.CancelBt.setText(_translate("StateSpectralDialog", "Cancel"))