accusleepy 0.3.1__py3-none-any.whl → 0.4.0__py3-none-any.whl

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.
accusleepy/gui/main.py CHANGED
@@ -5,6 +5,7 @@ import datetime
5
5
  import os
6
6
  import shutil
7
7
  import sys
8
+ import toml
8
9
  from dataclasses import dataclass
9
10
  from functools import partial
10
11
 
@@ -54,7 +55,7 @@ from accusleepy.signal_processing import (
54
55
  MESSAGE_BOX_MAX_DEPTH = 50
55
56
  LABEL_LENGTH_ERROR = "label file length does not match recording length"
56
57
  # relative path to config guide txt file
57
- CONFIG_GUIDE_FILE = "text/config_guide.txt"
58
+ CONFIG_GUIDE_FILE = os.path.normpath(r"text/config_guide.txt")
58
59
 
59
60
 
60
61
  @dataclass
@@ -116,6 +117,20 @@ class AccuSleepWindow(QtWidgets.QMainWindow):
116
117
  # messages to display
117
118
  self.messages = []
118
119
 
120
+ # display current version
121
+ version = ""
122
+ toml_file = os.path.join(
123
+ os.path.dirname(
124
+ os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
125
+ ),
126
+ "pyproject.toml",
127
+ )
128
+ if os.path.isfile(toml_file):
129
+ toml_data = toml.load(toml_file)
130
+ if "project" in toml_data and "version" in toml_data["project"]:
131
+ version = toml_data["project"]["version"]
132
+ self.ui.version_label.setText(f"v{version}")
133
+
119
134
  # user input: keyboard shortcuts
120
135
  keypress_quit = QtGui.QShortcut(
121
136
  QtGui.QKeySequence(
@@ -179,6 +194,7 @@ class AccuSleepWindow(QtWidgets.QMainWindow):
179
194
  )
180
195
  if not filename:
181
196
  return
197
+ filename = os.path.normpath(filename)
182
198
  save_recording_list(filename=filename, recordings=self.recordings)
183
199
  self.show_message(f"Saved list of recordings to {filename}")
184
200
 
@@ -193,6 +209,7 @@ class AccuSleepWindow(QtWidgets.QMainWindow):
193
209
  if file_dialog.exec():
194
210
  selected_files = file_dialog.selectedFiles()
195
211
  filename = selected_files[0]
212
+ filename = os.path.normpath(filename)
196
213
  else:
197
214
  return
198
215
 
@@ -229,7 +246,7 @@ class AccuSleepWindow(QtWidgets.QMainWindow):
229
246
  if event.type() == QtCore.QEvent.Drop:
230
247
  urls = event.mimeData().urls()
231
248
  if len(urls) == 1:
232
- filename = urls[0].toLocalFile()
249
+ filename = os.path.normpath(urls[0].toLocalFile())
233
250
 
234
251
  if filename is None:
235
252
  return super().eventFilter(obj, event)
@@ -289,6 +306,8 @@ class AccuSleepWindow(QtWidgets.QMainWindow):
289
306
  )
290
307
  if not model_filename:
291
308
  self.show_message("Model training canceled, no filename given")
309
+ return
310
+ model_filename = os.path.normpath(model_filename)
292
311
 
293
312
  # create (probably temporary) image folder
294
313
  temp_image_dir = os.path.join(
@@ -363,6 +382,7 @@ class AccuSleepWindow(QtWidgets.QMainWindow):
363
382
  self, "Select directory for training images"
364
383
  )
365
384
  if training_folder_parent:
385
+ training_folder_parent = os.path.normpath(training_folder_parent)
366
386
  self.training_image_dir = training_folder_parent
367
387
  self.ui.image_folder_label.setText(training_folder_parent)
368
388
 
@@ -560,6 +580,7 @@ class AccuSleepWindow(QtWidgets.QMainWindow):
560
580
  if file_dialog.exec():
561
581
  selected_files = file_dialog.selectedFiles()
562
582
  filename = selected_files[0]
583
+ filename = os.path.normpath(filename)
563
584
  else:
564
585
  return
565
586
 
@@ -707,6 +728,7 @@ class AccuSleepWindow(QtWidgets.QMainWindow):
707
728
  )
708
729
  if not filename:
709
730
  return
731
+ filename = os.path.normpath(filename)
710
732
 
711
733
  create_calibration_file(
712
734
  filename=filename,
@@ -871,6 +893,7 @@ class AccuSleepWindow(QtWidgets.QMainWindow):
871
893
  filter="*" + LABEL_FILE_TYPE,
872
894
  )
873
895
  if filename:
896
+ filename = os.path.normpath(filename)
874
897
  self.recordings[self.recording_index].label_file = filename
875
898
  self.ui.label_file_label.setText(filename)
876
899
 
@@ -885,6 +908,7 @@ class AccuSleepWindow(QtWidgets.QMainWindow):
885
908
  if file_dialog.exec():
