accusleepy 0.8.0__py3-none-any.whl → 0.8.1__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/bouts.py CHANGED
@@ -11,7 +11,7 @@ class Bout:
11
11
 
12
12
  length: int # length, in number of epochs
13
13
  start_index: int # index where bout starts
14
- end_index: int # index where bout ends
14
+ end_index: int # index where bout ends (non-inclusive)
15
15
  surrounding_state: int # brain state on both sides of the bout
16
16
 
17
17
 
@@ -41,6 +41,44 @@ def find_last_adjacent_bout(sorted_bouts: list[Bout], bout_index: int) -> int:
41
41
  return bout_index
42
42
 
43
43
 
44
+ def find_short_bouts(
45
+ labels: np.array, min_epochs: int, brain_states: set[int]
46
+ ) -> list[Bout]:
47
+ """Locate all brain state bouts below a minimum length
48
+
49
+ :param labels: brain state labels (digits in the 0-9 range)
50
+ :param min_epochs: minimum number of epochs in a bout
51
+ :param brain_states: set of brain states in the labels
52
+ :return: list of Bout objects
53
+ """
54
+ # convert labels to a string for regex search
55
+ # There is probably a regex that can find all patterns like ab+a
56
+ # without consuming each "a" but I haven't found it :(
57
+ label_string = "".join(labels.astype(str))
58
+ bouts = list()
59
+ for state in brain_states:
60
+ for other_state in brain_states:
61
+ if state == other_state:
62
+ continue
63
+ # get start and end indices of each bout
64
+ expression = (
65
+ f"(?<={other_state}){state}{{1,{min_epochs - 1}}}(?={other_state})"
66
+ )
67
+ matches = re.finditer(expression, label_string)
68
+ spans = [match.span() for match in matches]
69
+
70
+ for span in spans:
71
+ bouts.append(
72
+ Bout(
73
+ length=span[1] - span[0],
74
+ start_index=span[0],
75
+ end_index=span[1],
76
+ surrounding_state=other_state,
77
+ )
78
+ )
79
+ return bouts
80
+
81
+
44
82
  def enforce_min_bout_length(
45
83
  labels: np.array, epoch_length: int | float, min_bout_length: int | float
46
84
  ) -> np.array:
