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.
- {accusleepy-0.4.0 → accusleepy-0.4.4}/PKG-INFO +24 -1
- {accusleepy-0.4.0 → accusleepy-0.4.4}/README.md +23 -0
- accusleepy-0.4.4/accusleepy/gui/images/primary_window.png +0 -0
- accusleepy-0.4.4/accusleepy/gui/images/viewer_window.png +0 -0
- accusleepy-0.4.4/accusleepy/gui/images/viewer_window_annotated.png +0 -0
- {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/main.py +16 -14
- {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/manual_scoring.py +14 -21
- accusleepy-0.4.0/accusleepy/gui/text/main_guide_text.py → accusleepy-0.4.4/accusleepy/gui/text/main_guide.md +77 -88
- accusleepy-0.4.4/accusleepy/gui/text/manual_scoring_guide.md +23 -0
- {accusleepy-0.4.0 → accusleepy-0.4.4}/pyproject.toml +1 -1
- accusleepy-0.4.0/accusleepy/gui/text/manual_scoring_guide.txt +0 -28
- {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/__init__.py +0 -0
- {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/__main__.py +0 -0
- {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/brain_state_set.py +0 -0
- {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/classification.py +0 -0
- {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/config.json +0 -0
- {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/constants.py +0 -0
- {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/fileio.py +0 -0
- {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/__init__.py +0 -0
- {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/icons/brightness_down.png +0 -0
- {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/icons/brightness_up.png +0 -0
- {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/icons/double_down_arrow.png +0 -0
- {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/icons/double_up_arrow.png +0 -0
- {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/icons/down_arrow.png +0 -0
- {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/icons/home.png +0 -0
- {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/icons/question.png +0 -0
- {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/icons/save.png +0 -0
- {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/icons/up_arrow.png +0 -0
- {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/icons/zoom_in.png +0 -0
- {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/icons/zoom_out.png +0 -0
- {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/mplwidget.py +0 -0
- {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/primary_window.py +0 -0
- {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/primary_window.ui +0 -0
- {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/resources.qrc +0 -0
- {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/resources_rc.py +0 -0
- {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/text/config_guide.txt +0 -0
- {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/viewer_window.py +0 -0
- {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/gui/viewer_window.ui +0 -0
- {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/models.py +0 -0
- {accusleepy-0.4.0 → accusleepy-0.4.4}/accusleepy/multitaper.py +0 -0
- {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.
|
|
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
|
+

|
|
79
|
+
|
|
80
|
+
Manual scoring interface
|
|
81
|
+

|
|
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
|
+

|
|
51
|
+
|
|
52
|
+
Manual scoring interface
|
|
53
|
+

|
|
54
|
+
|
|
32
55
|
## Acknowledgements
|
|
33
56
|
|
|
34
57
|
We would like to thank [Franz Weber](https://www.med.upenn.edu/weberlab/) for creating an
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -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 =
|
|
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.
|
|
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.
|
|
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 =
|
|
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
|
-
|
|
505
|
-
|
|
506
|
-
|
|
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
|
-
|
|
509
|
-
|
|
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
|
|
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.
|
|
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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
1.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
|
45
|
-
4.
|
|
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
|
|
57
|
-
the recordings that were used when training
|
|
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
|
|
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
|
|
69
|
-
Label file: a
|
|
70
|
-
with entries that are either the undefined brain state (
|
|
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
|
|
74
|
-
for details. These have
|
|
75
|
-
Trained classification model: required for
|
|
76
|
-
Section 4 for details. These have
|
|
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
|
|
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
|
|
87
|
-
existing label file, or click the
|
|
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
|
|
90
|
-
brain state
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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
|
|
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
|
-
|
|
108
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
146
|
-
model.
|
|
147
|
-
6.
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
168
|
-
on either side of the bout
|
|
169
|
-
6. Click
|
|
170
|
-
recording list.
|
|
171
|
-
the
|
|
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
|
+

|
|
@@ -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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|