886
909
  selected_files = file_dialog.selectedFiles()
887
910
  filename = selected_files[0]
911
+ filename = os.path.normpath(filename)
888
912
  self.recordings[self.recording_index].label_file = filename
889
913
  self.ui.label_file_label.setText(filename)
890
914
 
@@ -899,6 +923,7 @@ class AccuSleepWindow(QtWidgets.QMainWindow):
899
923
  if file_dialog.exec():
900
924
  selected_files = file_dialog.selectedFiles()
901
925
  filename = selected_files[0]
926
+ filename = os.path.normpath(filename)
902
927
  self.recordings[self.recording_index].calibration_file = filename
903
928
  self.ui.calibration_file_label.setText(filename)
904
929
 
@@ -913,6 +938,7 @@ class AccuSleepWindow(QtWidgets.QMainWindow):
913
938
  if file_dialog.exec():
914
939
  selected_files = file_dialog.selectedFiles()
915
940
  filename = selected_files[0]
941
+ filename = os.path.normpath(filename)
916
942
  self.recordings[self.recording_index].recording_file = filename
917
943
  self.ui.recording_file_label.setText(filename)
918
944
 
@@ -1252,7 +1278,7 @@ def check_label_validity(
1252
1278
  sampling_rate: int | float,
1253
1279
  epoch_length: int | float,
1254
1280
  brain_state_set: BrainStateSet,
1255
- ) -> str:
1281
+ ) -> str | None:
1256
1282
  """Check whether a set of brain state labels is valid
1257
1283
 
1258
1284
  This returns an error message if a problem is found with the
@@ -1352,6 +1378,7 @@ def check_config_consistency(
1352
1378
  output.append(
1353
1379
  (
1354
1380
  "Warning: the epoch length used when training this model "
1381
+ f"({model_epoch_length} seconds) "
1355
1382
  "does not match the current epoch length setting."
1356
1383
  )
1357
1384
  )
@@ -27,7 +27,7 @@ LABEL_CMAP = np.concatenate(
27
27
  [np.array([[0, 0, 0, 0]]), plt.colormaps["tab10"](range(10))], axis=0
28
28
  )
29
29
  # relative path to user manual text file
30
- USER_MANUAL_FILE = "text/manual_scoring_guide.txt"
30
+ USER_MANUAL_FILE = os.path.normpath(r"text/manual_scoring_guide.txt")
31
31
 
32
32
  # constants used by callback functions
33
33
  # label formats
@@ -8,20 +8,8 @@
8
8
  ## WARNING! All changes made in this file will be lost when recompiling UI file!
9
9
  ################################################################################
10
10
 
11
- from PySide6.QtCore import (
12
- QCoreApplication,
13
- QMetaObject,
14
- QRect,
15
- QSize,
16
- Qt,
17
- )
18
- from PySide6.QtGui import (
19
- QBrush,
20
- QColor,
21
- QFont,
22
- QIcon,
23
- QPalette,
24
- )
11
+ from PySide6.QtCore import QCoreApplication, QMetaObject, QRect, QSize, Qt
12
+ from PySide6.QtGui import QBrush, QColor, QFont, QIcon, QPalette
25
13
  from PySide6.QtWidgets import (
26
14
  QCheckBox,
27
15
  QDoubleSpinBox,
@@ -202,6 +190,8 @@ class Ui_PrimaryWindow(object):
202
190
 
203
191
  self.left_scoring_vlayout.addWidget(self.recordinglistgroupbox)
204
192
 
193
+ self.logo_and_version_layout = QVBoxLayout()
194
+ self.logo_and_version_layout.setObjectName("logo_and_version_layout")
205
195
  self.logo_layout = QVBoxLayout()
206
196
  self.logo_layout.setObjectName("logo_layout")
207
197
  self.frame = QFrame(self.scoring_tab)
@@ -252,7 +242,24 @@ class Ui_PrimaryWindow(object):
252
242
 
253
243
  self.logo_layout.addWidget(self.frame)
254
244
 
255
- self.left_scoring_vlayout.addLayout(self.logo_layout)
245
+ self.logo_and_version_layout.addLayout(self.logo_layout)
246
+
247
+ self.version_label = QLabel(self.scoring_tab)
248
+ self.version_label.setObjectName("version_label")
249
+ sizePolicy3 = QSizePolicy(
250
+ QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Fixed
251
+ )
252
+ sizePolicy3.setHorizontalStretch(0)
253
+ sizePolicy3.setVerticalStretch(0)
254
+ sizePolicy3.setHeightForWidth(
255
+ self.version_label.sizePolicy().hasHeightForWidth()
256
+ )
257
+ self.version_label.setSizePolicy(sizePolicy3)
258
+ self.version_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
259
+
260
+ self.logo_and_version_layout.addWidget(self.version_label)
261
+
262
+ self.left_scoring_vlayout.addLayout(self.logo_and_version_layout)
256
263
 
257
264
  self.user_manual_layout = QHBoxLayout()
258
265
  self.user_manual_layout.setObjectName("user_manual_layout")
@@ -340,11 +347,6 @@ class Ui_PrimaryWindow(object):
340
347
  self.horizontalLayout.setObjectName("horizontalLayout")
341
348
  self.recording_file_button = QPushButton(self.selected_recording_groupbox)
342
349
  self.recording_file_button.setObjectName("recording_file_button")
343
- sizePolicy3 = QSizePolicy(
344
- QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Fixed
345
- )
346
- sizePolicy3.setHorizontalStretch(0)
347
- sizePolicy3.setVerticalStretch(0)
348
350
  sizePolicy3.setHeightForWidth(
349
351
  self.recording_file_button.sizePolicy().hasHeightForWidth()
350
352
  )
@@ -2217,9 +2219,23 @@ class Ui_PrimaryWindow(object):
2217
2219
  self.remove_button.setText(
2218
2220
  QCoreApplication.translate("PrimaryWindow", "remove", None)
2219
2221
  )
2222
+ # if QT_CONFIG(tooltip)
2223
+ self.export_button.setToolTip(
2224
+ QCoreApplication.translate(
2225
+ "PrimaryWindow", "Export recording list to file", None
2226
+ )
2227
+ )
2228
+ # endif // QT_CONFIG(tooltip)
2220
2229
  self.export_button.setText(
2221
2230
  QCoreApplication.translate("PrimaryWindow", "export", None)
2222
2231
  )
2232
+ # if QT_CONFIG(tooltip)
2233
+ self.import_button.setToolTip(
2234
+ QCoreApplication.translate(
2235
+ "PrimaryWindow", "Import recording list from file", None
2236
+ )
2237
+ )
2238
+ # endif // QT_CONFIG(tooltip)
2223
2239
  self.import_button.setText(
2224
2240
  QCoreApplication.translate("PrimaryWindow", "import", None)
2225
2241
  )
@@ -2232,6 +2248,9 @@ class Ui_PrimaryWindow(object):
2232
2248
  self.accusleepy1.setText(
2233
2249
  QCoreApplication.translate("PrimaryWindow", "AccuSleePy", None)
2234
2250
  )
2251
+ self.version_label.setText(
2252
+ QCoreApplication.translate("PrimaryWindow", "TextLabel", None)
2253
+ )
2235
2254
  # if QT_CONFIG(tooltip)
2236
2255
  self.user_manual_button.setToolTip(
2237
2256
  QCoreApplication.translate("PrimaryWindow", "User manual", None)
@@ -2246,6 +2265,13 @@ class Ui_PrimaryWindow(object):
2246
2265
  self.samplingratelabel.setText(
2247
2266
  QCoreApplication.translate("PrimaryWindow", "Sampling rate (Hz):", None)
2248
2267
  )
2268
+ # if QT_CONFIG(tooltip)
2269
+ self.recording_file_button.setToolTip(
2270
+ QCoreApplication.translate(
2271
+ "PrimaryWindow", "Select EEG+EMG recording", None
2272
+ )
2273
+ )
2274
+ # endif // QT_CONFIG(tooltip)
2249
2275
  self.recording_file_button.setText(
2250
2276
  QCoreApplication.translate("PrimaryWindow", "Select recording file", None)
2251
2277
  )
@@ -2288,10 +2314,24 @@ class Ui_PrimaryWindow(object):
2288
2314
  QCoreApplication.translate("PrimaryWindow", "Score manually", None)
2289
2315
  )
2290
2316
  self.manual_scoring_status.setText("")
2317
+ # if QT_CONFIG(tooltip)
2318
+ self.create_calibration_button.setToolTip(
2319
+ QCoreApplication.translate(
2320
+ "PrimaryWindow", "Create calibration file for this subject", None
2321
+ )
2322
+ )
2323
+ # endif // QT_CONFIG(tooltip)
2291
2324
  self.create_calibration_button.setText(
2292
2325
  QCoreApplication.translate("PrimaryWindow", "Create calibration file", None)
2293
2326
  )
2294
2327
  self.calibration_status.setText("")
2328
+ # if QT_CONFIG(tooltip)
2329
+ self.select_calibration_button.setToolTip(
2330
+ QCoreApplication.translate(
2331
+ "PrimaryWindow", "Load calibration file for this recording", None
2332
+ )
2333
+ )
2334
+ # endif // QT_CONFIG(tooltip)
2295
2335
  self.select_calibration_button.setText(
2296
2336
  QCoreApplication.translate("PrimaryWindow", "Select calibration file", None)
2297
2337
  )
@@ -2319,6 +2359,13 @@ class Ui_PrimaryWindow(object):
2319
2359
  "PrimaryWindow", "Minimum bout length (sec):", None
2320
2360
  )
2321
2361
  )
2362
+ # if QT_CONFIG(tooltip)
2363
+ self.load_model_button.setToolTip(
2364
+ QCoreApplication.translate(
2365
+ "PrimaryWindow", "Load a trained sleep scoring classifier", None
2366
+ )
2367
+ )
2368
+ # endif // QT_CONFIG(tooltip)
2322
2369
  self.load_model_button.setText(
2323
2370
  QCoreApplication.translate(
2324
2371
  "PrimaryWindow", "Load classification model", None
@@ -2346,6 +2393,13 @@ class Ui_PrimaryWindow(object):
2346
2393
  self.real_time_button.setText(
2347
2394
  QCoreApplication.translate("PrimaryWindow", "Real-time", None)
2348
2395
  )
2396
+ # if QT_CONFIG(tooltip)
2397
+ self.train_model_button.setToolTip(
2398
+ QCoreApplication.translate(
2399
+ "PrimaryWindow", "Begin training the classification model", None
2400
+ )
2401
+ )
2402
+ # endif // QT_CONFIG(tooltip)
2349
2403
  self.train_model_button.setText(
2350
2404
  QCoreApplication.translate(
2351
2405
  "PrimaryWindow", "Train classification model", None
@@ -2422,6 +2476,13 @@ class Ui_PrimaryWindow(object):
2422
2476
  self.label_17.setText(
2423
2477
  QCoreApplication.translate("PrimaryWindow", "Default epoch length:", None)
2424
2478
  )
2479
+ # if QT_CONFIG(tooltip)
2480
+ self.save_config_button.setToolTip(
2481
+ QCoreApplication.translate(
2482
+ "PrimaryWindow", "Save current configuration", None
2483
+ )
2484
+ )
2485
+ # endif // QT_CONFIG(tooltip)
2425
2486
  self.save_config_button.setText(
2426
2487
  QCoreApplication.translate("PrimaryWindow", "Save", None)
2427
2488
  )
@@ -263,6 +263,9 @@
263
263
  <verstretch>0</verstretch>
264
264
  </sizepolicy>
265
265
  </property>
266
+ <property name="toolTip">
267
+ <string>Export recording list to file</string>
268
+ </property>
266
269
  <property name="text">
267
270
  <string>export</string>
268
271
  </property>
@@ -276,6 +279,9 @@
276
279
  <verstretch>0</verstretch>
277
280
  </sizepolicy>
278
281
  </property>
282
+ <property name="toolTip">
283
+ <string>Import recording list from file</string>
284
+ </property>
279
285
  <property name="text">
280
286
  <string>import</string>
281
287
  </property>
@@ -287,132 +293,152 @@
287
293
  </widget>
288
294
  </item>
289
295
  <item>
290
- <layout class="QVBoxLayout" name="logo_layout">
296
+ <layout class="QVBoxLayout" name="logo_and_version_layout">
297
+ <item>
298
+ <layout class="QVBoxLayout" name="logo_layout">
299
+ <item>
300
+ <widget class="QFrame" name="frame">
301
+ <property name="sizePolicy">
302
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
303
+ <horstretch>0</horstretch>
304
+ <verstretch>0</verstretch>
305
+ </sizepolicy>
306
+ </property>
307
+ <property name="minimumSize">
308
+ <size>
309
+ <width>180</width>
310
+ <height>80</height>
311
+ </size>
312
+ </property>
313
+ <property name="styleSheet">
314
+ <string notr="true">background-color: transparent;</string>
315
+ </property>
316
+ <property name="frameShape">
317
+ <enum>QFrame::Shape::NoFrame</enum>
318
+ </property>
319
+ <property name="frameShadow">
320
+ <enum>QFrame::Shadow::Raised</enum>
321
+ </property>
322
+ <widget class="QLabel" name="accusleepy2">
323
+ <property name="geometry">
324
+ <rect>
325
+ <x>11</x>
326
+ <y>15</y>
327
+ <width>160</width>
328
+ <height>50</height>
329
+ </rect>
330
+ </property>
331
+ <property name="sizePolicy">
332
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
333
+ <horstretch>0</horstretch>
334
+ <verstretch>0</verstretch>
335
+ </sizepolicy>
336
+ </property>
337
+ <property name="font">
338
+ <font>
339
+ <pointsize>21</pointsize>
340
+ <italic>true</italic>
341
+ <bold>true</bold>
342
+ </font>
343
+ </property>
344
+ <property name="styleSheet">
345
+ <string notr="true">background-color: transparent;
346
+ color: rgb(130, 169, 68);</string>
347
+ </property>
348
+ <property name="text">
349
+ <string>AccuSleePy</string>
350
+ </property>
351
+ <property name="alignment">
352
+ <set>Qt::AlignmentFlag::AlignCenter</set>
353
+ </property>
354
+ </widget>
355
+ <widget class="QLabel" name="accusleepy3">
356
+ <property name="geometry">
357
+ <rect>
358
+ <x>13</x>
359
+ <y>17</y>
360
+ <width>160</width>
361
+ <height>50</height>
362
+ </rect>
363
+ </property>
364
+ <property name="sizePolicy">
365
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
366
+ <horstretch>0</horstretch>
367
+ <verstretch>0</verstretch>
368
+ </sizepolicy>
369
+ </property>
370
+ <property name="font">
371
+ <font>
372
+ <pointsize>21</pointsize>
373
+ <italic>true</italic>
374
+ <bold>true</bold>
375
+ </font>
376
+ </property>
377
+ <property name="styleSheet">
378
+ <string notr="true">background-color: transparent;
379
+ color: rgb(46, 63, 150);</string>
380
+ </property>
381
+ <property name="text">
382
+ <string>AccuSleePy</string>
383
+ </property>
384
+ <property name="alignment">
385
+ <set>Qt::AlignmentFlag::AlignCenter</set>
386
+ </property>
387
+ </widget>
388
+ <widget class="QLabel" name="accusleepy1">
389
+ <property name="geometry">
390
+ <rect>
391
+ <x>9</x>
392
+ <y>13</y>
393
+ <width>160</width>
394
+ <height>50</height>
395
+ </rect>
396
+ </property>
397
+ <property name="sizePolicy">
398
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
399
+ <horstretch>0</horstretch>
400
+ <verstretch>0</verstretch>
401
+ </sizepolicy>
402
+ </property>
403
+ <property name="font">
404
+ <font>
405
+ <pointsize>21</pointsize>
406
+ <italic>true</italic>
407
+ <bold>true</bold>
408
+ </font>
409
+ </property>
410
+ <property name="styleSheet">
411
+ <string notr="true">background-color: transparent;
412
+ color: rgb(244, 195, 68);</string>
413
+ </property>
414
+ <property name="text">
415
+ <string>AccuSleePy</string>
416
+ </property>
417
+ <property name="alignment">
418
+ <set>Qt::AlignmentFlag::AlignCenter</set>
419
+ </property>
420
+ </widget>
421
+ <zorder>accusleepy1</zorder>
422
+ <zorder>accusleepy2</zorder>
423
+ <zorder>accusleepy3</zorder>
424
+ </widget>
425
+ </item>
426
+ </layout>
427
+ </item>
291
428
  <item>
292
- <widget class="QFrame" name="frame">
429
+ <widget class="QLabel" name="version_label">
293
430
  <property name="sizePolicy">
294
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
431
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
295
432
  <horstretch>0</horstretch>
296
433
  <verstretch>0</verstretch>
297
434
  </sizepolicy>
298
435
  </property>
299
- <property name="minimumSize">
300
- <size>
301
- <width>180</width>
302
- <height>80</height>
303
- </size>
304
- </property>
305
- <property name="styleSheet">
306
- <string notr="true">background-color: transparent;</string>
307
- </property>
308
- <property name="frameShape">
309
- <enum>QFrame::Shape::NoFrame</enum>
436
+ <property name="text">
437
+ <string>TextLabel</string>
310
438
  </property>
311
- <property name="frameShadow">
312
- <enum>QFrame::Shadow::Raised</enum>
439
+ <property name="alignment">
440
+ <set>Qt::AlignmentFlag::AlignCenter</set>
313
441
  </property>
314
- <widget class="QLabel" name="accusleepy2">
315
- <property name="geometry">
316
- <rect>
317
- <x>11</x>
318
- <y>15</y>
319
- <width>160</width>
320
- <height>50</height>
321
- </rect>
322
- </property>
323
- <property name="sizePolicy">
324
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
325
- <horstretch>0</horstretch>
326
- <verstretch>0</verstretch>
327
- </sizepolicy>
328
- </property>
329
- <property name="font">
330
- <font>
331
- <pointsize>21</pointsize>
332
- <italic>true</italic>
333
- <bold>true</bold>
334
- </font>
335
- </property>
336
- <property name="styleSheet">
337
- <string notr="true">background-color: transparent;
338
- color: rgb(130, 169, 68);</string>
339
- </property>
340
- <property name="text">
341
- <string>AccuSleePy</string>
342
- </property>
343
- <property name="alignment">
344
- <set>Qt::AlignmentFlag::AlignCenter</set>
345
- </property>
346
- </widget>
347
- <widget class="QLabel" name="accusleepy3">
348
- <property name="geometry">
349
- <rect>
350
- <x>13</x>
351
- <y>17</y>
352
- <width>160</width>
353
- <height>50</height>
354
- </rect>
355
- </property>
356
- <property name="sizePolicy">
357
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
358
- <horstretch>0</horstretch>
359
- <verstretch>0</verstretch>
360
- </sizepolicy>
361
- </property>
362
- <property name="font">
363
- <font>
364
- <pointsize>21</pointsize>
365
- <italic>true</italic>
366
- <bold>true</bold>
367
- </font>
368
- </property>
369
- <property name="styleSheet">
370
- <string notr="true">background-color: transparent;
371
- color: rgb(46, 63, 150);</string>
372
- </property>
373
- <property name="text">
374
- <string>AccuSleePy</string>
375
- </property>
376
- <property name="alignment">
377
- <set>Qt::AlignmentFlag::AlignCenter</set>
378
- </property>
379
- </widget>
380
- <widget class="QLabel" name="accusleepy1">
381
- <property name="geometry">
382
- <rect>
383
- <x>9</x>
384
- <y>13</y>
385
- <width>160</width>
386
- <height>50</height>
387
- </rect>
388
- </property>
389
- <property name="sizePolicy">
390
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
391
- <horstretch>0</horstretch>
392
- <verstretch>0</verstretch>
393
- </sizepolicy>
394
- </property>
395
- <property name="font">
396
- <font>
397
- <pointsize>21</pointsize>
398
- <italic>true</italic>
399
- <bold>true</bold>
400
- </font>
401
- </property>
402
- <property name="styleSheet">
403
- <string notr="true">background-color: transparent;
404
- color: rgb(244, 195, 68);</string>
405
- </property>
406
- <property name="text">
407
- <string>AccuSleePy</string>
408
- </property>
409
- <property name="alignment">
410
- <set>Qt::AlignmentFlag::AlignCenter</set>
411
- </property>
412
- </widget>
413
- <zorder>accusleepy1</zorder>
414
- <zorder>accusleepy2</zorder>
415
- <zorder>accusleepy3</zorder>
416
442
  </widget>
417
443
  </item>
418
444
  </layout>
@@ -562,6 +588,9 @@ color: rgb(244, 195, 68);</string>
562
588
  <verstretch>0</verstretch>
563
589
  </sizepolicy>
564
590
  </property>
591
+ <property name="toolTip">
592
+ <string>Select EEG+EMG recording</string>
593
+ </property>
565
594
  <property name="text">
566
595
  <string>Select recording file</string>
567
596
  </property>
@@ -753,6 +782,9 @@ color: rgb(244, 195, 68);</string>
753
782
  <verstretch>0</verstretch>
754
783
  </sizepolicy>
755
784
  </property>
785
+ <property name="toolTip">
786
+ <string>Create calibration file for this subject</string>
787
+ </property>
756
788
  <property name="text">
757
789
  <string>Create calibration file</string>
758
790
  </property>
@@ -813,6 +845,9 @@ color: rgb(244, 195, 68);</string>
813
845
  <verstretch>0</verstretch>
814
846
  </sizepolicy>
815
847
  </property>
848
+ <property name="toolTip">
849
+ <string>Load calibration file for this recording</string>
850
+ </property>
816
851
  <property name="text">
817
852
  <string>Select calibration file</string>
818
853
  </property>
@@ -1042,6 +1077,9 @@ color: rgb(244, 195, 68);</string>
1042
1077
  <verstretch>0</verstretch>
1043
1078
  </sizepolicy>
1044
1079
  </property>
1080
+ <property name="toolTip">
1081
+ <string>Load a trained sleep scoring classifier</string>
1082
+ </property>
1045
1083
  <property name="text">
1046
1084
  <string>Load classification model</string>
1047
1085
  </property>
@@ -1296,6 +1334,9 @@ color: rgb(244, 195, 68);</string>
1296
1334
  <verstretch>0</verstretch>
1297
1335
  </sizepolicy>
1298
1336
  </property>
1337
+ <property name="toolTip">
1338
+ <string>Begin training the classification model</string>
1339
+ </property>
1299
1340
  <property name="text">
1300
1341
  <string>Train classification model</string>
1301
1342
  </property>
@@ -3553,6 +3594,9 @@ color: rgb(244, 195, 68);</string>
3553
3594
  <verstretch>0</verstretch>
3554
3595
  </sizepolicy>
3555
3596
  </property>
3597
+ <property name="toolTip">
3598
+ <string>Save current configuration</string>
3599
+ </property>
3556
3600
  <property name="text">
3557
3601
  <string>Save</string>
3558
3602
  </property>
@@ -1,5 +1,4 @@
1
1
  This is the current brain state configuration.
2
- You can also choose the default epoch length.
3
2
  If you make changes, click 'Save' to store them.
4
3
 
5
4
  Each brain state has several attributes:
@@ -26,3 +25,5 @@ Important notes:
26
25
  - Changing these settings can invalidate existing label files,
27
26
  calibration files, and trained models!
28
27
  - Reinstalling AccuSleePy will overwrite this configuration.
28
+ - You can also choose the default epoch length that is shown
29
+ when the primary interface starts up.
@@ -1,11 +1,31 @@
1
- from accusleepy.constants import BRAIN_STATE_COL, EEG_COL, EMG_COL, UNDEFINED_LABEL
1
+ from accusleepy.constants import (
2
+ BRAIN_STATE_COL,
3
+ CALIBRATION_FILE_TYPE,
4
+ EEG_COL,
5
+ EMG_COL,
6
+ LABEL_FILE_TYPE,
7
+ MODEL_FILE_TYPE,
8
+ RECORDING_FILE_TYPES,
9
+ UNDEFINED_LABEL,
10
+ )
2
11
 
3
12
  MAIN_GUIDE_TEXT = f"""