@@ -61,11 +99,9 @@ def enforce_min_bout_length(
61
99
  :param min_bout_length: minimum bout length, in seconds
62
100
  :return: updated brain state labels
63
101
  """
64
- # if recording is very short, don't change anything
65
- if labels.size < 3:
66
- return labels
67
-
68
- if epoch_length == min_bout_length:
102
+ # if the recording is very short or the minimum bout length
103
+ # is one epoch long, don't change anything
104
+ if labels.size < 3 or epoch_length == min_bout_length:
69
105
  return labels
70
106
 
71
107
  # get minimum number of epochs in a bout
@@ -73,36 +109,8 @@ def enforce_min_bout_length(
73
109
  # get set of states in the labels
74
110
  brain_states = set(labels.tolist())
75
111
 
76
- while True: # so true
77
- # convert labels to a string for regex search
78
- # There is probably a regex that can find all patterns like ab+a
79
- # without consuming each "a" but I haven't found it :(
80
- label_string = "".join(labels.astype(str))
81
-
82
- bouts = list()
83
-
84
- for state in brain_states:
85
- for other_state in brain_states:
86
- if state == other_state:
87
- continue
88
- # get start and end indices of each bout
89
- expression = (
90
- f"(?<={other_state}){state}{{1,{min_epochs - 1}}}(?={other_state})"
91
- )
92
- matches = re.finditer(expression, label_string)
93
- spans = [match.span() for match in matches]
94
-
95
- # if some bouts were found
96
- for span in spans:
97
- bouts.append(
98
- Bout(
99
- length=span[1] - span[0],
100
- start_index=span[0],
101
- end_index=span[1],
102
- surrounding_state=other_state,
103
- )
104
- )
105
-
112
+ while True:
113
+ bouts = find_short_bouts(labels, min_epochs, brain_states)
106
114
  if len(bouts) == 0:
107
115
  break
108
116
 
accusleepy/fileio.py CHANGED
@@ -29,6 +29,21 @@ class Hyperparameters:
29
29
  training_epochs: int
30
30
 
31
31
 
32
+ @dataclass
33
+ class AccuSleePyConfig:
34
+ """AccuSleePy configuration settings"""
35
+
36
+ brain_state_set: BrainStateSet
37
+ default_epoch_length: int | float
38
+ overwrite_setting: bool
39
+ save_confidence_setting: bool
40
+ min_bout_length: int | float
41
+ emg_filter: EMGFilter
42
+ hyperparameters: Hyperparameters
43
+ epochs_to_show: int
44
+ autoscroll_state: bool
45
+
46
+
32
47
  @dataclass
33
48
  class Recording:
34
49
  """Store information about a recording"""
@@ -111,20 +126,11 @@ def save_labels(
111
126
  pd.DataFrame({c.BRAIN_STATE_COL: labels}).to_csv(filename, index=False)
112
127
 
113
128
 
114
- def load_config() -> tuple[
115
- BrainStateSet,
116
- int | float,
117
- bool,
118
- bool,
119
- int | float,
120
- EMGFilter,
121
- Hyperparameters,
122
- int,
123
- bool,
124
- ]:
129
+ def load_config() -> AccuSleePyConfig:
125
130
  """Load configuration file with brain state options
126
131
 
127
- :return: set of brain state options,
132
+ :return: AccuSleePyConfig containing the following:
133
+ set of brain state options,
128
134
  default epoch length,
129
135
  default overwrite setting,
130
136
  default confidence score output setting,
@@ -139,15 +145,21 @@ def load_config() -> tuple[
139
145
  ) as f:
140
146
  data = json.load(f)
141
147
 
142
- return (
143
- BrainStateSet(
148
+ return AccuSleePyConfig(
149
+ brain_state_set=BrainStateSet(
144
150
  [BrainState(**b) for b in data[BRAIN_STATES_KEY]], c.UNDEFINED_LABEL
145
151
  ),
146
- data[c.DEFAULT_EPOCH_LENGTH_KEY],
147
- data.get(c.DEFAULT_OVERWRITE_KEY, c.DEFAULT_OVERWRITE_SETTING),
148
- data.get(c.DEFAULT_CONFIDENCE_SETTING_KEY, c.DEFAULT_CONFIDENCE_SETTING),
149
- data.get(c.DEFAULT_MIN_BOUT_LENGTH_KEY, c.DEFAULT_MIN_BOUT_LENGTH),
150
- EMGFilter(
152
+ default_epoch_length=data[c.DEFAULT_EPOCH_LENGTH_KEY],
153
+ overwrite_setting=data.get(
154
+ c.DEFAULT_OVERWRITE_KEY, c.DEFAULT_OVERWRITE_SETTING
155
+ ),
156
+ save_confidence_setting=data.get(
157
+ c.DEFAULT_CONFIDENCE_SETTING_KEY, c.DEFAULT_CONFIDENCE_SETTING
158
+ ),
159
+ min_bout_length=data.get(
160
+ c.DEFAULT_MIN_BOUT_LENGTH_KEY, c.DEFAULT_MIN_BOUT_LENGTH
161
+ ),
162
+ emg_filter=EMGFilter(
151
163
  **data.get(
152
164
  c.EMG_FILTER_KEY,
153
165
  {
@@ -157,7 +169,7 @@ def load_config() -> tuple[
157
169
  },
158
170
  )
159
171
  ),
160
- Hyperparameters(
172
+ hyperparameters=Hyperparameters(
161
173
  **data.get(
162
174
  c.HYPERPARAMETERS_KEY,
163
175
  {
@@ -168,8 +180,8 @@ def load_config() -> tuple[
168
180
  },
169
181
  )
170
182
  ),
171
- data.get(c.EPOCHS_TO_SHOW_KEY, c.DEFAULT_EPOCHS_TO_SHOW),
172
- data.get(c.AUTOSCROLL_KEY, c.DEFAULT_AUTOSCROLL_STATE),
183
+ epochs_to_show=data.get(c.EPOCHS_TO_SHOW_KEY, c.DEFAULT_EPOCHS_TO_SHOW),
184
+ autoscroll_state=data.get(c.AUTOSCROLL_KEY, c.DEFAULT_AUTOSCROLL_STATE),
173
185
  )
174
186
 
175
187
 
Binary file
accusleepy/gui/main.py CHANGED
@@ -113,17 +113,16 @@ class AccuSleepWindow(QMainWindow):
113
113
  self.setWindowTitle("AccuSleePy")
114
114
 
115
115
  # fill in settings tab
116
- (
117
- self.brain_state_set,
118
- self.epoch_length,
119
- self.only_overwrite_undefined,
120
- self.save_confidence_scores,
121
- self.min_bout_length,
122
- self.emg_filter,
123
- self.hyperparameters,
124
- self.default_epochs_to_show,
125
- self.default_autoscroll_state,
126
- ) = load_config()
116
+ config = load_config()
117
+ self.brain_state_set = config.brain_state_set
118
+ self.epoch_length = config.default_epoch_length
119
+ self.only_overwrite_undefined = config.overwrite_setting
120
+ self.save_confidence_scores = config.save_confidence_setting
121
+ self.min_bout_length = config.min_bout_length
122
+ self.emg_filter = config.emg_filter
123
+ self.hyperparameters = config.hyperparameters
124
+ self.default_epochs_to_show = config.epochs_to_show
125
+ self.default_autoscroll_state = config.autoscroll_state
127
126
 
128
127
  self.settings_widgets = None
129
128
  self.initialize_settings_tab()
@@ -139,18 +139,10 @@ class ManualScoringWindow(QDialog):
139
139
  self.ui.setupUi(self)
140
140
  self.setWindowTitle("AccuSleePy manual scoring window")
141
141
 
142
- # load set of valid brain states
143
- (
144
- self.brain_state_set,
145
- _,
146
- _,
147
- _,
148
- _,
149
- _,
150
- _,
151
- self.epochs_to_show,
152
- self.autoscroll_state,
153
- ) = load_config()
142
+ config = load_config()
143
+ self.brain_state_set = config.brain_state_set
144
+ self.epochs_to_show = config.epochs_to_show
145
+ self.autoscroll_state = config.autoscroll_state
154
146
 
155
147
  # find the set of y-axis locations of valid brain state labels
156
148
  self.label_display_options = convert_labels(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: accusleepy
3
- Version: 0.8.0
3
+ Version: 0.8.1
4
4
  Summary: Python implementation of AccuSleep
5
5
  License: GPL-3.0-only
6
6
  Author: Zeke Barger
@@ -80,6 +80,7 @@ please consult the [developer guide](accusleepy/gui/text/dev_guide.md).
80
80
 
81
81
  ## Changelog
82
82
 
83
+ - 0.8.1: Increased test coverage
83
84
  - 0.8.0: More configurable settings, visual improvements
84
85
  - 0.7.1-0.7.3: Bugfixes, code cleanup
85
86
  - 0.7.0: More settings can be configured in the UI
@@ -87,10 +88,7 @@ please consult the [developer guide](accusleepy/gui/text/dev_guide.md).
87
88
  since the new calibration feature will make the confidence scores more accurate.
88
89
  - 0.5.0: Performance improvements
89
90
  - 0.4.5: Added support for python 3.13, **removed support for python 3.10.**
90
- - 0.4.4: Performance improvements
91
- - 0.4.3: Improved unit tests and user manuals
92
- - 0.4.0: Improved visuals and user manuals
93
- - 0.1.0-0.3.1: Early development versions
91
+ - 0.1.0-0.4.4: Early development versions
94
92
 
95
93
  ## Screenshots
96
94
 
@@ -1,11 +1,11 @@
1
1
  accusleepy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  accusleepy/__main__.py,sha256=dKzl2N2Hg9lD264CWYNxThRyDKzWwyMwHRXmJxOmMis,104
3
- accusleepy/bouts.py,sha256=F_y6DxnpKFfImYb7vCZluZ2eD5I_33gZXmRM8mvebsg,5679
3
+ accusleepy/bouts.py,sha256=biJEzCjMQR-RTlQcfeomkp6NxcA5FXkhE8Kp2XyL4P4,6039
4
4
  accusleepy/brain_state_set.py,sha256=fRkrArHLIbEKimub804yt_mUXoyfsjJEfiJnTjeCMkY,3233
5
5
  accusleepy/classification.py,sha256=mF35xMrD9QXGldSnl3vkdHbm7CAptPUNjHxUA_agOTA,9778
6
6
  accusleepy/config.json,sha256=VmUFsiGD1ymEyjdzqeM5nTp8jWvDI-DIxLy1_92nueo,875
7
7
  accusleepy/constants.py,sha256=62mmsr1NKzF-psS-9esuAE65kAcPL6o8v9UXQEvb5yc,2983
8
- accusleepy/fileio.py,sha256=iWUQtWCSL9hG3eQC8-RXJUrHv149PBxM3IjYKaUcMFk,7981
8
+ accusleepy/fileio.py,sha256=-aEgp2oonjQKRizVI1uI5CGknnBOxE6HG0DzxDYbSkM,8512
9
9
  accusleepy/gui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  accusleepy/gui/icons/brightness_down.png,sha256=PLT1fb83RHIhSRuU7MMMx0G7oJAY7o9wUcnqM8veZfM,12432
11
11
  accusleepy/gui/icons/brightness_up.png,sha256=64GnUqgPvN5xZ6Um3wOzwqvUmdAWYZT6eFmWpBsHyks,12989
@@ -18,11 +18,11 @@ accusleepy/gui/icons/save.png,sha256=J3EA8iU1BqLYRSsrq_OdoZlqrv2yfL7oV54DklTy_DI
18
18
  accusleepy/gui/icons/up_arrow.png,sha256=V9yF9t1WgjPaUu-mF1YGe_DfaRHg2dUpR_sUVVcvVvY,3329
19
19
  accusleepy/gui/icons/zoom_in.png,sha256=MFWnKZp7Rvh4bLPq4Cqo4sB_jQYedUUtT8-ZO8tNYyc,13589
20
20
  accusleepy/gui/icons/zoom_out.png,sha256=IB8Jecb3i0U4qjWRR46ridjLpvLCSe7PozBaLqQqYSw,13055
21
- accusleepy/gui/images/primary_window.png,sha256=jI_E2oZZN-Ajb4_5n-jVlNT7OkEPrK50xK2WOJnaiBc,598184
21
+ accusleepy/gui/images/primary_window.png,sha256=yRGUdIcByF8DtPtDWqjmnQ8J3IHKtmijBsT7N9e1Ij0,595764
22
22
  accusleepy/gui/images/viewer_window.png,sha256=b_B7m9WSLMAOzNjctq76SyekO1WfC6qYZVNnYfhjPe8,977197
23
23
  accusleepy/gui/images/viewer_window_annotated.png,sha256=uMNUmsZIdzDlQpyoiS3lJGoWlg_T325Oj5hDZhM3Y14,146817
24
- accusleepy/gui/main.py,sha256=GdxQXdg0kxCaJzClvRiN95A6pQjZ-jBoOb2YyInKvyc,58253
25
- accusleepy/gui/manual_scoring.py,sha256=woi4LxsUkHfNnjPGKdSFWyynuti1rWFrar6IJP7HyKA,40773
24
+ accusleepy/gui/main.py,sha256=cZQH0qJ_mykeQP7eadc1yzFHYeDwbRngrR4_H1wMxWY,58438
25
+ accusleepy/gui/manual_scoring.py,sha256=QCFF-CIU6nh26NB8Z9ktohCk8p7ola2hgjazD-OrK_o,40697
26
26
  accusleepy/gui/mplwidget.py,sha256=rJSTtWmLjHn8r3c9Kb23Rc4XzXl3i9B-JrjNjjlNnmQ,13492
27
27
  accusleepy/gui/primary_window.py,sha256=qqV-GAC3BgOus1lJMOg2U4AGQbhy35zLMyN8Q7ouTd8,141479
28
28
  accusleepy/gui/primary_window.ui,sha256=2mD0G6b8bsyyUvMCUosQ0K-nAzMA2iiP3yMpeh9INcQ,208209
@@ -38,6 +38,6 @@ accusleepy/multitaper.py,sha256=D5-iglwkFBRciL5tKSNcunMtcq0rM3zHwRHUVPgem1U,2567
38
38
  accusleepy/signal_processing.py,sha256=47fEAx8Aqqkiqix1ai2YEK9Fhq6UHoQcwAcOi-a8ewo,16834
39
39
  accusleepy/temperature_scaling.py,sha256=glvPcvxHpBdFjwjGfZdNku9L_BozycEmdqZhKKUCCNg,5749
40
40
  accusleepy/validation.py,sha256=VpLWK-wD5tCU6lTBG3KYgTi3PWGuYh6NitMgMoMH8JM,4434
41
- accusleepy-0.8.0.dist-info/METADATA,sha256=gnk8O1By632zTCFJG9ifqkQDDSEDTqggGUpG8F-WPgs,4800
42
- accusleepy-0.8.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
43
- accusleepy-0.8.0.dist-info/RECORD,,
41
+ accusleepy-0.8.1.dist-info/METADATA,sha256=29kPvzKr2ykosWwidIt6FKrjvIY-m88Ui9GQPoQPN-g,4710
42
+ accusleepy-0.8.1.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
43
+ accusleepy-0.8.1.dist-info/RECORD,,