accusleepy 0.1.2__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/config.json +3 -2
- accusleepy/constants.py +2 -0
- accusleepy/fileio.py +14 -6
- accusleepy/gui/main.py +54 -32
- accusleepy/gui/manual_scoring.py +3 -3
- accusleepy/gui/primary_window.py +138 -7
- accusleepy/gui/primary_window.ui +241 -119
- accusleepy/gui/text/config_guide.txt +3 -1
- accusleepy/gui/text/{main_guide.txt → main_guide_text.py} +52 -21
- {accusleepy-0.1.2.dist-info → accusleepy-0.4.0.dist-info}/METADATA +10 -5
- {accusleepy-0.1.2.dist-info → accusleepy-0.4.0.dist-info}/RECORD +12 -12
- {accusleepy-0.1.2.dist-info → accusleepy-0.4.0.dist-info}/WHEEL +0 -0
accusleepy/config.json
CHANGED
accusleepy/constants.py
CHANGED
accusleepy/fileio.py
CHANGED
|
@@ -11,6 +11,7 @@ from accusleepy.brain_state_set import BRAIN_STATES_KEY, BrainState, BrainStateS
|
|
|
11
11
|
from accusleepy.constants import (
|
|
12
12
|
BRAIN_STATE_COL,
|
|
13
13
|
CONFIG_FILE,
|
|
14
|
+
DEFAULT_EPOCH_LENGTH_KEY,
|
|
14
15
|
EEG_COL,
|
|
15
16
|
EMG_COL,
|
|
16
17
|
MIXTURE_MEAN_COL,
|
|
@@ -82,7 +83,9 @@ def load_model(filename: str) -> tuple[SSANN, int | float, int, str, dict]:
|
|
|
82
83
|
(default or real-time), set of brain state options
|
|
83
84
|
used when training the model
|
|
84
85
|
"""
|
|
85
|
-
state_dict = torch.load(
|
|
86
|
+
state_dict = torch.load(
|
|
87
|
+
filename, weights_only=True, map_location=torch.device("cpu")
|
|
88
|
+
)
|
|
86
89
|
epoch_length = state_dict.pop("epoch_length")
|
|
87
90
|
epochs_per_img = state_dict.pop("epochs_per_img")
|
|
88
91
|
model_type = state_dict.pop("model_type")
|
|
@@ -141,10 +144,10 @@ def save_labels(labels: np.array, filename: str) -> None:
|
|
|
141
144
|
pd.DataFrame({BRAIN_STATE_COL: labels}).to_csv(filename, index=False)
|
|
142
145
|
|
|
143
146
|
|
|
144
|
-
def load_config() -> BrainStateSet:
|
|
147
|
+
def load_config() -> tuple[BrainStateSet, int | float]:
|
|
145
148
|
"""Load configuration file with brain state options
|
|
146
149
|
|
|
147
|
-
:return: set of brain state options
|
|
150
|
+
:return: set of brain state options and default epoch length
|
|
148
151
|
"""
|
|
149
152
|
with open(
|
|
150
153
|
os.path.join(os.path.dirname(os.path.abspath(__file__)), CONFIG_FILE), "r"
|
|
@@ -152,18 +155,23 @@ def load_config() -> BrainStateSet:
|
|
|
152
155
|
data = json.load(f)
|
|
153
156
|
return BrainStateSet(
|
|
154
157
|
[BrainState(**b) for b in data[BRAIN_STATES_KEY]], UNDEFINED_LABEL
|
|
155
|
-
)
|
|
158
|
+
), data[DEFAULT_EPOCH_LENGTH_KEY]
|
|
156
159
|
|
|
157
160
|
|
|
158
|
-
def save_config(
|
|
161
|
+
def save_config(
|
|
162
|
+
brain_state_set: BrainStateSet, default_epoch_length: int | float
|
|
163
|
+
) -> None:
|
|
159
164
|
"""Save configuration of brain state options to json file
|
|
160
165
|
|
|
161
166
|
:param brain_state_set: set of brain state options
|
|
167
|
+
:param default_epoch_length: epoch length to use when the GUI starts
|
|
162
168
|
"""
|
|
169
|
+
output_dict = brain_state_set.to_output_dict()
|
|
170
|
+
output_dict.update({DEFAULT_EPOCH_LENGTH_KEY: default_epoch_length})
|
|
163
171
|
with open(
|
|
164
172
|
os.path.join(os.path.dirname(os.path.abspath(__file__)), CONFIG_FILE), "w"
|
|
165
173
|
) as f:
|
|
166
|
-
json.dump(
|
|
174
|
+
json.dump(output_dict, f, indent=4)
|
|
167
175
|
|
|
168
176
|
|
|
169
177
|
def load_recording_list(filename: str) -> list[Recording]:
|
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
|
|
|
@@ -40,6 +41,7 @@ from accusleepy.fileio import (
|
|
|
40
41
|
save_model,
|
|
41
42
|
save_recording_list,
|
|
42
43
|
)
|
|
44
|
+
from accusleepy.gui.text.main_guide_text import MAIN_GUIDE_TEXT
|
|
43
45
|
from accusleepy.gui.manual_scoring import ManualScoringWindow
|
|
44
46
|
from accusleepy.gui.primary_window import Ui_PrimaryWindow
|
|
45
47
|
from accusleepy.signal_processing import (
|
|
@@ -52,9 +54,8 @@ from accusleepy.signal_processing import (
|
|
|
52
54
|
# max number of messages to display
|
|
53
55
|
MESSAGE_BOX_MAX_DEPTH = 50
|
|
54
56
|
LABEL_LENGTH_ERROR = "label file length does not match recording length"
|
|
55
|
-
# relative path to
|
|
56
|
-
|
|
57
|
-
CONFIG_GUIDE_FILE = "text/config_guide.txt"
|
|
57
|
+
# relative path to config guide txt file
|
|
58
|
+
CONFIG_GUIDE_FILE = os.path.normpath(r"text/config_guide.txt")
|
|
58
59
|
|
|
59
60
|
|
|
60
61
|
@dataclass
|
|
@@ -80,12 +81,12 @@ class AccuSleepWindow(QtWidgets.QMainWindow):
|
|
|
80
81
|
self.setWindowTitle("AccuSleePy")
|
|
81
82
|
|
|
82
83
|
# fill in settings tab
|
|
83
|
-
self.brain_state_set = load_config()
|
|
84
|
+
self.brain_state_set, self.epoch_length = load_config()
|
|
84
85
|
self.settings_widgets = None
|
|
85
86
|
self.initialize_settings_tab()
|
|
86
87
|
|
|
87
88
|
# initialize info about the recordings, classification data / settings
|
|
88
|
-
self.epoch_length
|
|
89
|
+
self.ui.epoch_length_input.setValue(self.epoch_length)
|
|
89
90
|
self.model = None
|
|
90
91
|
self.only_overwrite_undefined = False
|
|
91
92
|
self.min_bout_length = 5
|
|
@@ -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,24 +306,31 @@ 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)
|
|
311
|
+
|
|
312
|
+
# create (probably temporary) image folder
|
|
313
|
+
temp_image_dir = os.path.join(
|
|
314
|
+
self.training_image_dir,
|
|
315
|
+
"images_" + datetime.datetime.now().strftime("%Y%m%d%H%M"),
|
|
316
|
+
)
|
|
292
317
|
|
|
293
|
-
#
|
|
294
|
-
if os.path.exists(self.training_image_dir):
|
|
318
|
+
if os.path.exists(temp_image_dir): # unlikely
|
|
295
319
|
self.show_message(
|
|
296
320
|
"Warning: training image folder exists, will be overwritten"
|
|
297
321
|
)
|
|
298
|
-
os.makedirs(
|
|
322
|
+
os.makedirs(temp_image_dir, exist_ok=True)
|
|
299
323
|
|
|
300
324
|
# create training images
|
|
301
325
|
self.show_message(
|
|
302
|
-
(f"Creating training images in {
|
|
326
|
+
(f"Creating training images in {temp_image_dir}, please wait...")
|
|
303
327
|
)
|
|
304
328
|
self.ui.message_area.repaint()
|
|
305
329
|
QtWidgets.QApplication.processEvents()
|
|
306
330
|
print("Creating training images")
|
|
307
331
|
failed_recordings = create_training_images(
|
|
308
332
|
recordings=self.recordings,
|
|
309
|
-
output_path=
|
|
333
|
+
output_path=temp_image_dir,
|
|
310
334
|
epoch_length=self.epoch_length,
|
|
311
335
|
epochs_per_img=self.training_epochs_per_img,
|
|
312
336
|
brain_state_set=self.brain_state_set,
|
|
@@ -330,10 +354,8 @@ class AccuSleepWindow(QtWidgets.QMainWindow):
|
|
|
330
354
|
QtWidgets.QApplication.processEvents()
|
|
331
355
|
print("Training model")
|
|
332
356
|
model = train_model(
|
|
333
|
-
annotations_file=os.path.join(
|
|
334
|
-
|
|
335
|
-
),
|
|
336
|
-
img_dir=self.training_image_dir,
|
|
357
|
+
annotations_file=os.path.join(temp_image_dir, ANNOTATIONS_FILENAME),
|
|
358
|
+
img_dir=temp_image_dir,
|
|
337
359
|
mixture_weights=self.brain_state_set.mixture_weights,
|
|
338
360
|
n_classes=self.brain_state_set.n_classes,
|
|
339
361
|
)
|
|
@@ -350,20 +372,19 @@ class AccuSleepWindow(QtWidgets.QMainWindow):
|
|
|
350
372
|
|
|
351
373
|
# optionally delete images
|
|
352
374
|
if self.delete_training_images:
|
|
353
|
-
shutil.rmtree(
|
|
375
|
+
shutil.rmtree(temp_image_dir)
|
|
354
376
|
|
|
355
377
|
self.show_message(f"Training complete, saved model to {model_filename}")
|
|
356
378
|
|
|
357
|
-
def set_training_folder(self):
|
|
379
|
+
def set_training_folder(self) -> None:
|
|
380
|
+
"""Select location in which to create a folder for training images"""
|
|
358
381
|
training_folder_parent = QtWidgets.QFileDialog.getExistingDirectory(
|
|
359
382
|
self, "Select directory for training images"
|
|
360
383
|
)
|
|
361
384
|
if training_folder_parent:
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
)
|
|
366
|
-
self.ui.image_folder_label.setText(self.training_image_dir)
|
|
385
|
+
training_folder_parent = os.path.normpath(training_folder_parent)
|
|
386
|
+
self.training_image_dir = training_folder_parent
|
|
387
|
+
self.ui.image_folder_label.setText(training_folder_parent)
|
|
367
388
|
|
|
368
389
|
def update_image_deletion(self) -> None:
|
|
369
390
|
"""Update choice of whether to delete images after training"""
|
|
@@ -559,6 +580,7 @@ class AccuSleepWindow(QtWidgets.QMainWindow):
|
|
|
559
580
|
if file_dialog.exec():
|
|
560
581
|
selected_files = file_dialog.selectedFiles()
|
|
561
582
|
filename = selected_files[0]
|
|
583
|
+
filename = os.path.normpath(filename)
|
|
562
584
|
else:
|
|
563
585
|
return
|
|
564
586
|
|
|
@@ -706,6 +728,7 @@ class AccuSleepWindow(QtWidgets.QMainWindow):
|
|
|
706
728
|
)
|
|
707
729
|
if not filename:
|
|
708
730
|
return
|
|
731
|
+
filename = os.path.normpath(filename)
|
|
709
732
|
|
|
710
733
|
create_calibration_file(
|
|
711
734
|
filename=filename,
|
|
@@ -870,6 +893,7 @@ class AccuSleepWindow(QtWidgets.QMainWindow):
|
|
|
870
893
|
filter="*" + LABEL_FILE_TYPE,
|
|
871
894
|
)
|
|
872
895
|
if filename:
|
|
896
|
+
filename = os.path.normpath(filename)
|
|
873
897
|
self.recordings[self.recording_index].label_file = filename
|
|
874
898
|
self.ui.label_file_label.setText(filename)
|
|
875
899
|
|
|
@@ -884,6 +908,7 @@ class AccuSleepWindow(QtWidgets.QMainWindow):
|
|
|
884
908
|
if file_dialog.exec():
|
|
885
909
|
selected_files = file_dialog.selectedFiles()
|
|
886
910
|
filename = selected_files[0]
|
|
911
|
+
filename = os.path.normpath(filename)
|
|
887
912
|
self.recordings[self.recording_index].label_file = filename
|
|
888
913
|
self.ui.label_file_label.setText(filename)
|
|
889
914
|
|
|
@@ -898,6 +923,7 @@ class AccuSleepWindow(QtWidgets.QMainWindow):
|
|
|
898
923
|
if file_dialog.exec():
|
|
899
924
|
selected_files = file_dialog.selectedFiles()
|
|
900
925
|
filename = selected_files[0]
|
|
926
|
+
filename = os.path.normpath(filename)
|
|
901
927
|
self.recordings[self.recording_index].calibration_file = filename
|
|
902
928
|
self.ui.calibration_file_label.setText(filename)
|
|
903
929
|
|
|
@@ -912,6 +938,7 @@ class AccuSleepWindow(QtWidgets.QMainWindow):
|
|
|
912
938
|
if file_dialog.exec():
|
|
913
939
|
selected_files = file_dialog.selectedFiles()
|
|
914
940
|
filename = selected_files[0]
|
|
941
|
+
filename = os.path.normpath(filename)
|
|
915
942
|
self.recordings[self.recording_index].recording_file = filename
|
|
916
943
|
self.ui.recording_file_label.setText(filename)
|
|
917
944
|
|
|
@@ -1004,15 +1031,8 @@ class AccuSleepWindow(QtWidgets.QMainWindow):
|
|
|
1004
1031
|
|
|
1005
1032
|
def show_user_manual(self) -> None:
|
|
1006
1033
|
"""Show a popup window with the user manual"""
|
|
1007
|
-
user_manual_file = open(
|
|
1008
|
-
os.path.join(os.path.dirname(os.path.abspath(__file__)), USER_MANUAL_FILE),
|
|
1009
|
-
"r",
|
|
1010
|
-
)
|
|
1011
|
-
user_manual_text = user_manual_file.read()
|
|
1012
|
-
user_manual_file.close()
|
|
1013
|
-
|
|
1014
1034
|
label_widget = QtWidgets.QLabel()
|
|
1015
|
-
label_widget.setText(
|
|
1035
|
+
label_widget.setText(MAIN_GUIDE_TEXT)
|
|
1016
1036
|
scroll_area = QtWidgets.QScrollArea()
|
|
1017
1037
|
scroll_area.setStyleSheet("background-color: white;")
|
|
1018
1038
|
scroll_area.setWidget(label_widget)
|
|
@@ -1110,6 +1130,7 @@ class AccuSleepWindow(QtWidgets.QMainWindow):
|
|
|
1110
1130
|
}
|
|
1111
1131
|
|
|
1112
1132
|
# update widget state to display current config
|
|
1133
|
+
self.ui.default_epoch_input.setValue(self.epoch_length)
|
|
1113
1134
|
states = {b.digit: b for b in self.brain_state_set.brain_states}
|
|
1114
1135
|
for digit in range(10):
|
|
1115
1136
|
if digit in states.keys():
|
|
@@ -1247,7 +1268,7 @@ class AccuSleepWindow(QtWidgets.QMainWindow):
|
|
|
1247
1268
|
self.brain_state_set = BrainStateSet(brain_states, UNDEFINED_LABEL)
|
|
1248
1269
|
|
|
1249
1270
|
# save to file
|
|
1250
|
-
save_config(self.brain_state_set)
|
|
1271
|
+
save_config(self.brain_state_set, self.ui.default_epoch_input.value())
|
|
1251
1272
|
self.ui.save_config_status.setText("configuration saved")
|
|
1252
1273
|
|
|
1253
1274
|
|
|
@@ -1257,7 +1278,7 @@ def check_label_validity(
|
|
|
1257
1278
|
sampling_rate: int | float,
|
|
1258
1279
|
epoch_length: int | float,
|
|
1259
1280
|
brain_state_set: BrainStateSet,
|
|
1260
|
-
) -> str:
|
|
1281
|
+
) -> str | None:
|
|
1261
1282
|
"""Check whether a set of brain state labels is valid
|
|
1262
1283
|
|
|
1263
1284
|
This returns an error message if a problem is found with the
|
|
@@ -1357,6 +1378,7 @@ def check_config_consistency(
|
|
|
1357
1378
|
output.append(
|
|
1358
1379
|
(
|
|
1359
1380
|
"Warning: the epoch length used when training this model "
|
|
1381
|
+
f"({model_epoch_length} seconds) "
|
|
1360
1382
|
"does not match the current epoch length setting."
|
|
1361
1383
|
)
|
|
1362
1384
|
)
|
accusleepy/gui/manual_scoring.py
CHANGED
|
@@ -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
|
|
@@ -111,7 +111,7 @@ class ManualScoringWindow(QtWidgets.QDialog):
|
|
|
111
111
|
self.setWindowTitle("AccuSleePy manual scoring window")
|
|
112
112
|
|
|
113
113
|
# load set of valid brain states
|
|
114
|
-
self.brain_state_set = load_config()
|
|
114
|
+
self.brain_state_set, _ = load_config()
|
|
115
115
|
|
|
116
116
|
# initial setting for number of epochs to show in the lower plot
|
|
117
117
|
self.epochs_to_show = 5
|
|
@@ -833,7 +833,7 @@ class ManualScoringWindow(QtWidgets.QDialog):
|
|
|
833
833
|
self.adjust_upper_figure_x_limits()
|
|
834
834
|
|
|
835
835
|
# update parts of lower plot
|
|
836
|
-
old_window_center = round(self.epochs_to_show / 2) + self.lower_left_epoch
|
|
836
|
+
old_window_center = round((self.epochs_to_show - 1) / 2) + self.lower_left_epoch
|
|
837
837
|
# change the window bounds if needed
|
|
838
838
|
if self.epoch < old_window_center and self.lower_left_epoch > 0:
|
|
839
839
|
self.lower_left_epoch -= 1
|
accusleepy/gui/primary_window.py
CHANGED
|
@@ -100,6 +100,11 @@ class Ui_PrimaryWindow(object):
|
|
|
100
100
|
self.epoch_length_input.sizePolicy().hasHeightForWidth()
|
|
101
101
|
)
|
|
102
102
|
self.epoch_length_input.setSizePolicy(sizePolicy1)
|
|
103
|
+
self.epoch_length_input.setAlignment(
|
|
104
|
+
Qt.AlignmentFlag.AlignLeading
|
|
105
|
+
| Qt.AlignmentFlag.AlignLeft
|
|
106
|
+
| Qt.AlignmentFlag.AlignVCenter
|
|
107
|
+
)
|
|
103
108
|
self.epoch_length_input.setMaximum(100000.000000000000000)
|
|
104
109
|
self.epoch_length_input.setSingleStep(0.500000000000000)
|
|
105
110
|
|
|
@@ -185,6 +190,8 @@ class Ui_PrimaryWindow(object):
|
|
|
185
190
|
|
|
186
191
|
self.left_scoring_vlayout.addWidget(self.recordinglistgroupbox)
|
|
187
192
|
|
|
193
|
+
self.logo_and_version_layout = QVBoxLayout()
|
|
194
|
+
self.logo_and_version_layout.setObjectName("logo_and_version_layout")
|
|
188
195
|
self.logo_layout = QVBoxLayout()
|
|
189
196
|
self.logo_layout.setObjectName("logo_layout")
|
|
190
197
|
self.frame = QFrame(self.scoring_tab)
|
|
@@ -235,7 +242,24 @@ class Ui_PrimaryWindow(object):
|
|
|
235
242
|
|
|
236
243
|
self.logo_layout.addWidget(self.frame)
|
|
237
244
|
|
|
238
|
-
self.
|
|
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)
|
|
239
263
|
|
|
240
264
|
self.user_manual_layout = QHBoxLayout()
|
|
241
265
|
self.user_manual_layout.setObjectName("user_manual_layout")
|
|
@@ -293,6 +317,11 @@ class Ui_PrimaryWindow(object):
|
|
|
293
317
|
self.sampling_rate_input.sizePolicy().hasHeightForWidth()
|
|
294
318
|
)
|
|
295
319
|
self.sampling_rate_input.setSizePolicy(sizePolicy1)
|
|
320
|
+
self.sampling_rate_input.setAlignment(
|
|
321
|
+
Qt.AlignmentFlag.AlignLeading
|
|
322
|
+
| Qt.AlignmentFlag.AlignLeft
|
|
323
|
+
| Qt.AlignmentFlag.AlignVCenter
|
|
324
|
+
)
|
|
296
325
|
self.sampling_rate_input.setMinimum(0.000000000000000)
|
|
297
326
|
self.sampling_rate_input.setMaximum(100000.000000000000000)
|
|
298
327
|
|
|
@@ -318,11 +347,6 @@ class Ui_PrimaryWindow(object):
|
|
|
318
347
|
self.horizontalLayout.setObjectName("horizontalLayout")
|
|
319
348
|
self.recording_file_button = QPushButton(self.selected_recording_groupbox)
|
|
320
349
|
self.recording_file_button.setObjectName("recording_file_button")
|
|
321
|
-
sizePolicy3 = QSizePolicy(
|
|
322
|
-
QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Fixed
|
|
323
|
-
)
|
|
324
|
-
sizePolicy3.setHorizontalStretch(0)
|
|
325
|
-
sizePolicy3.setVerticalStretch(0)
|
|
326
350
|
sizePolicy3.setHeightForWidth(
|
|
327
351
|
self.recording_file_button.sizePolicy().hasHeightForWidth()
|
|
328
352
|
)
|
|
@@ -608,6 +632,11 @@ class Ui_PrimaryWindow(object):
|
|
|
608
632
|
self.bout_length_input.sizePolicy().hasHeightForWidth()
|
|
609
633
|
)
|
|
610
634
|
self.bout_length_input.setSizePolicy(sizePolicy1)
|
|
635
|
+
self.bout_length_input.setAlignment(
|
|
636
|
+
Qt.AlignmentFlag.AlignLeading
|
|
637
|
+
| Qt.AlignmentFlag.AlignLeft
|
|
638
|
+
| Qt.AlignmentFlag.AlignVCenter
|
|
639
|
+
)
|
|
611
640
|
self.bout_length_input.setDecimals(2)
|
|
612
641
|
self.bout_length_input.setMaximum(1000.000000000000000)
|
|
613
642
|
self.bout_length_input.setValue(5.000000000000000)
|
|
@@ -2044,6 +2073,44 @@ class Ui_PrimaryWindow(object):
|
|
|
2044
2073
|
|
|
2045
2074
|
self.verticalLayout_6.addLayout(self.horizontalLayout_4)
|
|
2046
2075
|
|
|
2076
|
+
self.default_epoch_layout = QHBoxLayout()
|
|
2077
|
+
self.default_epoch_layout.setObjectName("default_epoch_layout")
|
|
2078
|
+
self.horizontalSpacer_71 = QSpacerItem(
|
|
2079
|
+
10, 10, QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Minimum
|
|
2080
|
+
)
|
|
2081
|
+
|
|
2082
|
+
self.default_epoch_layout.addItem(self.horizontalSpacer_71)
|
|
2083
|
+
|
|
2084
|
+
self.horizontalLayout_60 = QHBoxLayout()
|
|
2085
|
+
self.horizontalLayout_60.setObjectName("horizontalLayout_60")
|
|
2086
|
+
self.label_17 = QLabel(self.settings_tab)
|
|
2087
|
+
self.label_17.setObjectName("label_17")
|
|
2088
|
+
sizePolicy1.setHeightForWidth(self.label_17.sizePolicy().hasHeightForWidth())
|
|
2089
|
+
self.label_17.setSizePolicy(sizePolicy1)
|
|
2090
|
+
|
|
2091
|
+
self.horizontalLayout_60.addWidget(self.label_17)
|
|
2092
|
+
|
|
2093
|
+
self.default_epoch_input = QDoubleSpinBox(self.settings_tab)
|
|
2094
|
+
self.default_epoch_input.setObjectName("default_epoch_input")
|
|
2095
|
+
sizePolicy1.setHeightForWidth(
|
|
2096
|
+
self.default_epoch_input.sizePolicy().hasHeightForWidth()
|
|
2097
|
+
)
|
|
2098
|
+
self.default_epoch_input.setSizePolicy(sizePolicy1)
|
|
2099
|
+
self.default_epoch_input.setMaximum(100000.000000000000000)
|
|
2100
|
+
self.default_epoch_input.setSingleStep(0.500000000000000)
|
|
2101
|
+
|
|
2102
|
+
self.horizontalLayout_60.addWidget(self.default_epoch_input)
|
|
2103
|
+
|
|
2104
|
+
self.default_epoch_layout.addLayout(self.horizontalLayout_60)
|
|
2105
|
+
|
|
2106
|
+
self.horizontalSpacer_70 = QSpacerItem(
|
|
2107
|
+
10, 10, QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Minimum
|
|
2108
|
+
)
|
|
2109
|
+
|
|
2110
|
+
self.default_epoch_layout.addItem(self.horizontalSpacer_70)
|
|
2111
|
+
|
|
2112
|
+
self.verticalLayout_6.addLayout(self.default_epoch_layout)
|
|
2113
|
+
|
|
2047
2114
|
self.horizontalLayout_18 = QHBoxLayout()
|
|
2048
2115
|
self.horizontalLayout_18.setSpacing(10)
|
|
2049
2116
|
self.horizontalLayout_18.setObjectName("horizontalLayout_18")
|
|
@@ -2079,6 +2146,7 @@ class Ui_PrimaryWindow(object):
|
|
|
2079
2146
|
self.verticalLayout_6.addLayout(self.horizontalLayout_18)
|
|
2080
2147
|
|
|
2081
2148
|
self.verticalLayout_6.setStretch(0, 2)
|
|
2149
|
+
self.verticalLayout_6.setStretch(1, 2)
|
|
2082
2150
|
self.verticalLayout_6.setStretch(2, 2)
|
|
2083
2151
|
self.verticalLayout_6.setStretch(3, 2)
|
|
2084
2152
|
self.verticalLayout_6.setStretch(4, 2)
|
|
@@ -2088,7 +2156,8 @@ class Ui_PrimaryWindow(object):
|
|
|
2088
2156
|
self.verticalLayout_6.setStretch(8, 2)
|
|
2089
2157
|
self.verticalLayout_6.setStretch(9, 2)
|
|
2090
2158
|
self.verticalLayout_6.setStretch(10, 2)
|
|
2091
|
-
self.verticalLayout_6.setStretch(11,
|
|
2159
|
+
self.verticalLayout_6.setStretch(11, 2)
|
|
2160
|
+
self.verticalLayout_6.setStretch(12, 3)
|
|
2092
2161
|
|
|
2093
2162
|
self.settings_tab_layout.addLayout(self.verticalLayout_6, 0, 0, 1, 1)
|
|
2094
2163
|
|
|
@@ -2150,9 +2219,23 @@ class Ui_PrimaryWindow(object):
|
|
|
2150
2219
|
self.remove_button.setText(
|
|
2151
2220
|
QCoreApplication.translate("PrimaryWindow", "remove", None)
|
|
2152
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)
|
|
2153
2229
|
self.export_button.setText(
|
|
2154
2230
|
QCoreApplication.translate("PrimaryWindow", "export", None)
|
|
2155
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)
|
|
2156
2239
|
self.import_button.setText(
|
|
2157
2240
|
QCoreApplication.translate("PrimaryWindow", "import", None)
|
|
2158
2241
|
)
|
|
@@ -2165,6 +2248,9 @@ class Ui_PrimaryWindow(object):
|
|
|
2165
2248
|
self.accusleepy1.setText(
|
|
2166
2249
|
QCoreApplication.translate("PrimaryWindow", "AccuSleePy", None)
|
|
2167
2250
|
)
|
|
2251
|
+
self.version_label.setText(
|
|
2252
|
+
QCoreApplication.translate("PrimaryWindow", "TextLabel", None)
|
|
2253
|
+
)
|
|
2168
2254
|
# if QT_CONFIG(tooltip)
|
|
2169
2255
|
self.user_manual_button.setToolTip(
|
|
2170
2256
|
QCoreApplication.translate("PrimaryWindow", "User manual", None)
|
|
@@ -2179,6 +2265,13 @@ class Ui_PrimaryWindow(object):
|
|
|
2179
2265
|
self.samplingratelabel.setText(
|
|
2180
2266
|
QCoreApplication.translate("PrimaryWindow", "Sampling rate (Hz):", None)
|
|
2181
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)
|
|
2182
2275
|
self.recording_file_button.setText(
|
|
2183
2276
|
QCoreApplication.translate("PrimaryWindow", "Select recording file", None)
|
|
2184
2277
|
)
|
|
@@ -2221,10 +2314,24 @@ class Ui_PrimaryWindow(object):
|
|
|
2221
2314
|
QCoreApplication.translate("PrimaryWindow", "Score manually", None)
|
|
2222
2315
|
)
|
|
2223
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)
|
|
2224
2324
|
self.create_calibration_button.setText(
|
|
2225
2325
|
QCoreApplication.translate("PrimaryWindow", "Create calibration file", None)
|
|
2226
2326
|
)
|
|
2227
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)
|
|
2228
2335
|
self.select_calibration_button.setText(
|
|
2229
2336
|
QCoreApplication.translate("PrimaryWindow", "Select calibration file", None)
|
|
2230
2337
|
)
|
|
@@ -2252,6 +2359,13 @@ class Ui_PrimaryWindow(object):
|
|
|
2252
2359
|
"PrimaryWindow", "Minimum bout length (sec):", None
|
|
2253
2360
|
)
|
|
2254
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)
|
|
2255
2369
|
self.load_model_button.setText(
|
|
2256
2370
|
QCoreApplication.translate(
|
|
2257
2371
|
"PrimaryWindow", "Load classification model", None
|
|
@@ -2279,6 +2393,13 @@ class Ui_PrimaryWindow(object):
|
|
|
2279
2393
|
self.real_time_button.setText(
|
|
2280
2394
|
QCoreApplication.translate("PrimaryWindow", "Real-time", None)
|
|
2281
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)
|
|
2282
2403
|
self.train_model_button.setText(
|
|
2283
2404
|
QCoreApplication.translate(
|
|
2284
2405
|
"PrimaryWindow", "Train classification model", None
|
|
@@ -2352,6 +2473,16 @@ class Ui_PrimaryWindow(object):
|
|
|
2352
2473
|
self.label_3.setText(QCoreApplication.translate("PrimaryWindow", "0", None))
|
|
2353
2474
|
self.enable_state_0.setText("")
|
|
2354
2475
|
self.state_scored_0.setText("")
|
|
2476
|
+
self.label_17.setText(
|
|
2477
|
+
QCoreApplication.translate("PrimaryWindow", "Default epoch length:", None)
|
|
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)
|
|
2355
2486
|
self.save_config_button.setText(
|
|
2356
2487
|
QCoreApplication.translate("PrimaryWindow", "Save", None)
|
|
2357
2488
|
)
|
accusleepy/gui/primary_window.ui
CHANGED
|
@@ -164,6 +164,9 @@
|
|
|
164
164
|
<verstretch>0</verstretch>
|
|
165
165
|
</sizepolicy>
|
|
166
166
|
</property>
|
|
167
|
+
<property name="alignment">
|
|
168
|
+
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter</set>
|
|
169
|
+
</property>
|
|
167
170
|
<property name="maximum">
|
|
168
171
|
<double>100000.000000000000000</double>
|
|
169
172
|
</property>
|
|
@@ -260,6 +263,9 @@
|
|
|
260
263
|
<verstretch>0</verstretch>
|
|
261
264
|
</sizepolicy>
|
|
262
265
|
</property>
|
|
266
|
+
<property name="toolTip">
|
|
267
|
+
<string>Export recording list to file</string>
|
|
268
|
+
</property>
|
|
263
269
|
<property name="text">
|
|
264
270
|
<string>export</string>
|
|
265
271
|
</property>
|
|
@@ -273,6 +279,9 @@
|
|
|
273
279
|
<verstretch>0</verstretch>
|
|
274
280
|
</sizepolicy>
|
|
275
281
|
</property>
|
|
282
|
+
<property name="toolTip">
|
|
283
|
+
<string>Import recording list from file</string>
|
|
284
|
+
</property>
|
|
276
285
|
<property name="text">
|
|
277
286
|
<string>import</string>
|
|
278
287
|
</property>
|
|
@@ -284,132 +293,152 @@
|
|
|
284
293
|
</widget>
|
|
285
294
|
</item>
|
|
286
295
|
<item>
|
|
287
|
-
<layout class="QVBoxLayout" name="
|
|
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>
|
|
288
428
|
<item>
|
|
289
|
-
<widget class="
|
|
429
|
+
<widget class="QLabel" name="version_label">
|
|
290
430
|
<property name="sizePolicy">
|
|
291
|
-
<sizepolicy hsizetype="
|
|
431
|
+
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
292
432
|
<horstretch>0</horstretch>
|
|
293
433
|
<verstretch>0</verstretch>
|
|
294
434
|
</sizepolicy>
|
|
295
435
|
</property>
|
|
296
|
-
<property name="
|
|
297
|
-
<
|
|
298
|
-
<width>180</width>
|
|
299
|
-
<height>80</height>
|
|
300
|
-
</size>
|
|
301
|
-
</property>
|
|
302
|
-
<property name="styleSheet">
|
|
303
|
-
<string notr="true">background-color: transparent;</string>
|
|
304
|
-
</property>
|
|
305
|
-
<property name="frameShape">
|
|
306
|
-
<enum>QFrame::Shape::NoFrame</enum>
|
|
436
|
+
<property name="text">
|
|
437
|
+
<string>TextLabel</string>
|
|
307
438
|
</property>
|
|
308
|
-
<property name="
|
|
309
|
-
<
|
|
439
|
+
<property name="alignment">
|
|
440
|
+
<set>Qt::AlignmentFlag::AlignCenter</set>
|
|
310
441
|
</property>
|
|
311
|
-
<widget class="QLabel" name="accusleepy2">
|
|
312
|
-
<property name="geometry">
|
|
313
|
-
<rect>
|
|
314
|
-
<x>11</x>
|
|
315
|
-
<y>15</y>
|
|
316
|
-
<width>160</width>
|
|
317
|
-
<height>50</height>
|
|
318
|
-
</rect>
|
|
319
|
-
</property>
|
|
320
|
-
<property name="sizePolicy">
|
|
321
|
-
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
|
322
|
-
<horstretch>0</horstretch>
|
|
323
|
-
<verstretch>0</verstretch>
|
|
324
|
-
</sizepolicy>
|
|
325
|
-
</property>
|
|
326
|
-
<property name="font">
|
|
327
|
-
<font>
|
|
328
|
-
<pointsize>21</pointsize>
|
|
329
|
-
<italic>true</italic>
|
|
330
|
-
<bold>true</bold>
|
|
331
|
-
</font>
|
|
332
|
-
</property>
|
|
333
|
-
<property name="styleSheet">
|
|
334
|
-
<string notr="true">background-color: transparent;
|
|
335
|
-
color: rgb(130, 169, 68);</string>
|
|
336
|
-
</property>
|
|
337
|
-
<property name="text">
|
|
338
|
-
<string>AccuSleePy</string>
|
|
339
|
-
</property>
|
|
340
|
-
<property name="alignment">
|
|
341
|
-
<set>Qt::AlignmentFlag::AlignCenter</set>
|
|
342
|
-
</property>
|
|
343
|
-
</widget>
|
|
344
|
-
<widget class="QLabel" name="accusleepy3">
|
|
345
|
-
<property name="geometry">
|
|
346
|
-
<rect>
|
|
347
|
-
<x>13</x>
|
|
348
|
-
<y>17</y>
|
|
349
|
-
<width>160</width>
|
|
350
|
-
<height>50</height>
|
|
351
|
-
</rect>
|
|
352
|
-
</property>
|
|
353
|
-
<property name="sizePolicy">
|
|
354
|
-
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
|
355
|
-
<horstretch>0</horstretch>
|
|
356
|
-
<verstretch>0</verstretch>
|
|
357
|
-
</sizepolicy>
|
|
358
|
-
</property>
|
|
359
|
-
<property name="font">
|
|
360
|
-
<font>
|
|
361
|
-
<pointsize>21</pointsize>
|
|
362
|
-
<italic>true</italic>
|
|
363
|
-
<bold>true</bold>
|
|
364
|
-
</font>
|
|
365
|
-
</property>
|
|
366
|
-
<property name="styleSheet">
|
|
367
|
-
<string notr="true">background-color: transparent;
|
|
368
|
-
color: rgb(46, 63, 150);</string>
|
|
369
|
-
</property>
|
|
370
|
-
<property name="text">
|
|
371
|
-
<string>AccuSleePy</string>
|
|
372
|
-
</property>
|
|
373
|
-
<property name="alignment">
|
|
374
|
-
<set>Qt::AlignmentFlag::AlignCenter</set>
|
|
375
|
-
</property>
|
|
376
|
-
</widget>
|
|
377
|
-
<widget class="QLabel" name="accusleepy1">
|
|
378
|
-
<property name="geometry">
|
|
379
|
-
<rect>
|
|
380
|
-
<x>9</x>
|
|
381
|
-
<y>13</y>
|
|
382
|
-
<width>160</width>
|
|
383
|
-
<height>50</height>
|
|
384
|
-
</rect>
|
|
385
|
-
</property>
|
|
386
|
-
<property name="sizePolicy">
|
|
387
|
-
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
|
388
|
-
<horstretch>0</horstretch>
|
|
389
|
-
<verstretch>0</verstretch>
|
|
390
|
-
</sizepolicy>
|
|
391
|
-
</property>
|
|
392
|
-
<property name="font">
|
|
393
|
-
<font>
|
|
394
|
-
<pointsize>21</pointsize>
|
|
395
|
-
<italic>true</italic>
|
|
396
|
-
<bold>true</bold>
|
|
397
|
-
</font>
|
|
398
|
-
</property>
|
|
399
|
-
<property name="styleSheet">
|
|
400
|
-
<string notr="true">background-color: transparent;
|
|
401
|
-
color: rgb(244, 195, 68);</string>
|
|
402
|
-
</property>
|
|
403
|
-
<property name="text">
|
|
404
|
-
<string>AccuSleePy</string>
|
|
405
|
-
</property>
|
|
406
|
-
<property name="alignment">
|
|
407
|
-
<set>Qt::AlignmentFlag::AlignCenter</set>
|
|
408
|
-
</property>
|
|
409
|
-
</widget>
|
|
410
|
-
<zorder>accusleepy1</zorder>
|
|
411
|
-
<zorder>accusleepy2</zorder>
|
|
412
|
-
<zorder>accusleepy3</zorder>
|
|
413
442
|
</widget>
|
|
414
443
|
</item>
|
|
415
444
|
</layout>
|
|
@@ -512,6 +541,9 @@ color: rgb(244, 195, 68);</string>
|
|
|
512
541
|
<verstretch>0</verstretch>
|
|
513
542
|
</sizepolicy>
|
|
514
543
|
</property>
|
|
544
|
+
<property name="alignment">
|
|
545
|
+
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter</set>
|
|
546
|
+
</property>
|
|
515
547
|
<property name="minimum">
|
|
516
548
|
<double>0.000000000000000</double>
|
|
517
549
|
</property>
|
|
@@ -556,6 +588,9 @@ color: rgb(244, 195, 68);</string>
|
|
|
556
588
|
<verstretch>0</verstretch>
|
|
557
589
|
</sizepolicy>
|
|
558
590
|
</property>
|
|
591
|
+
<property name="toolTip">
|
|
592
|
+
<string>Select EEG+EMG recording</string>
|
|
593
|
+
</property>
|
|
559
594
|
<property name="text">
|
|
560
595
|
<string>Select recording file</string>
|
|
561
596
|
</property>
|
|
@@ -747,6 +782,9 @@ color: rgb(244, 195, 68);</string>
|
|
|
747
782
|
<verstretch>0</verstretch>
|
|
748
783
|
</sizepolicy>
|
|
749
784
|
</property>
|
|
785
|
+
<property name="toolTip">
|
|
786
|
+
<string>Create calibration file for this subject</string>
|
|
787
|
+
</property>
|
|
750
788
|
<property name="text">
|
|
751
789
|
<string>Create calibration file</string>
|
|
752
790
|
</property>
|
|
@@ -807,6 +845,9 @@ color: rgb(244, 195, 68);</string>
|
|
|
807
845
|
<verstretch>0</verstretch>
|
|
808
846
|
</sizepolicy>
|
|
809
847
|
</property>
|
|
848
|
+
<property name="toolTip">
|
|
849
|
+
<string>Load calibration file for this recording</string>
|
|
850
|
+
</property>
|
|
810
851
|
<property name="text">
|
|
811
852
|
<string>Select calibration file</string>
|
|
812
853
|
</property>
|
|
@@ -982,6 +1023,9 @@ color: rgb(244, 195, 68);</string>
|
|
|
982
1023
|
<verstretch>0</verstretch>
|
|
983
1024
|
</sizepolicy>
|
|
984
1025
|
</property>
|
|
1026
|
+
<property name="alignment">
|
|
1027
|
+
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter</set>
|
|
1028
|
+
</property>
|
|
985
1029
|
<property name="decimals">
|
|
986
1030
|
<number>2</number>
|
|
987
1031
|
</property>
|
|
@@ -1033,6 +1077,9 @@ color: rgb(244, 195, 68);</string>
|
|
|
1033
1077
|
<verstretch>0</verstretch>
|
|
1034
1078
|
</sizepolicy>
|
|
1035
1079
|
</property>
|
|
1080
|
+
<property name="toolTip">
|
|
1081
|
+
<string>Load a trained sleep scoring classifier</string>
|
|
1082
|
+
</property>
|
|
1036
1083
|
<property name="text">
|
|
1037
1084
|
<string>Load classification model</string>
|
|
1038
1085
|
</property>
|
|
@@ -1287,6 +1334,9 @@ color: rgb(244, 195, 68);</string>
|
|
|
1287
1334
|
<verstretch>0</verstretch>
|
|
1288
1335
|
</sizepolicy>
|
|
1289
1336
|
</property>
|
|
1337
|
+
<property name="toolTip">
|
|
1338
|
+
<string>Begin training the classification model</string>
|
|
1339
|
+
</property>
|
|
1290
1340
|
<property name="text">
|
|
1291
1341
|
<string>Train classification model</string>
|
|
1292
1342
|
</property>
|
|
@@ -1465,7 +1515,7 @@ color: rgb(244, 195, 68);</string>
|
|
|
1465
1515
|
</layout>
|
|
1466
1516
|
</item>
|
|
1467
1517
|
<item row="0" column="0">
|
|
1468
|
-
<layout class="QVBoxLayout" name="verticalLayout_6" stretch="2,
|
|
1518
|
+
<layout class="QVBoxLayout" name="verticalLayout_6" stretch="2,2,2,2,2,2,2,2,2,2,2,2,3">
|
|
1469
1519
|
<item>
|
|
1470
1520
|
<layout class="QHBoxLayout" name="horizontalLayout_3" stretch="3,3,4,3,4">
|
|
1471
1521
|
<property name="spacing">
|
|
@@ -3446,6 +3496,75 @@ color: rgb(244, 195, 68);</string>
|
|
|
3446
3496
|
</item>
|
|
3447
3497
|
</layout>
|
|
3448
3498
|
</item>
|
|
3499
|
+
<item>
|
|
3500
|
+
<layout class="QHBoxLayout" name="default_epoch_layout">
|
|
3501
|
+
<item>
|
|
3502
|
+
<spacer name="horizontalSpacer_71">
|
|
3503
|
+
<property name="orientation">
|
|
3504
|
+
<enum>Qt::Orientation::Horizontal</enum>
|
|
3505
|
+
</property>
|
|
3506
|
+
<property name="sizeType">
|
|
3507
|
+
<enum>QSizePolicy::Policy::Preferred</enum>
|
|
3508
|
+
</property>
|
|
3509
|
+
<property name="sizeHint" stdset="0">
|
|
3510
|
+
<size>
|
|
3511
|
+
<width>10</width>
|
|
3512
|
+
<height>10</height>
|
|
3513
|
+
</size>
|
|
3514
|
+
</property>
|
|
3515
|
+
</spacer>
|
|
3516
|
+
</item>
|
|
3517
|
+
<item>
|
|
3518
|
+
<layout class="QHBoxLayout" name="horizontalLayout_60">
|
|
3519
|
+
<item>
|
|
3520
|
+
<widget class="QLabel" name="label_17">
|
|
3521
|
+
<property name="sizePolicy">
|
|
3522
|
+
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
|
3523
|
+
<horstretch>0</horstretch>
|
|
3524
|
+
<verstretch>0</verstretch>
|
|
3525
|
+
</sizepolicy>
|
|
3526
|
+
</property>
|
|
3527
|
+
<property name="text">
|
|
3528
|
+
<string>Default epoch length:</string>
|
|
3529
|
+
</property>
|
|
3530
|
+
</widget>
|
|
3531
|
+
</item>
|
|
3532
|
+
<item>
|
|
3533
|
+
<widget class="QDoubleSpinBox" name="default_epoch_input">
|
|
3534
|
+
<property name="sizePolicy">
|
|
3535
|
+
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
|
3536
|
+
<horstretch>0</horstretch>
|
|
3537
|
+
<verstretch>0</verstretch>
|
|
3538
|
+
</sizepolicy>
|
|
3539
|
+
</property>
|
|
3540
|
+
<property name="maximum">
|
|
3541
|
+
<double>100000.000000000000000</double>
|
|
3542
|
+
</property>
|
|
3543
|
+
<property name="singleStep">
|
|
3544
|
+
<double>0.500000000000000</double>
|
|
3545
|
+
</property>
|
|
3546
|
+
</widget>
|
|
3547
|
+
</item>
|
|
3548
|
+
</layout>
|
|
3549
|
+
</item>
|
|
3550
|
+
<item>
|
|
3551
|
+
<spacer name="horizontalSpacer_70">
|
|
3552
|
+
<property name="orientation">
|
|
3553
|
+
<enum>Qt::Orientation::Horizontal</enum>
|
|
3554
|
+
</property>
|
|
3555
|
+
<property name="sizeType">
|
|
3556
|
+
<enum>QSizePolicy::Policy::Preferred</enum>
|
|
3557
|
+
</property>
|
|
3558
|
+
<property name="sizeHint" stdset="0">
|
|
3559
|
+
<size>
|
|
3560
|
+
<width>10</width>
|
|
3561
|
+
<height>10</height>
|
|
3562
|
+
</size>
|
|
3563
|
+
</property>
|
|
3564
|
+
</spacer>
|
|
3565
|
+
</item>
|
|
3566
|
+
</layout>
|
|
3567
|
+
</item>
|
|
3449
3568
|
<item>
|
|
3450
3569
|
<layout class="QHBoxLayout" name="horizontalLayout_18" stretch="6,1,7">
|
|
3451
3570
|
<property name="spacing">
|
|
@@ -3475,6 +3594,9 @@ color: rgb(244, 195, 68);</string>
|
|
|
3475
3594
|
<verstretch>0</verstretch>
|
|
3476
3595
|
</sizepolicy>
|
|
3477
3596
|
</property>
|
|
3597
|
+
<property name="toolTip">
|
|
3598
|
+
<string>Save current configuration</string>
|
|
3599
|
+
</property>
|
|
3478
3600
|
<property name="text">
|
|
3479
3601
|
<string>Save</string>
|
|
3480
3602
|
</property>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
This is the current brain state configuration.
|
|
2
|
-
If you
|
|
2
|
+
If you make changes, click 'Save' to store them.
|
|
3
3
|
|
|
4
4
|
Each brain state has several attributes:
|
|
5
5
|
|
|
@@ -25,3 +25,5 @@ Important notes:
|
|
|
25
25
|
- Changing these settings can invalidate existing label files,
|
|
26
26
|
calibration files, and trained models!
|
|
27
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,8 +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
|
|
1
14
|
Section 1: Overview of the GUI
|
|
2
15
|
Section 2: AccuSleePy file types
|
|
3
16
|
Section 3: Manually assigning brain state labels
|
|
4
17
|
Section 4: Automatically assigning brain state labels
|
|
5
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
|
+
|
|
6
29
|
-----------------------------------------------------------------------
|
|
7
30
|
Section 1: Overview of the primary interface
|
|
8
31
|
-----------------------------------------------------------------------
|
|
@@ -40,18 +63,17 @@ There are four types of files associated with AccuSleePy.
|
|
|
40
63
|
To select a file in the primary interface, you can either use the
|
|
41
64
|
associated button, or drag/drop the file into the empty box adjacent
|
|
42
65
|
to the button.
|
|
43
|
-
Recording file: a
|
|
44
|
-
data and one column of EMG data.
|
|
45
|
-
|
|
46
|
-
Label file: a
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
and REM = 1, wake = 2, NREM = 3.
|
|
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})
|
|
71
|
+
or one of the digits in your brain state configuration.
|
|
72
|
+
By default, these are 1-3 where REM = 1, wake = 2, NREM = 3.
|
|
51
73
|
Calibration data file: required for automatic labeling. See Section 4
|
|
52
|
-
for details.
|
|
74
|
+
for details. These have {CALIBRATION_FILE_TYPE} format.
|
|
53
75
|
Trained classification model: required for automatic labeling. See
|
|
54
|
-
Section 4 for details.
|
|
76
|
+
Section 4 for details. These have {MODEL_FILE_TYPE} format.
|
|
55
77
|
|
|
56
78
|
-----------------------------------------------------------------------
|
|
57
79
|
Section 3: Manually assigning brain state labels
|
|
@@ -75,6 +97,12 @@ Section 4: Automatically scoring recordings with a classification model
|
|
|
75
97
|
Automatic brain state scoring requires the inputs described in
|
|
76
98
|
Section 3, as well as calibration data files and a trained classifier.
|
|
77
99
|
If you already have all of these files, proceed to Section 4C.
|
|
100
|
+
Models trained on the AccuSleep dataset are provided at
|
|
101
|
+
https://osf.io/py5eb under /python_format/models/ for epoch lengths of
|
|
102
|
+
2.5, 4, 5, and 10 seconds. These models are the "default" type, in that
|
|
103
|
+
they use several epochs of data before and after any given epoch when
|
|
104
|
+
scoring that epoch. (The other model type, called "real-time", only
|
|
105
|
+
uses data from the current epoch and several preceding epochs.)
|
|
78
106
|
|
|
79
107
|
--- Section 4A: Creating calibration data files ---
|
|
80
108
|
Each recording must have a calibration file assigned to it.
|
|
@@ -95,14 +123,12 @@ To create a calibration data file:
|
|
|
95
123
|
4. Enter a filename for the calibration data file.
|
|
96
124
|
5. The calibration file will automatically be assigned to the currently
|
|
97
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.
|
|
98
130
|
|
|
99
131
|
--- Section 4B: Training your own classification model ---
|
|
100
|
-
Pre-trained classification models are provided with AccuSleePy for
|
|
101
|
-
epoch lengths of 2.5, 4, 5, and 10 seconds. These models are the
|
|
102
|
-
"default" type, in that they use several epochs of data before and
|
|
103
|
-
after any given epoch when scoring that epoch. (The other model type,
|
|
104
|
-
called "real-time", only uses data from the current epoch and several
|
|
105
|
-
preceding epochs.
|
|
106
132
|
To train a new model on your own data:
|
|
107
133
|
1. Add your scored recordings to the recording list. Make sure the
|
|
108
134
|
sampling rate, recording file, and label file are set for each
|
|
@@ -113,11 +139,15 @@ To train a new model on your own data:
|
|
|
113
139
|
type models, this must be an odd number. In general, about 30
|
|
114
140
|
seconds worth of data is enough.
|
|
115
141
|
4. Choose whether the images used to train the model should be
|
|
116
|
-
deleted once training is complete.
|
|
117
|
-
|
|
142
|
+
deleted once training is complete. (It's generally best to
|
|
143
|
+
leave this box checked.)
|
|
144
|
+
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
|
|
118
148
|
new directory with an automatically generated name will be
|
|
119
149
|
created inside the directory you choose.
|
|
120
|
-
|
|
150
|
+
7. Click the "Train classification model" button and enter a
|
|
121
151
|
filename for the trained model. Training can take some time.
|
|
122
152
|
|
|
123
153
|
--- Section 4C: Automatic labeling ---
|
|
@@ -127,8 +157,8 @@ Instructions for automatic labeling using this GUI are below.
|
|
|
127
157
|
for each recording. See section 4A for instructions on creating
|
|
128
158
|
calibration files.
|
|
129
159
|
3. Click 'Load classification model' to load the trained classification
|
|
130
|
-
model.
|
|
131
|
-
the same as the current epoch length.
|
|
160
|
+
model. It's important that the epoch length used when training this
|
|
161
|
+
model is the same as the current epoch length.
|
|
132
162
|
4. If you wish to preserve any existing labels in the label file, and
|
|
133
163
|
only overwrite undefined epochs, check the box labeled
|
|
134
164
|
'Only overwrite undefined epochs'.
|
|
@@ -140,3 +170,4 @@ Instructions for automatic labeling using this GUI are below.
|
|
|
140
170
|
recording list. Labels will be saved to the file specified by
|
|
141
171
|
the 'Select or create label file' field of each recording. You can
|
|
142
172
|
click 'Score manually' to visualize the results.
|
|
173
|
+
"""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: accusleepy
|
|
3
|
-
Version: 0.
|
|
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)
|
|
@@ -30,16 +31,19 @@ Description-Content-Type: text/markdown
|
|
|
30
31
|
## Description
|
|
31
32
|
|
|
32
33
|
AccuSleePy is a python implementation of AccuSleep--a set of graphical user interfaces for scoring rodent
|
|
33
|
-
sleep using EEG and EMG recordings.
|
|
34
|
+
sleep using EEG and EMG recordings. It offers several improvements over the original MATLAB version
|
|
35
|
+
and is the only version that will be actively maintained.
|
|
36
|
+
|
|
37
|
+
If you use AccuSleep in your research, please cite our
|
|
34
38
|
[publication](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0224642):
|
|
35
39
|
|
|
36
40
|
Barger, Z., Frye, C. G., Liu, D., Dan, Y., & Bouchard, K. E. (2019). Robust, automated sleep scoring by a compact neural network with distributional shift correction. *PLOS ONE, 14*(12), 1–18.
|
|
37
41
|
|
|
38
|
-
The data
|
|
42
|
+
The data and models associated with AccuSleep are available at https://osf.io/py5eb/
|
|
39
43
|
|
|
40
44
|
Please contact zekebarger (at) gmail (dot) com with any questions or comments about the software.
|
|
41
45
|
|
|
42
|
-
## Installation
|
|
46
|
+
## Installation
|
|
43
47
|
|
|
44
48
|
- (recommended) create a new virtual environment (using
|
|
45
49
|
[venv](https://docs.python.org/3/library/venv.html),
|
|
@@ -47,10 +51,11 @@ Please contact zekebarger (at) gmail (dot) com with any questions or comments ab
|
|
|
47
51
|
etc.) using python >=3.10,<3.13
|
|
48
52
|
- (optional) if you have a CUDA device and want to speed up model training, [install PyTorch](https://pytorch.org/)
|
|
49
53
|
- `pip install accusleepy`
|
|
54
|
+
- (optional) download a classification model from https://osf.io/py5eb/ under /python_format/models/
|
|
50
55
|
|
|
51
56
|
## Usage
|
|
52
57
|
|
|
53
|
-
`python -m accusleepy`
|
|
58
|
+
`python -m accusleepy` will open the primary interface.
|
|
54
59
|
|
|
55
60
|
## Acknowledgements
|
|
56
61
|
|
|
@@ -2,9 +2,9 @@ accusleepy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
2
2
|
accusleepy/__main__.py,sha256=dKzl2N2Hg9lD264CWYNxThRyDKzWwyMwHRXmJxOmMis,104
|
|
3
3
|
accusleepy/brain_state_set.py,sha256=fRkrArHLIbEKimub804yt_mUXoyfsjJEfiJnTjeCMkY,3233
|
|
4
4
|
accusleepy/classification.py,sha256=xrmPyMHlzYh0QfNCID1PRIYEIyNkWduOi7g1Bdb6xfg,8573
|
|
5
|
-
accusleepy/config.json,sha256=
|
|
6
|
-
accusleepy/constants.py,sha256=
|
|
7
|
-
accusleepy/fileio.py,sha256=
|
|
5
|
+
accusleepy/config.json,sha256=F76WRLarMEW38BBMPwFlQ_d7Dur-ptqYmW8BxqnQF4A,464
|
|
6
|
+
accusleepy/constants.py,sha256=PnsPANggyIfMfd6OCR-kNztFOTybUEhMnPeibu5_eEU,1280
|
|
7
|
+
accusleepy/fileio.py,sha256=S5pf_hE-btJPMbrTplKLaQTULSJQoOJ-56LBH79Uz3I,6383
|
|
8
8
|
accusleepy/gui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
9
|
accusleepy/gui/icons/brightness_down.png,sha256=PLT1fb83RHIhSRuU7MMMx0G7oJAY7o9wUcnqM8veZfM,12432
|
|
10
10
|
accusleepy/gui/icons/brightness_up.png,sha256=64GnUqgPvN5xZ6Um3wOzwqvUmdAWYZT6eFmWpBsHyks,12989
|
|
@@ -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=
|
|
21
|
-
accusleepy/gui/manual_scoring.py,sha256=
|
|
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=
|
|
24
|
-
accusleepy/gui/primary_window.ui,sha256=
|
|
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=
|
|
28
|
-
accusleepy/gui/text/
|
|
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.
|
|
36
|
-
accusleepy-0.
|
|
37
|
-
accusleepy-0.
|
|
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,,
|
|
File without changes
|