13
+ Section 0: Definitions
4
14
  Section 1: Overview of the GUI
5
15
  Section 2: AccuSleePy file types
6
16
  Section 3: Manually assigning brain state labels
7
17
  Section 4: Automatically assigning brain state labels
8
18
 
19
+ -----------------------------------------------------------------------
20
+ Section 0: Definitions
21
+ -----------------------------------------------------------------------
22
+ Recording: a table containing one channel of EEG data and one channel
23
+ of EMG data collected at a constant sampling rate.
24
+ Epoch: the temporal resolution of brain state scoring. If, for example,
25
+ the epoch length is 5 seconds, then a brain state label will be
26
+ assigned to each 5-second segment of a recording.
27
+ Bout: a contiguous set of epochs with the same brain state.
28
+
9
29
  -----------------------------------------------------------------------
10
30
  Section 1: Overview of the primary interface
11
31
  -----------------------------------------------------------------------
@@ -43,17 +63,17 @@ There are four types of files associated with AccuSleePy.
43
63
  To select a file in the primary interface, you can either use the
44
64
  associated button, or drag/drop the file into the empty box adjacent
45
65
  to the button.
46
- Recording file: a .csv or .parquet file containing one column of EEG
47
- data and one column of EMG data. The column names must be
48
- {EEG_COL} and {EMG_COL}.
49
- Label file: a .csv file with one column titled {BRAIN_STATE_COL}
50
- with entries that are either the undefined brain state, {UNDEFINED_LABEL},
66
+ Recording file: a {" or ".join(RECORDING_FILE_TYPES)} file containing one
67
+ column of EEG data and one column of EMG data.
68
+ The column names must be {EEG_COL} and {EMG_COL}.
69
+ Label file: a {LABEL_FILE_TYPE} file with one column titled {BRAIN_STATE_COL}
70
+ with entries that are either the undefined brain state ({UNDEFINED_LABEL})
51
71
  or one of the digits in your brain state configuration.
