accusleepy 0.4.0__tar.gz → 0.4.4__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 (41) hide show
  1. {accusleepy-0.4.0 → accusleepy-0.4.4}/PKG-INFO +24 -1
  2. {accusleepy-0.4.0 → accusleepy-0.4.4}/README.md +23 -0
  3. accusleepy-0.4.4/accusleepy/gui/images/primary_window.png +0 -0
  4. accusleepy-0.4.4/accusleepy/gui/images/viewer_window.png +0 -0
  5. accusleepy-0.4.4/accusleepy/gui/images/viewer_window_annotated.png +0 -0
  6. {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/main.py +16 -14
  7. {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/manual_scoring.py +14 -21
  8. accusleepy-0.4.0/accusleepy/gui/text/main_guide_text.py → accusleepy-0.4.4/accusleepy/gui/text/main_guide.md +77 -88
  9. accusleepy-0.4.4/accusleepy/gui/text/manual_scoring_guide.md +23 -0
  10. {accusleepy-0.4.0 → accusleepy-0.4.4}/pyproject.toml +1 -1
  11. accusleepy-0.4.0/accusleepy/gui/text/manual_scoring_guide.txt +0 -28
  12. {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/__init__.py +0 -0
  13. {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/__main__.py +0 -0
  14. {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/brain_state_set.py +0 -0
  15. {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/classification.py +0 -0
  16. {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/config.json +0 -0
  17. {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/constants.py +0 -0
  18. {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/fileio.py +0 -0
  19. {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/__init__.py +0 -0
  20. {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/icons/brightness_down.png +0 -0
  21. {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/icons/brightness_up.png +0 -0
  22. {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/icons/double_down_arrow.png +0 -0
  23. {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/icons/double_up_arrow.png +0 -0
  24. {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/icons/down_arrow.png +0 -0
  25. {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/icons/home.png +0 -0
  26. {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/icons/question.png +0 -0
  27. {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/icons/save.png +0 -0
  28. {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/icons/up_arrow.png +0 -0
  29. {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/icons/zoom_in.png +0 -0
  30. {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/icons/zoom_out.png +0 -0
  31. {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/mplwidget.py +0 -0
  32. {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/primary_window.py +0 -0
  33. {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/primary_window.ui +0 -0
  34. {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/resources.qrc +0 -0
  35. {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/resources_rc.py +0 -0
  36. {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/text/config_guide.txt +0 -0
  37. {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/viewer_window.py +0 -0
  38. {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/viewer_window.ui +0 -0
  39. {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/models.py +0 -0
  40. {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/multitaper.py +0 -0
  41. {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/signal_processing.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: accusleepy
3
- Version: 0.4.0
3
+ Version: 0.4.4
4
4
  Summary: Python implementation of AccuSleep
5
5
  License: GPL-3.0-only
6
6
  Author: Zeke Barger
@@ -43,6 +43,18 @@ The data and models associated with AccuSleep are available at https://osf.io/py
43
43
 
44
44
  Please contact zekebarger (at) gmail (dot) com with any questions or comments about the software.
45
45
 
46
+ ## What's new
47
+
48
+ AccuSleePy offers the following improvements over the MATLAB version:
49
+
50
+ - Up to 10 brain states can be configured through the user interface
51
+ - Models can be trained through the user interface
52
+ - Model files contain useful metadata (brain state configuration,
53
+ epoch length, number of epochs)
54
+ - Models optimized for real-time scoring can be trained
55
+ - Lists of recordings can be imported and exported for repeatable batch processing
56
+ - Undo/redo functionality in the manual scoring interface
57
+
46
58
  ## Installation
47
59
 
48
60
  - (recommended) create a new virtual environment (using
@@ -57,6 +69,17 @@ etc.) using python >=3.10,<3.13
57
69
 
58
70
  `python -m accusleepy` will open the primary interface.
59
71
 
72
+ [Guide to the primary interface](accusleepy/gui/text/main_guide.md)
73
+
74
+ [Guide to the manual scoring interface](accusleepy/gui/text/manual_scoring_guide.md)
75
+
76
+ ## Screenshots
77
+ Primary interface
78
+ ![AccuSleePy primary interface](accusleepy/gui/images/primary_window.png)
79
+
80
+ Manual scoring interface
81
+ ![AccuSleePy manual scoring interface](accusleepy/gui/images/viewer_window.png)
82
+
60
83
  ## Acknowledgements
61
84
 
62
85
  We would like to thank [Franz Weber](https://www.med.upenn.edu/weberlab/) for creating an
@@ -15,6 +15,18 @@ The data and models associated with AccuSleep are available at https://osf.io/py
15
15
 
16
16
  Please contact zekebarger (at) gmail (dot) com with any questions or comments about the software.
17
17
 
18
+ ## What's new
19
+
20
+ AccuSleePy offers the following improvements over the MATLAB version:
21
+
22
+ - Up to 10 brain states can be configured through the user interface
23
+ - Models can be trained through the user interface
24
+ - Model files contain useful metadata (brain state configuration,
25
+ epoch length, number of epochs)
26
+ - Models optimized for real-time scoring can be trained
27
+ - Lists of recordings can be imported and exported for repeatable batch processing
28
+ - Undo/redo functionality in the manual scoring interface
29
+
18
30
  ## Installation
19
31
 
20
32
  - (recommended) create a new virtual environment (using
@@ -29,6 +41,17 @@ etc.) using python >=3.10,<3.13
29
41
 
30
42
  `python -m accusleepy` will open the primary interface.
31
43
 
44
+ [Guide to the primary interface](accusleepy/gui/text/main_guide.md)
45
+
46
+ [Guide to the manual scoring interface](accusleepy/gui/text/manual_scoring_guide.md)
47
+
48
+ ## Screenshots
49
+ Primary interface
50
+ ![AccuSleePy primary interface](accusleepy/gui/images/primary_window.png)
51
+
52
+ Manual scoring interface
53
+ ![AccuSleePy manual scoring interface](accusleepy/gui/images/viewer_window.png)
54
+
32
55
  ## Acknowledgements
33
56
 
34
57
  We would like to thank [Franz Weber](https://www.med.upenn.edu/weberlab/) for creating an
@@ -41,7 +41,6 @@ from accusleepy.fileio import (
41
41
  save_model,
42
42
  save_recording_list,
43
43
  )
44
- from accusleepy.gui.text.main_guide_text import MAIN_GUIDE_TEXT
45
44
  from accusleepy.gui.manual_scoring import ManualScoringWindow
46
45
  from accusleepy.gui.primary_window import Ui_PrimaryWindow
47
46
  from accusleepy.signal_processing import (
@@ -52,10 +51,11 @@ from accusleepy.signal_processing import (
52
51
  )
53
52
 
54
53
  # max number of messages to display
55
- MESSAGE_BOX_MAX_DEPTH = 50
54
+ MESSAGE_BOX_MAX_DEPTH = 200
56
55
  LABEL_LENGTH_ERROR = "label file length does not match recording length"
57
56
  # relative path to config guide txt file
58
57
  CONFIG_GUIDE_FILE = os.path.normpath(r"text/config_guide.txt")
58
+ MAIN_GUIDE_FILE = os.path.normpath(r"text/main_guide.md")
59
59
 
60
60
 
61
61
  @dataclass
@@ -294,7 +294,7 @@ class AccuSleepWindow(QtWidgets.QMainWindow):
294
294
  error_message = self.check_single_file_inputs(recording_index)
295
295
  if error_message:
296
296
  self.show_message(
297
- f"ERROR ({self.recordings[recording_index].name}): {error_message}"
297
+ f"ERROR (recording {self.recordings[recording_index].name}): {error_message}"
298
298
  )
299
299
  return
300
300
 
@@ -431,7 +431,7 @@ class AccuSleepWindow(QtWidgets.QMainWindow):
431
431
  f"error on recording {self.recordings[recording_index].name}"
432
432
  )
433
433
  self.show_message(
434
- f"ERROR ({self.recordings[recording_index].name}): {error_message}"
434
+ f"ERROR (recording {self.recordings[recording_index].name}): {error_message}"
435
435
  )
436
436
  return
437
437
  if self.recordings[recording_index].calibration_file == "":
@@ -440,7 +440,7 @@ class AccuSleepWindow(QtWidgets.QMainWindow):
440
440
  )
441
441
  self.show_message(
442
442
  (
443
- f"ERROR ({self.recordings[recording_index].name}): "
443
+ f"ERROR (recording {self.recordings[recording_index].name}): "
444
444
  "no calibration file selected"
445
445
  )
446
446
  )
@@ -752,7 +752,7 @@ class AccuSleepWindow(QtWidgets.QMainWindow):
752
752
  self.recordings[self.recording_index].calibration_file = filename
753
753
  self.ui.calibration_file_label.setText(filename)
754
754
 
755
- def check_single_file_inputs(self, recording_index: int) -> str:
755
+ def check_single_file_inputs(self, recording_index: int) -> str | None:
756
756
  """Check that a recording's inputs appear valid
757
757
 
758
758
  This runs some basic tests for whether it will be possible to
@@ -772,6 +772,8 @@ class AccuSleepWindow(QtWidgets.QMainWindow):
772
772
  return "invalid epoch length or sampling rate"
773
773
  if self.recordings[self.recording_index].recording_file == "":
774
774
  return "no recording selected"
775
+ if not os.path.isfile(self.recordings[self.recording_index].recording_file):
776
+ return "recording file does not exist"
775
777
  if self.recordings[self.recording_index].label_file == "":
776
778
  return "no label file selected"
777
779
 
@@ -1031,15 +1033,15 @@ class AccuSleepWindow(QtWidgets.QMainWindow):
1031
1033
 
1032
1034
  def show_user_manual(self) -> None:
1033
1035
  """Show a popup window with the user manual"""
1034
- label_widget = QtWidgets.QLabel()
1035
- label_widget.setText(MAIN_GUIDE_TEXT)
1036
- scroll_area = QtWidgets.QScrollArea()
1037
- scroll_area.setStyleSheet("background-color: white;")
1038
- scroll_area.setWidget(label_widget)
1039
- grid = QtWidgets.QGridLayout()
1040
- grid.addWidget(scroll_area)
1041
1036
  self.popup = QtWidgets.QWidget()
1042
- self.popup.setLayout(grid)
1037
+ self.popup_vlayout = QtWidgets.QVBoxLayout(self.popup)
1038
+ self.guide_textbox = QtWidgets.QTextBrowser(self.popup)
1039
+ self.popup_vlayout.addWidget(self.guide_textbox)
1040
+
1041
+ url = QtCore.QUrl.fromLocalFile(MAIN_GUIDE_FILE)
1042
+ self.guide_textbox.setSource(url)
1043
+ self.guide_textbox.setOpenLinks(False)
1044
+
1043
1045
  self.popup.setGeometry(QtCore.QRect(100, 100, 600, 600))
1044
1046
  self.popup.show()
1045
1047
 
@@ -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 = os.path.normpath(r"text/manual_scoring_guide.txt")
30
+ USER_MANUAL_FILE = os.path.normpath(r"text/manual_scoring_guide.md")
31
31
 
32
32
  # constants used by callback functions
33
33
  # label formats
@@ -61,7 +61,7 @@ UNDEFINED_STATE = "undefined"
61
61
  # before starting to scroll again - must be in (0, 0.5)
62
62
  SCROLL_BOUNDARY = 0.35
63
63
  # max number of sequential undo actions allowed
64
- UNDO_LIMIT = 100
64
+ UNDO_LIMIT = 1000
65
65
 
66
66
 
67
67
  @dataclass
@@ -446,8 +446,6 @@ class ManualScoringWindow(QtWidgets.QDialog):
446
446
  self.label_img = create_label_img(
447
447
  self.display_labels, self.label_display_options
448
448
  )
449
- # update the plots
450
- self.update_figures()
451
449
 
452
450
  def redo(self) -> None:
453
451
  """Redo the last change to brain state labels that was undone"""
@@ -501,21 +499,18 @@ class ManualScoringWindow(QtWidgets.QDialog):
501
499
 
502
500
  def show_user_manual(self) -> None:
503
501
  """Show a popup window with the user manual"""
504
- user_manual_file = open(
505
- os.path.join(os.path.dirname(os.path.abspath(__file__)), USER_MANUAL_FILE),
506
- "r",
502
+ self.popup = QtWidgets.QWidget()
503
+ self.popup_vlayout = QtWidgets.QVBoxLayout(self.popup)
504
+ self.guide_textbox = QtWidgets.QTextBrowser(self.popup)
505
+ self.popup_vlayout.addWidget(self.guide_textbox)
506
+
507
+ url = QtCore.QUrl.fromLocalFile(
508
+ os.path.join(os.path.dirname(os.path.abspath(__file__)), USER_MANUAL_FILE)
507
509
  )
508
- user_manual_text = user_manual_file.read()
509
- user_manual_file.close()
510
- label_widget = QtWidgets.QLabel()
511
- label_widget.setText(user_manual_text)
512
- label_widget.setStyleSheet("background-color: white;")
510
+ self.guide_textbox.setSource(url)
511
+ self.guide_textbox.setOpenLinks(False)
513
512
 
514
- self.popup = QtWidgets.QWidget()
515
- grid = QtWidgets.QGridLayout()
516
- grid.addWidget(label_widget)
517
- self.popup.setLayout(grid)
518
- self.popup.setGeometry(QtCore.QRect(50, 100, 350, 400))
513
+ self.popup.setGeometry(QtCore.QRect(100, 100, 830, 600))
519
514
  self.popup.show()
520
515
 
521
516
  def jump_to_next_state(self, direction: str, target: str) -> None:
@@ -719,7 +714,6 @@ class ManualScoringWindow(QtWidgets.QDialog):
719
714
  self.ui.upperfigure.canvas.axes[2].set_xlim(
720
715
  (self.upper_left_epoch, self.upper_right_epoch + 1)
721
716
  )
722
- self.ui.upperfigure.canvas.draw()
723
717
 
724
718
  def zoom_x(self, direction: str) -> None:
725
719
  """Change upper figure x-axis zoom level
@@ -757,6 +751,7 @@ class ManualScoringWindow(QtWidgets.QDialog):
757
751
  self.upper_left_epoch = 0
758
752
  self.upper_right_epoch = self.n_epochs - 1
759
753
  self.adjust_upper_figure_x_limits()
754
+ self.ui.upperfigure.canvas.draw()
760
755
 
761
756
  def modify_current_epoch_label(self, digit: int) -> None:
762
757
  """Change the current epoch's brain state label
@@ -977,8 +972,6 @@ class ManualScoringWindow(QtWidgets.QDialog):
977
972
  else:
978
973
  self.upper_left_epoch = self.epoch - upper_epoch_padding
979
974
  self.upper_right_epoch = self.epoch + upper_epoch_padding
980
- # update upper marker
981
- self.update_upper_marker()
982
975
  self.adjust_upper_figure_x_limits()
983
976
 
984
977
  # update lower figure x-axis range
@@ -993,7 +986,7 @@ class ManualScoringWindow(QtWidgets.QDialog):
993
986
  self.lower_left_epoch = self.epoch - lower_epoch_padding
994
987
  self.lower_right_epoch = self.epoch + lower_epoch_padding
995
988
 
996
- self.update_lower_figure()
989
+ self.update_figures()
997
990
 
998
991
 
999
992
  def convert_labels(labels: np.array, style: str) -> np.array:
@@ -1,48 +1,31 @@
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
- )
11
-
12
- MAIN_GUIDE_TEXT = f"""
13
- Section 0: Definitions
14
- Section 1: Overview of the GUI
15
- Section 2: AccuSleePy file types
16
- Section 3: Manually assigning brain state labels
17
- Section 4: Automatically assigning brain state labels
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,
1
+ # Definitions
2
+ - Recording: a table containing one channel of electroencephalogram (EEG)
3
+ data and one channel of electromyogram (EMG) data collected at a
4
+ constant sampling rate.
5
+ - Epoch: the temporal resolution of brain state scoring. If, for example,
25
6
  the epoch length is 5 seconds, then a brain state label will be
26
7
  assigned to each 5-second segment of a recording.
27
- Bout: a contiguous set of epochs with the same brain state.
28
-
29
- -----------------------------------------------------------------------
30
- Section 1: Overview of the primary interface
31
- -----------------------------------------------------------------------
32
- This interface allows a user to assign brain state labels to 1-channel
33
- electroencephalogram (EEG) and electromyogram (EMG) data.
34
- The overall workflow looks like this:
35
- 1. Enter the epoch length for all recordings. This determines the time
36
- resolution of the brain state labels.
37
- 2. For each of your recordings, add to the recording list, enter its
38
- sampling rate, load the EEG/EMG data, and determine where to save
39
- the brain state labels (or load the labels if they already exist)
8
+ - Bout: a contiguous set of epochs with the same brain state.
9
+
10
+
11
+ # 1. Overview of the primary interface
12
+
13
+ The workflow for sleep scoring is as follows:
14
+ 1. Set the epoch length
15
+ 2. For each of your recordings:
16
+ 1. create a new entry in the list of recordings
17
+ 2. enter the sampling rate
18
+ 3. select the recording file containing the EEG and EMG data
19
+ 4. choose a filename for saving the brain state labels,
20
+ or select an existing label file
21
+
40
22
  At this point, you can score the recordings manually.
23
+
41
24
  3. For each recording, create a calibration file using a small amount
42
25
  of labeled data, or choose a calibration file created using
43
26
  another recording from the same subject and under the same recording
44
- conditions (i.e., equipment)
45
- 4. Choose a trained classification model file with a matching epoch size
27
+ conditions
28
+ 4. Select a trained classification model file with the correct epoch length
46
29
  5. Score all recordings automatically using the classifier
47
30
 
48
31
  By default, there are three brain state options: REM, wake, and NREM.
@@ -53,49 +36,46 @@ classification model.
53
36
 
54
37
  Use the "import" and "export" buttons to load or save a list of
55
38
  recordings. This can be useful if you need to re-score a set of
56
- recordings with a different model, or if you want to keep a record of
57
- the recordings that were used when training your model.
39
+ recordings with a new model, or if you want to keep a record of
40
+ the recordings that were used when training a model.
58
41
 
59
- -----------------------------------------------------------------------
60
- Section 2: AccuSleePy file types
61
- -----------------------------------------------------------------------
42
+ # 2. AccuSleePy file types
62
43
  There are four types of files associated with AccuSleePy.
63
44
  To select a file in the primary interface, you can either use the
64
45
  associated button, or drag/drop the file into the empty box adjacent
65
46
  to the button.
66
- Recording file: a {" or ".join(RECORDING_FILE_TYPES)} file containing one
47
+ - Recording file: a .parquet or .csv file containing one
67
48
  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})
49
+ The column names must be eeg and emg.
50
+ - Label file: a .csv file with one column titled brain_state
51
+ with entries that are either the undefined brain state (by default, this is -1)
71
52
  or one of the digits in your brain state configuration.
72
53
  By default, these are 1-3 where REM = 1, wake = 2, NREM = 3.
73
- Calibration data file: required for automatic labeling. See Section 4
74
- for details. These have {CALIBRATION_FILE_TYPE} format.
75
- Trained classification model: required for automatic labeling. See
76
- Section 4 for details. These have {MODEL_FILE_TYPE} format.
77
-
78
- -----------------------------------------------------------------------
79
- Section 3: Manually assigning brain state labels
80
- -----------------------------------------------------------------------
54
+ - Calibration data file: required for automated scoring. See Section 4
55
+ for details. These have .csv format.
56
+ - Trained classification model: required for automated scoring. See
57
+ Section 4 for details. These have .pth format.
58
+
59
+ # 3. Manually assigning brain state labels
81
60
  1. Select the recording you wish to modify from the recording list, or
82
61
  add a new one.
83
- 2. Click the 'Select recording file' button to set the location of the
62
+ 2. Click the "Select recording file" button to set the location of the
84
63
  EEG/EMG data, or drag/drop the recording file into the box next
85
64
  to the button.
86
- 3. Click the 'Select' label file button (or drag/drop) to choose an
87
- existing label file, or click the 'create' label file button to
65
+ 3. Click the "Select" label file button (or drag/drop) to choose an
66
+ existing label file, or click the "create" label file button to
88
67
  enter the filename for a new label file.
89
- 4. Click 'Score manually' to launch an interactive window for manual
90
- brain state labeling. Close the window when you are finished.
91
- This interface has many useful keyboard shortcuts, so it's recommended
92
- to consult its user manual.
93
-
94
- -----------------------------------------------------------------------
95
- Section 4: Automatically scoring recordings with a classification model
96
- -----------------------------------------------------------------------
68
+ 4. Click "Score manually" to launch an interactive window for manual
69
+ brain state scoring. When you are finished, save your changes and
70
+ close the window.
71
+
72
+ The manual scoring interface has many useful keyboard shortcuts,
73
+ so please consult its user manual by clicking the question mark icon.
74
+
75
+ # 4. Automatically scoring recordings with a classification model
97
76
  Automatic brain state scoring requires the inputs described in
98
- Section 3, as well as calibration data files and a trained classifier.
77
+ Section 3, as well as calibration data files and a trained classification
78
+ model.
99
79
  If you already have all of these files, proceed to Section 4C.
100
80
  Models trained on the AccuSleep dataset are provided at
101
81
  https://osf.io/py5eb under /python_format/models/ for epoch lengths of
@@ -104,14 +84,18 @@ they use several epochs of data before and after any given epoch when
104
84
  scoring that epoch. (The other model type, called "real-time", only
105
85
  uses data from the current epoch and several preceding epochs.)
106
86
 
107
- --- Section 4A: Creating calibration data files ---
108
- Each recording must have a calibration file assigned to it.
87
+ ## 4A. Creating calibration data files
88
+
89
+ In order to perform automated sleep scoring,
90
+ each recording must have a calibration file assigned to it.
109
91
  This file lets AccuSleep transform features of the EEG and EMG data so
110
92
  that they are in the same range as the classifier's training data.
111
93
  You can use the same calibration file for multiple recordings, as long
112
94
  as they come from the same subject and were collected under the same
113
95
  recording conditions (i.e., the same recording equipment was used).
96
+
114
97
  To create a calibration data file:
98
+
115
99
  1. Ensure you have a file containing brain state labels. You can create
116
100
  this file by following the steps in Section 3, or select an
117
101
  existing label file.
@@ -119,20 +103,23 @@ To create a calibration data file:
119
103
  stage (e.g., REM, wakefulness, and NREM). It is recommended to
120
104
  label at least several minutes of each stage, and more labels can
121
105
  improve classification accuracy.
122
- 3. Click 'Create calibration file'.
106
+ 3. Click "Create calibration file".
123
107
  4. Enter a filename for the calibration data file.
124
108
  5. The calibration file will automatically be assigned to the currently
125
109
  selected recording.
110
+
126
111
  Note that epoch length can affect the calibration process. If you make
127
112
  a calibration file for a subject using one epoch length, but want to
128
113
  score another recording from the same subject with a different epoch
129
114
  length, it's best to create a new calibration file.
130
115
 
131
- --- Section 4B: Training your own classification model ---
116
+ ## 4B. Training your own classification model
117
+
132
118
  To train a new model on your own data:
119
+
133
120
  1. Add your scored recordings to the recording list. Make sure the
134
121
  sampling rate, recording file, and label file are set for each
135
- recording.
122
+ recording. Calibration files are not required.
136
123
  2. Click the "Model training" tab
137
124
  3. Choose the number of epochs to consider when scoring each epoch.
138
125
  This will be the "width" of the training images. For "default"
@@ -142,32 +129,34 @@ To train a new model on your own data:
142
129
  deleted once training is complete. (It's generally best to
143
130
  leave this box checked.)
144
131
  5. Choose whether to create a "default" or "real-time"-type model.
145
- Note that scoring recordings in the GUI requires a default-type
146
- model.
147
- 6. Select a directory where the training images will be saved. A
132
+ Note that scoring recordings in the primary interface requires
133
+ a default-type model.
134
+ 6. Click "Set training image directory" to select the location
135
+ where the images used to train the model will be saved. A
148
136
  new directory with an automatically generated name will be
149
137
  created inside the directory you choose.
150
- 7. Click the "Train classification model" button and enter a
138
+ 7. Click "Train classification model" and enter a
151
139
  filename for the trained model. Training can take some time.
140
+ The console will display progress updates.
141
+
142
+ ## 4C. Automatic scoring
143
+
144
+ Instructions for automatic scoring using this interface are below.
152
145
 
153
- --- Section 4C: Automatic labeling ---
154
- Instructions for automatic labeling using this GUI are below.
155
146
  1. Set the epoch length for all recordings.
156
147
  2. Select the recording file, label file, and calibration file to use
157
148
  for each recording. See section 4A for instructions on creating
158
149
  calibration files.
159
- 3. Click 'Load classification model' to load the trained classification
150
+ 3. Click "Load classification model" to load the trained classification
160
151
  model. It's important that the epoch length used when training this
161
152
  model is the same as the current epoch length.
162
153
  4. If you wish to preserve any existing labels in the label file, and
163
154
  only overwrite undefined epochs, check the box labeled
164
- 'Only overwrite undefined epochs'.
155
+ "Only overwrite undefined epochs".
165
156
  5. Set the minimum bout length, in seconds. A typical value could be 5.
166
157
  Following automatic labeling, any brain state bout shorter than this
167
- duration will be reassigned to the surrounding stage (if the stages
168
- on either side of the bout match).
169
- 6. Click 'Score all automatically' to score all recordings in the
170
- recording list. Labels will be saved to the file specified by
171
- the 'Select or create label file' field of each recording. You can
172
- click 'Score manually' to visualize the results.
173
- """
158
+ duration will be reassigned to the surrounding state (if the states
159
+ on either side of the bout are the same).
160
+ 6. Click "Score all automatically" to score all recordings in the
161
+ recording list. To inspect the results, select a recording
162
+ in the list and click "Score manually".
@@ -0,0 +1,23 @@
1
+ # Manual scoring interface
2
+
3
+ Keyboard shortcuts:
4
+ - Mouse click on the upper 3 plots: jump to epoch
5
+ - Ctrl + S: save labels to file
6
+ - Right / left arrow: move one epoch forward / backward in time
7
+ - Numbers 0-9: set current epoch to this brain state
8
+ - Backspace: set current epoch to the undefined state
9
+ - Ctrl + Z: undo last change to brain state labels
10
+ - Ctrl + Y: redo last change to brain state labels
11
+ - Shift + (number 0-9, or backspace):
12
+ After pressing this combination, click and drag on the upper plot of brain
13
+ state labels to set the selected epochs
14
+ to this brain state. Press Escape to cancel.
15
+ - Plus (+): zoom in (upper panel x-axis)
16
+ - Minus (-): zoom out (upper panel x-axis)
17
+ - Shift + right / left arrow: jump to the next / previous epoch with a different brain state
18
+ than the current epoch
19
+ - Spacebar: equivalent to shift + right arrow
20
+ - Ctrl + right / left arrow: jump to the next / preceding undefined epoch
21
+ - Ctrl + W: quit
22
+
23
+ ![ ](../images/viewer_window_annotated.png)
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "accusleepy"
3
- version = "0.4.0"
3
+ version = "0.4.4"
4
4
  description = "Python implementation of AccuSleep"
5
5
  authors = [
6
6
  {name = "Zeke Barger",email = "zekebarger@gmail.com"}
@@ -1,28 +0,0 @@
1
- The lower panel shows a zoomed-in subset of the epochs shown in the upper panel.
2
- The red diamond in the upper panel and the red lines in the lower panel
3
- mark the currently selected epoch.
4
- The red horizontal line in the upper panel indicates the epochs shown in the lower panel.
5
- Click a location on the upper panel to jump to that epoch.
6
- The buttons next to the spectrogram control the zoom level and intensity.
7
- The buttons next to the EEG and EMG plots control the zoom level and y-axis offset.
8
- If "auto-scroll" is enabled, modifying the brain state of the current epoch
9
- will automatically select the next epoch.
10
-
11
- Keyboard shortcuts:
12
- Ctrl + S: save labels to file
13
- Right arrow: move one epoch forward in time
14
- Left arrow: move one epoch backward in time
15
- Numbers 0-9: set current epoch to this brain state
16
- Backspace: set current epoch to undefined
17
- Ctrl + Z: undo last change to brain state labels
18
- Ctrl + Y: redo last change to brain state labels
19
- Shift + (number 0-9, or backspace):
20
- Click and drag on the upper plot of brain state labels to set the selected epochs
21
- to the desired brain state. Press Esc to cancel.
22
- +: zoom in (upper panel x-axis)
23
- -: zoom out (upper panel x-axis)
24
- Shift + right arrow, or space: jump to the next epoch of a different state
25
- than the current epoch
26
- Shift + left arrow: jump to the preceding epoch of a different state than the current epoch
27
- Ctrl + right/left arrow: jump to the next/preceding undefined epoch
28
- Ctrl + W: quit