accusleepy 0.6.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/__init__.py +0 -0
- accusleepy/__main__.py +4 -0
- accusleepy/bouts.py +142 -0
- accusleepy/brain_state_set.py +89 -0
- accusleepy/classification.py +285 -0
- accusleepy/config.json +24 -0
- accusleepy/constants.py +46 -0
- accusleepy/fileio.py +179 -0
- accusleepy/gui/__init__.py +0 -0
- accusleepy/gui/icons/brightness_down.png +0 -0
- accusleepy/gui/icons/brightness_up.png +0 -0
- accusleepy/gui/icons/double_down_arrow.png +0 -0
- accusleepy/gui/icons/double_up_arrow.png +0 -0
- accusleepy/gui/icons/down_arrow.png +0 -0
- accusleepy/gui/icons/home.png +0 -0
- accusleepy/gui/icons/question.png +0 -0
- accusleepy/gui/icons/save.png +0 -0
- accusleepy/gui/icons/up_arrow.png +0 -0
- accusleepy/gui/icons/zoom_in.png +0 -0
- accusleepy/gui/icons/zoom_out.png +0 -0
- accusleepy/gui/images/primary_window.png +0 -0
- accusleepy/gui/images/viewer_window.png +0 -0
- accusleepy/gui/images/viewer_window_annotated.png +0 -0
- accusleepy/gui/main.py +1494 -0
- accusleepy/gui/manual_scoring.py +1096 -0
- accusleepy/gui/mplwidget.py +386 -0
- accusleepy/gui/primary_window.py +2577 -0
- accusleepy/gui/primary_window.ui +3831 -0
- accusleepy/gui/resources.qrc +16 -0
- accusleepy/gui/resources_rc.py +6710 -0
- accusleepy/gui/text/config_guide.txt +27 -0
- accusleepy/gui/text/main_guide.md +167 -0
- accusleepy/gui/text/manual_scoring_guide.md +23 -0
- accusleepy/gui/viewer_window.py +610 -0
- accusleepy/gui/viewer_window.ui +926 -0
- accusleepy/models.py +108 -0
- accusleepy/multitaper.py +661 -0
- accusleepy/signal_processing.py +469 -0
- accusleepy/temperature_scaling.py +157 -0
- accusleepy-0.6.0.dist-info/METADATA +106 -0
- accusleepy-0.6.0.dist-info/RECORD +42 -0
- accusleepy-0.6.0.dist-info/WHEEL +4 -0
accusleepy/fileio.py
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
import pandas as pd
|
|
7
|
+
from PySide6.QtWidgets import QListWidgetItem
|
|
8
|
+
|
|
9
|
+
from accusleepy.brain_state_set import BRAIN_STATES_KEY, BrainState, BrainStateSet
|
|
10
|
+
from accusleepy.constants import (
|
|
11
|
+
BRAIN_STATE_COL,
|
|
12
|
+
CONFIDENCE_SCORE_COL,
|
|
13
|
+
CONFIG_FILE,
|
|
14
|
+
DEFAULT_CONFIDENCE_SETTING_KEY,
|
|
15
|
+
DEFAULT_EPOCH_LENGTH_KEY,
|
|
16
|
+
EEG_COL,
|
|
17
|
+
EMG_COL,
|
|
18
|
+
MIXTURE_MEAN_COL,
|
|
19
|
+
MIXTURE_SD_COL,
|
|
20
|
+
RECORDING_LIST_NAME,
|
|
21
|
+
UNDEFINED_LABEL,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass
|
|
26
|
+
class Recording:
|
|
27
|
+
"""Store information about a recording"""
|
|
28
|
+
|
|
29
|
+
name: int = 1 # name to show in the GUI
|
|
30
|
+
recording_file: str = "" # path to recording file
|
|
31
|
+
label_file: str = "" # path to label file
|
|
32
|
+
calibration_file: str = "" # path to calibration file
|
|
33
|
+
sampling_rate: int | float = 0.0 # sampling rate, in Hz
|
|
34
|
+
widget: QListWidgetItem = None # list item widget shown in the GUI
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def load_calibration_file(filename: str) -> (np.array, np.array):
|
|
38
|
+
"""Load a calibration file
|
|
39
|
+
|
|
40
|
+
:param filename: filename
|
|
41
|
+
:return: mixture means and SDs
|
|
42
|
+
"""
|
|
43
|
+
df = pd.read_csv(filename)
|
|
44
|
+
mixture_means = df[MIXTURE_MEAN_COL].values
|
|
45
|
+
mixture_sds = df[MIXTURE_SD_COL].values
|
|
46
|
+
return mixture_means, mixture_sds
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def load_csv_or_parquet(filename: str) -> pd.DataFrame:
|
|
50
|
+
"""Load a csv or parquet file as a dataframe
|
|
51
|
+
|
|
52
|
+
:param filename: filename
|
|
53
|
+
:return: dataframe of file contents
|
|
54
|
+
"""
|
|
55
|
+
extension = os.path.splitext(filename)[1]
|
|
56
|
+
if extension == ".csv":
|
|
57
|
+
df = pd.read_csv(filename)
|
|
58
|
+
elif extension == ".parquet":
|
|
59
|
+
df = pd.read_parquet(filename)
|
|
60
|
+
else:
|
|
61
|
+
raise Exception("file must be csv or parquet")
|
|
62
|
+
return df
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def load_recording(filename: str) -> (np.array, np.array):
|
|
66
|
+
"""Load recording of EEG and EMG time series data
|
|
67
|
+
|
|
68
|
+
:param filename: filename
|
|
69
|
+
:return: arrays of EEG and EMG data
|
|
70
|
+
"""
|
|
71
|
+
df = load_csv_or_parquet(filename)
|
|
72
|
+
eeg = df[EEG_COL].values
|
|
73
|
+
emg = df[EMG_COL].values
|
|
74
|
+
return eeg, emg
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def load_labels(filename: str) -> (np.array, np.array):
|
|
78
|
+
"""Load file of brain state labels and confidence scores
|
|
79
|
+
|
|
80
|
+
:param filename: filename
|
|
81
|
+
:return: array of brain state labels and, optionally, array of confidence scores
|
|
82
|
+
"""
|
|
83
|
+
df = load_csv_or_parquet(filename)
|
|
84
|
+
if CONFIDENCE_SCORE_COL in df.columns:
|
|
85
|
+
return df[BRAIN_STATE_COL].values, df[CONFIDENCE_SCORE_COL].values
|
|
86
|
+
else:
|
|
87
|
+
return df[BRAIN_STATE_COL].values, None
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def save_labels(
|
|
91
|
+
labels: np.array, filename: str, confidence_scores: np.array = None
|
|
92
|
+
) -> None:
|
|
93
|
+
"""Save brain state labels to file
|
|
94
|
+
|
|
95
|
+
:param labels: brain state labels
|
|
96
|
+
:param filename: filename
|
|
97
|
+
:param confidence_scores: optional confidence scores
|
|
98
|
+
"""
|
|
99
|
+
if confidence_scores is not None:
|
|
100
|
+
pd.DataFrame(
|
|
101
|
+
{BRAIN_STATE_COL: labels, CONFIDENCE_SCORE_COL: confidence_scores}
|
|
102
|
+
).to_csv(filename, index=False)
|
|
103
|
+
else:
|
|
104
|
+
pd.DataFrame({BRAIN_STATE_COL: labels}).to_csv(filename, index=False)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def load_config() -> tuple[BrainStateSet, int | float, bool]:
|
|
108
|
+
"""Load configuration file with brain state options
|
|
109
|
+
|
|
110
|
+
:return: set of brain state options, other settings
|
|
111
|
+
"""
|
|
112
|
+
with open(
|
|
113
|
+
os.path.join(os.path.dirname(os.path.abspath(__file__)), CONFIG_FILE), "r"
|
|
114
|
+
) as f:
|
|
115
|
+
data = json.load(f)
|
|
116
|
+
|
|
117
|
+
return (
|
|
118
|
+
BrainStateSet(
|
|
119
|
+
[BrainState(**b) for b in data[BRAIN_STATES_KEY]], UNDEFINED_LABEL
|
|
120
|
+
),
|
|
121
|
+
data[DEFAULT_EPOCH_LENGTH_KEY],
|
|
122
|
+
data.get(DEFAULT_CONFIDENCE_SETTING_KEY, True),
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def save_config(
|
|
127
|
+
brain_state_set: BrainStateSet,
|
|
128
|
+
default_epoch_length: int | float,
|
|
129
|
+
save_confidence_setting: bool,
|
|
130
|
+
) -> None:
|
|
131
|
+
"""Save configuration of brain state options to json file
|
|
132
|
+
|
|
133
|
+
:param brain_state_set: set of brain state options
|
|
134
|
+
:param default_epoch_length: epoch length to use when the GUI starts
|
|
135
|
+
:param save_confidence_setting: whether the option to save confidence
|
|
136
|
+
scores should be True by default
|
|
137
|
+
"""
|
|
138
|
+
output_dict = brain_state_set.to_output_dict()
|
|
139
|
+
output_dict.update({DEFAULT_EPOCH_LENGTH_KEY: default_epoch_length})
|
|
140
|
+
output_dict.update({DEFAULT_CONFIDENCE_SETTING_KEY: save_confidence_setting})
|
|
141
|
+
with open(
|
|
142
|
+
os.path.join(os.path.dirname(os.path.abspath(__file__)), CONFIG_FILE), "w"
|
|
143
|
+
) as f:
|
|
144
|
+
json.dump(output_dict, f, indent=4)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def load_recording_list(filename: str) -> list[Recording]:
|
|
148
|
+
"""Load list of recordings from file
|
|
149
|
+
|
|
150
|
+
:param filename: filename of list of recordings
|
|
151
|
+
:return: list of recordings
|
|
152
|
+
"""
|
|
153
|
+
with open(filename, "r") as f:
|
|
154
|
+
data = json.load(f)
|
|
155
|
+
recording_list = [Recording(**r) for r in data[RECORDING_LIST_NAME]]
|
|
156
|
+
for i, r in enumerate(recording_list):
|
|
157
|
+
r.name = i + 1
|
|
158
|
+
return recording_list
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def save_recording_list(filename: str, recordings: list[Recording]) -> None:
|
|
162
|
+
"""Save list of recordings to file
|
|
163
|
+
|
|
164
|
+
:param filename: where to save the list
|
|
165
|
+
:param recordings: list of recordings to export
|
|
166
|
+
"""
|
|
167
|
+
recording_dict = {
|
|
168
|
+
RECORDING_LIST_NAME: [
|
|
169
|
+
{
|
|
170
|
+
"recording_file": r.recording_file,
|
|
171
|
+
"label_file": r.label_file,
|
|
172
|
+
"calibration_file": r.calibration_file,
|
|
173
|
+
"sampling_rate": r.sampling_rate,
|
|
174
|
+
}
|
|
175
|
+
for r in recordings
|
|
176
|
+
]
|
|
177
|
+
}
|
|
178
|
+
with open(filename, "w") as f:
|
|
179
|
+
json.dump(recording_dict, f, indent=4)
|
|
File without changes
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|