52
72
  By default, these are 1-3 where REM = 1, wake = 2, NREM = 3.
53
73
  Calibration data file: required for automatic labeling. See Section 4
54
- for details. These have .csv format.
74
+ for details. These have {CALIBRATION_FILE_TYPE} format.
55
75
  Trained classification model: required for automatic labeling. See
56
- Section 4 for details. These have .pth format.
76
+ Section 4 for details. These have {MODEL_FILE_TYPE} format.
57
77
 
58
78
  -----------------------------------------------------------------------
59
79
  Section 3: Manually assigning brain state labels
@@ -103,6 +123,10 @@ To create a calibration data file:
103
123
  4. Enter a filename for the calibration data file.
104
124
  5. The calibration file will automatically be assigned to the currently
105
125
  selected recording.
126
+ Note that epoch length can affect the calibration process. If you make
127
+ a calibration file for a subject using one epoch length, but want to
128
+ score another recording from the same subject with a different epoch
129
+ length, it's best to create a new calibration file.
106
130
 
107
131
  --- Section 4B: Training your own classification model ---
108
132
  To train a new model on your own data:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: accusleepy
3
- Version: 0.3.1
3
+ Version: 0.4.0
4
4
  Summary: Python implementation of AccuSleep
5
5
  License: GPL-3.0-only
6
6
  Author: Zeke Barger
@@ -20,6 +20,7 @@ Requires-Dist: pillow (>=11.1.0,<12.0.0)
20
20
  Requires-Dist: pre-commit (>=4.2.0,<5.0.0)
21
21
  Requires-Dist: pyside6 (>=6.7.1,<6.8.0)
22
22
  Requires-Dist: scipy (>=1.15.2,<2.0.0)
23
+ Requires-Dist: toml (>=0.10.2,<0.11.0)
23
24
  Requires-Dist: torch (>=2.6.0,<3.0.0)
24
25
  Requires-Dist: torchvision (>=0.21.0,<0.22.0)
25
26
  Requires-Dist: tqdm (>=4.67.1,<5.0.0)
@@ -17,21 +17,21 @@ accusleepy/gui/icons/save.png,sha256=J3EA8iU1BqLYRSsrq_OdoZlqrv2yfL7oV54DklTy_DI
17
17
  accusleepy/gui/icons/up_arrow.png,sha256=V9yF9t1WgjPaUu-mF1YGe_DfaRHg2dUpR_sUVVcvVvY,3329
18
18
  accusleepy/gui/icons/zoom_in.png,sha256=MFWnKZp7Rvh4bLPq4Cqo4sB_jQYedUUtT8-ZO8tNYyc,13589
19
19
  accusleepy/gui/icons/zoom_out.png,sha256=IB8Jecb3i0U4qjWRR46ridjLpvLCSe7PozBaLqQqYSw,13055
20
- accusleepy/gui/main.py,sha256=IGhSD9vSTO09H72Ou1icbujQfzCy1twTCdeR2Dv8I7s,53055
21
- accusleepy/gui/manual_scoring.py,sha256=Jfu7uxXk6W4mmq81h4LnLSArP735l0XvbuZq9yYG650,40686
20
+ accusleepy/gui/main.py,sha256=r6NWxwWkkkOOeXDfKggrGA6d8d3RS0M4Ylf2HhtnoPk,54234
21
+ accusleepy/gui/manual_scoring.py,sha256=RaOpFso9whXib3MfiZblGJoTS-_dehBnSA-rtvO0qBo,40705
22
22
  accusleepy/gui/mplwidget.py,sha256=f9O3u_96whQGUwpi3o_QGc7yjiETX5vE0oj3ePXTJWE,12279
23
- accusleepy/gui/primary_window.py,sha256=eK9yrU6PK5hX1RORjc7DvqCDuDt55iA1LylXp3oh0j8,101850
24
- accusleepy/gui/primary_window.ui,sha256=NqCSnvlC1mKrWNn034u8avpMF7WudlR8G5jLjFNdTmk,144812
23
+ accusleepy/gui/primary_window.py,sha256=RXpDvcb7zy8Ea4Da1VhMG1T6GC54KW3vyGjqqQJN45k,104582
24
+ accusleepy/gui/primary_window.ui,sha256=09k4xFcjgOL9mlhFlg6mXCc_tgj4_FY9CZ3H03e3z3A,147074
25
25
  accusleepy/gui/resources.qrc,sha256=ByNEmJqr0YbKBqoZGvONZtjyNYr4ST4enO6TEdYSqWg,802
26
26
  accusleepy/gui/resources_rc.py,sha256=Z2e34h30U4snJjnYdZVV9B6yjATKxxfvgTRt5uXtQdo,329727
27
- accusleepy/gui/text/config_guide.txt,sha256=wz2QtRgd1eXUZMmtfAIVgqvDOtjkOnTOK-IGkLALg4U,1073
28
- accusleepy/gui/text/main_guide_text.py,sha256=YP-2sexvU5VIeKc1FXHsG0cUCgGfcU4qLD59JRlOMMo,8038
27
+ accusleepy/gui/text/config_guide.txt,sha256=7xyo5ifQjWgXmCdgHuei0DCsXZcU4vo5VRlpOb2KVs4,1130
28
+ accusleepy/gui/text/main_guide_text.py,sha256=4WpPYpuXCX811roitKuEI68dWIBNFrNrMyiKO2u8xyY,9050
29
29
  accusleepy/gui/text/manual_scoring_guide.txt,sha256=onBnUZJyX18oN1CgjD2HSnlEQHsUscHpOYf11kTKZ4U,1460
30
30
  accusleepy/gui/viewer_window.py,sha256=5PkbuYMXUegH1CExCoqSGDZ9GeJqCCUz0-3WWkM8Vfc,24049
31
31
  accusleepy/gui/viewer_window.ui,sha256=D1LwUFR-kZ_GWGZFFtXvGJdFWghLrOWZTblQeLQt9kI,30525
32
32
  accusleepy/models.py,sha256=Muapsw088AUHqRIbW97Rkbv0oiwCtQvO9tEoBCC-MYg,1476
33
33
  accusleepy/multitaper.py,sha256=V6MJDk0OSWhg2MFhrnt9dvYrHiNsk2T7IxAA7paZVyE,25549
34
34
  accusleepy/signal_processing.py,sha256=-aXnywfp1LBsk3DcbIMmZlgv3f8j6sZ6js0bizZId0o,21718
35
- accusleepy-0.3.1.dist-info/METADATA,sha256=xgwUR8pWzqQp3fi_g6UXCVbvxrL3CdVahoq476bIEaQ,2729
36
- accusleepy-0.3.1.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
37
- accusleepy-0.3.1.dist-info/RECORD,,
35
+ accusleepy-0.4.0.dist-info/METADATA,sha256=QRIDk41bldqfRDcdCoQCVnVk4GkcwHSpV1cQm8dmRdI,2768
36
+ accusleepy-0.4.0.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
37
+ accusleepy-0.4.0.dist-info/RECORD,,