misleep 0.2.3__tar.gz → 0.2.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. {misleep-0.2.3 → misleep-0.2.4}/PKG-INFO +1 -1
  2. {misleep-0.2.3 → misleep-0.2.4}/misleep/analysis/auto_stage.py +52 -30
  3. misleep-0.2.4/misleep/analysis/auto_stage_model/P30_EEG_F_lightgbm.pkl +0 -0
  4. misleep-0.2.4/misleep/analysis/auto_stage_model/P30_EEG_P_lightgbm.pkl +0 -0
  5. misleep-0.2.4/misleep/analysis/auto_stage_model/ado_EEG_F_lightgbm.pkl +0 -0
  6. misleep-0.2.4/misleep/analysis/auto_stage_model/ado_EEG_P_lightgbm.pkl +0 -0
  7. misleep-0.2.4/misleep/analysis/auto_stage_model/adult_EEG_F_lightgbm.pkl +0 -0
  8. misleep-0.2.4/misleep/analysis/auto_stage_model/adult_EEG_P_lightgbm.pkl +0 -0
  9. {misleep-0.2.3 → misleep-0.2.4}/misleep/config.ini +3 -4
  10. {misleep-0.2.3 → misleep-0.2.4}/misleep/gui/dialog.py +10 -4
  11. {misleep-0.2.3 → misleep-0.2.4}/misleep/gui/main_window.py +12 -7
  12. {misleep-0.2.3 → misleep-0.2.4}/misleep/gui/uis/auto_stage_dialog_ui.py +26 -9
  13. {misleep-0.2.3 → misleep-0.2.4}/misleep/io/annotation_io.py +28 -0
  14. {misleep-0.2.3 → misleep-0.2.4}/misleep.egg-info/PKG-INFO +1 -1
  15. {misleep-0.2.3 → misleep-0.2.4}/misleep.egg-info/SOURCES.txt +6 -3
  16. {misleep-0.2.3 → misleep-0.2.4}/setup.py +7 -3
  17. misleep-0.2.3/misleep/analysis/auto_stage_model/EEG_F_lightgbm_20241221.pkl +0 -0
  18. misleep-0.2.3/misleep/analysis/auto_stage_model/EEG_P_lightgbm_20241221.pkl +0 -0
  19. misleep-0.2.3/misleep/analysis/classification.py +0 -0
  20. {misleep-0.2.3 → misleep-0.2.4}/LICENSE +0 -0
  21. {misleep-0.2.3 → misleep-0.2.4}/README.md +0 -0
  22. {misleep-0.2.3 → misleep-0.2.4}/misleep/__init__.py +0 -0
  23. {misleep-0.2.3 → misleep-0.2.4}/misleep/__main__.py +0 -0
  24. {misleep-0.2.3 → misleep-0.2.4}/misleep/analysis/__init__.py +0 -0
  25. {misleep-0.2.3 → misleep-0.2.4}/misleep/analysis/detection.py +0 -0
  26. {misleep-0.2.3 → misleep-0.2.4}/misleep/gui/__init__.py +0 -0
  27. {misleep-0.2.3 → misleep-0.2.4}/misleep/gui/about.py +0 -0
  28. {misleep-0.2.3 → misleep-0.2.4}/misleep/gui/resources/__init__.py +0 -0
  29. {misleep-0.2.3 → misleep-0.2.4}/misleep/gui/resources/entire_logo.png +0 -0
  30. {misleep-0.2.3 → misleep-0.2.4}/misleep/gui/resources/logo.png +0 -0
  31. {misleep-0.2.3 → misleep-0.2.4}/misleep/gui/resources/misleep.py +0 -0
  32. {misleep-0.2.3 → misleep-0.2.4}/misleep/gui/resources/misleep.qrc +0 -0
  33. {misleep-0.2.3 → misleep-0.2.4}/misleep/gui/show.py +0 -0
  34. {misleep-0.2.3 → misleep-0.2.4}/misleep/gui/spec_window.py +0 -0
  35. {misleep-0.2.3 → misleep-0.2.4}/misleep/gui/thread.py +0 -0
  36. {misleep-0.2.3 → misleep-0.2.4}/misleep/gui/uis/SWA_detect_dialog_ui.py +0 -0
  37. {misleep-0.2.3 → misleep-0.2.4}/misleep/gui/uis/__init__.py +0 -0
  38. {misleep-0.2.3 → misleep-0.2.4}/misleep/gui/uis/about_ui.py +0 -0
  39. {misleep-0.2.3 → misleep-0.2.4}/misleep/gui/uis/horizontal_line_dialog_ui.py +0 -0
  40. {misleep-0.2.3 → misleep-0.2.4}/misleep/gui/uis/label_dialog_ui.py +0 -0
  41. {misleep-0.2.3 → misleep-0.2.4}/misleep/gui/uis/main_window_ui.py +0 -0
  42. {misleep-0.2.3 → misleep-0.2.4}/misleep/gui/uis/save_data_dialog_ui.py +0 -0
  43. {misleep-0.2.3 → misleep-0.2.4}/misleep/gui/uis/spec_window_ui.py +0 -0
  44. {misleep-0.2.3 → misleep-0.2.4}/misleep/gui/uis/spindle_detect_dialog_ui.py +0 -0
  45. {misleep-0.2.3 → misleep-0.2.4}/misleep/gui/uis/state_spectral_dialog_ui.py +0 -0
  46. {misleep-0.2.3 → misleep-0.2.4}/misleep/gui/uis/transfer_result_dialog_ui.py +0 -0
  47. {misleep-0.2.3 → misleep-0.2.4}/misleep/gui/utils.py +0 -0
  48. {misleep-0.2.3 → misleep-0.2.4}/misleep/io/__init__.py +0 -0
  49. {misleep-0.2.3 → misleep-0.2.4}/misleep/io/base.py +0 -0
  50. {misleep-0.2.3 → misleep-0.2.4}/misleep/io/signal_io.py +0 -0
  51. {misleep-0.2.3 → misleep-0.2.4}/misleep/preprocessing/__init__.py +0 -0
  52. {misleep-0.2.3 → misleep-0.2.4}/misleep/preprocessing/channel.py +0 -0
  53. {misleep-0.2.3 → misleep-0.2.4}/misleep/preprocessing/signals.py +0 -0
  54. {misleep-0.2.3 → misleep-0.2.4}/misleep/preprocessing/spectral.py +0 -0
  55. {misleep-0.2.3 → misleep-0.2.4}/misleep/utils/__init__.py +0 -0
  56. {misleep-0.2.3 → misleep-0.2.4}/misleep/utils/annotation.py +0 -0
  57. {misleep-0.2.3 → misleep-0.2.4}/misleep/utils/logger_handler.py +0 -0
  58. {misleep-0.2.3 → misleep-0.2.4}/misleep/utils/signals.py +0 -0
  59. {misleep-0.2.3 → misleep-0.2.4}/misleep/viz/__init__.py +0 -0
  60. {misleep-0.2.3 → misleep-0.2.4}/misleep/viz/hypnogram.py +0 -0
  61. {misleep-0.2.3 → misleep-0.2.4}/misleep/viz/signals.py +0 -0
  62. {misleep-0.2.3 → misleep-0.2.4}/misleep/viz/spectral.py +0 -0
  63. {misleep-0.2.3 → misleep-0.2.4}/misleep.egg-info/dependency_links.txt +0 -0
  64. {misleep-0.2.3 → misleep-0.2.4}/misleep.egg-info/requires.txt +0 -0
  65. {misleep-0.2.3 → misleep-0.2.4}/misleep.egg-info/top_level.txt +0 -0
  66. {misleep-0.2.3 → misleep-0.2.4}/setup.cfg +0 -0
  67. {misleep-0.2.3 → misleep-0.2.4}/test/test_annotation_io.py +0 -0
  68. {misleep-0.2.3 → misleep-0.2.4}/test/test_loadmat73.py +0 -0
  69. {misleep-0.2.3 → misleep-0.2.4}/test/test_midata.py +0 -0
  70. {misleep-0.2.3 → misleep-0.2.4}/test/test_show.py +0 -0
  71. {misleep-0.2.3 → misleep-0.2.4}/test/test_signal_io.py +0 -0
  72. {misleep-0.2.3 → misleep-0.2.4}/test/test_signals_viz.py +0 -0
  73. {misleep-0.2.3 → misleep-0.2.4}/test/test_spectral_viz.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: misleep
3
- Version: 0.2.3
3
+ Version: 0.2.4
4
4
  Summary: MiSleep: Mice Sleep EEG/EMG visualization, scoring and analysis.
5
5
  Home-page: https://github.com/BryanWang0702/MiSleep/
6
6
  Download-URL: https://github.com/BryanWang0702/MiSleep/
@@ -6,6 +6,7 @@ from scipy import stats
6
6
  import antropy
7
7
  import joblib
8
8
  import copy
9
+ import lightgbm
9
10
 
10
11
 
11
12
  def filter_power_line_noise(data, sf, noise_band='50-100-150'):
@@ -33,7 +34,7 @@ def split_window_data(data, sf, state, window_length=20, stride_length=5):
33
34
  """
34
35
 
35
36
  # If the data is shorter than the window length, remove it
36
- if data.shape[0]/sf < 20:
37
+ if data.shape[0]/sf < window_length:
37
38
  return []
38
39
 
39
40
  window_data = []
@@ -45,15 +46,24 @@ def split_window_data(data, sf, state, window_length=20, stride_length=5):
45
46
 
46
47
  return window_data
47
48
 
48
- def delta_theta_ratio(data, sf):
49
+ def delta_theta_ratio_theta(data, sf):
49
50
  """Calculate the delta/theta ratio from the original signal data
50
51
  Note, here the data is 20 seconds, we only need the ratio from the 5 seconds beginning
51
52
  """
52
53
  freq, t, Sxx = misleep.spectrogram(data, sf, window=1)
53
54
  band_second = np.where(t < 5)
54
55
  psd = np.sum(np.array([each[band_second] for each in Sxx]), axis=1)
55
- band_power = misleep.band_power(psd, freq, bands=[[0.5, 4, 'delta'], [5, 9, 'theta']])
56
- return band_power['delta'] / band_power['theta']
56
+ band_power = misleep.band_power(psd, freq, bands=[[0.5, 4, 'delta'], [5, 9, 'theta']], relative=True)
57
+ return band_power['delta'] / band_power['theta'], band_power['theta']
58
+
59
+ def self_zscore(feature, quantile=0.95):
60
+ """Zscore the extracted features from the signal data, to exclude the abnormal signal, use 0.95 quantile
61
+ Return the quantile zscore feature data
62
+ """
63
+ upper_quantile = np.quantile(feature, quantile)
64
+ feature = [each if each < upper_quantile else upper_quantile for each in feature]
65
+ return (feature - np.mean(feature)) / np.std(feature)
66
+
57
67
 
58
68
  def get_data_features(data, sf, data_format='EEG'):
59
69
  """ Get data features, data format can be 'EEG' or 'EMG'
@@ -67,11 +77,8 @@ def get_data_features(data, sf, data_format='EEG'):
67
77
  # Time-domain features, both EEG and EMG
68
78
  # 1. standard deviation
69
79
  data_std = np.array([np.std(each[0][:int(5*sf)]) for each in data])
70
- # Set those abnormal points to the upper quartile
71
- data_std_upper_quantile = np.quantile(data_std, 0.95)
72
- data_std = [each if each < data_std_upper_quantile else data_std_upper_quantile for each in data_std]
73
80
  # Z-score the std features
74
- window_feature_df[f'{data_format}_std_zscore'] = (data_std - np.mean(data_std)) / np.std(data_std)
81
+ window_feature_df[f'{data_format}_std_zscore'] = self_zscore(data_std)
75
82
 
76
83
  # 2. Zero crossing rate for EEG and EMG
77
84
  zerocross_rate = [antropy.num_zerocross(each[0][:int(5*sf)]) / (5*sf) for each in data]
@@ -81,46 +88,60 @@ def get_data_features(data, sf, data_format='EEG'):
81
88
  hjorth = [antropy.hjorth_params(each[0][:int(5*sf)]) for each in data]
82
89
  hjorth_M = [each[0] for each in hjorth]
83
90
  hjorth_C = [each[1] for each in hjorth]
84
- window_feature_df[f'{data_format}_Hjorth_M'] = (hjorth_M - np.mean(hjorth_M)) / np.std(hjorth_M)
85
- window_feature_df[f'{data_format}_Hjorth_C'] = (hjorth_C - np.mean(hjorth_C)) / np.std(hjorth_C)
91
+ window_feature_df[f'{data_format}_Hjorth_M'] = self_zscore(hjorth_M)
92
+ window_feature_df[f'{data_format}_Hjorth_C'] = self_zscore(hjorth_C)
86
93
 
87
94
  # 4. Permutation entropy
88
95
  perm_entropy= [antropy.perm_entropy(each[0][:int(5*sf)]) for each in data]
89
- window_feature_df[f'{data_format}_perm_entropy'] = (perm_entropy - np.mean(perm_entropy)) / np.std(perm_entropy)
96
+ window_feature_df[f'{data_format}_perm_entropy'] = self_zscore(perm_entropy)
90
97
 
91
98
  # Some features only with EEG
92
99
  if data_format.startswith('EEG'):
93
100
  # 1. Skewness and kurtosis for EEG signal(s)
94
101
  data_skewness = np.array([stats.skew(each[0][:int(5*sf)]) for each in data])
95
102
  data_kurtosis = np.array([stats.kurtosis(each[0][:int(5*sf)]) for each in data])
96
- window_feature_df[f'{data_format}_skewness_zscore'] = (data_skewness - np.mean(data_skewness)) / np.std(data_skewness)
97
- window_feature_df[f'{data_format}_kurtosis_zscore'] = (data_kurtosis - np.mean(data_kurtosis)) / np.std(data_kurtosis)
103
+ window_feature_df[f'{data_format}_skewness_zscore'] = self_zscore(data_skewness)
104
+ window_feature_df[f'{data_format}_kurtosis_zscore'] = self_zscore(data_kurtosis)
98
105
  # Frequency-domain features
99
106
  # 1. delta/theta
100
- delta_theta = [delta_theta_ratio(each[0], sf) for each in data]
101
- window_feature_df[f'{data_format}_delta_theta'] = (delta_theta - np.mean(delta_theta)) / np.std(delta_theta)
107
+ delta_theta = [delta_theta_ratio_theta(each[0], sf) for each in data]
108
+ delta_theta_ratio = [each[0] for each in delta_theta]
109
+ theta = [each[1] for each in delta_theta]
110
+ window_feature_df[f'{data_format}_delta_theta_ratio'] = self_zscore(delta_theta_ratio)
111
+ window_feature_df[f'{data_format}_theta'] = self_zscore(theta)
102
112
 
103
113
  return window_feature_df
104
114
 
105
- def result_constraints(pred_label):
115
+ def result_constraints(pred_prob):
106
116
  """
107
117
  Once finished the prediction, add some constraints to make the result more smooth
108
118
  1. No REM after Wake, set to NREM
109
119
  2. All one epoch between two same state will be set to the around state
110
120
  """
111
121
 
112
- pred_label = copy.deepcopy(pred_label)
113
- for idx in range(1, len(pred_label)-1):
114
- label_ = pred_label[idx]
115
- if label_ == 3 and pred_label[idx+1] == 2: # REM after Wake
116
- pred_label[idx+1] = 1
117
- if pred_label[idx-1] ==pred_label[idx+1]: # Same state previous and after
118
- pred_label[idx] = pred_label[idx-1]
122
+ """
123
+ Once finished the prediction, add some constraints to make the result more smooth
124
+ 1. REM threshold is lower, set to 0.15
125
+ 2. No REM after Wake, set to NREM
126
+ 3. All one epoch between two same state will be set to the around state
127
+ """
128
+
129
+ pred_prob = copy.deepcopy(pred_prob)
130
+ pred_label = [each+1 for each in np.argmax(pred_prob, axis=1)]
131
+ pred_label = [2 if each[1] > 0.1 else pred_label[idx] for idx, each in enumerate(pred_prob)] # REM threshold
132
+
133
+ # for idx in range(1, len(pred_label)-1):
134
+ # label_ = pred_label[idx]
135
+
136
+ # if label_ == 3 and pred_label[idx+1] == 2: # REM after Wake
137
+ # pred_label[idx+1] = 1
138
+ # if pred_label[idx-1] ==pred_label[idx+1]: # Same state previous and after
139
+ # pred_label[idx] = pred_label[idx-1]
119
140
 
120
141
  return pred_label
121
142
 
122
143
 
123
- def auto_stage_gbm(EEG, EMG, sf, EEG_channel='F'):
144
+ def auto_stage_gbm(EEG, EMG, label, sf, EEG_channel='F', mouse_age='adult'):
124
145
  """
125
146
  Auto stage with lightgbm method
126
147
 
@@ -134,12 +155,16 @@ def auto_stage_gbm(EEG, EMG, sf, EEG_channel='F'):
134
155
  Sampling frequency of the EEG and EMG data, should be the same.
135
156
  EEG_channel : string
136
157
  Specify the channel of EEG, frontal or parietal. Options: {'F', 'P'}. Default is 'F' for frontal.
158
+ mouse_age : string
159
+ Specify which age model to use. {'adult', 'ado', 'P30'}, default is 'adult'.
160
+ Here the adult is > P56, ado is P30~P56, P30 is less than P30.
137
161
 
138
162
  Return
139
163
  ------
140
164
  pred_label : list
141
165
  Predicted labels for every second. May less than the data length for about 15 seconds.
142
166
  """
167
+
143
168
  EEG = split_window_data(EEG, sf, state=4) # All set the initial state '4'
144
169
  EMG = split_window_data(EMG, sf, state=4)
145
170
 
@@ -147,12 +172,9 @@ def auto_stage_gbm(EEG, EMG, sf, EEG_channel='F'):
147
172
  window_feature_df = pd.concat([get_data_features(EEG, sf, data_format='EEG'), get_data_features(EMG, sf, data_format='EMG')], axis=1)
148
173
  window_feature_df = window_feature_df.filter(like='E')
149
174
 
150
- if EEG_channel == 'F':
151
- gbm_model = joblib.load(r'./misleep/analysis/auto_stage_model/EEG_F_lightgbm_20241221.pkl')
152
- if EEG_channel == 'P':
153
- gbm_model = joblib.load(r'./misleep/analysis/auto_stage_model/EEG_P_lightgbm_20241221.pkl')
175
+ gbm_model = joblib.load(f'./misleep/analysis/auto_stage_model/{mouse_age}_EEG_{EEG_channel}_lightgbm.pkl')
154
176
 
155
- pred_label = gbm_model.predict(window_feature_df, num_iteration=gbm_model.best_iteration_)
156
- pred_label = result_constraints(pred_label)
177
+ pred_prob = gbm_model.predict_proba(window_feature_df, num_iteration=gbm_model.best_iteration_)
178
+ pred_label = result_constraints(pred_prob)
157
179
  pred_label = [item for each in pred_label for item in [each]*5]
158
180
  return pred_label
@@ -1,7 +1,7 @@
1
1
  [gui]
2
- version = v0.2.3
3
- updatetime = 2024/12/23
4
- marker = ['long REM', 'first REM', 'WindEEG', 'W-R ', 'maker']
2
+ version = v0.2.4
3
+ updatetime = 2025/1/16
4
+ marker = ['good', 'first REM', 'WindEEG', 'W-R ', 'maker']
5
5
  startend = ['burst-supression', 'REM', 'Wake', 'Spindle', 'SWA', 'start end label', 'start end label']
6
6
  statemap = {"1": "NREM", "2": "REM", "3": "Wake", "4": "INIT", "5": "IS", "6": "MicroArousal"}
7
7
  statecolor = {"1": "orange", "2": "skyblue", "3": "red", "4": "white", "5": "green", "6": "pink"}
@@ -10,4 +10,3 @@ statecolorbgalpha = 0.1
10
10
  markerlinecolor = "red"
11
11
  startendlinecolor = "blue"
12
12
  openpath = E:
13
-
@@ -220,7 +220,7 @@ class transferResult_dialog(QDialog, Ui_TransferResultDialog):
220
220
  df, analyse_df, start_end_df, marker_df = transfer_result(mianno=mianno, ac_time=ac_time)
221
221
 
222
222
  fd, _ = QFileDialog.getSaveFileName(self, "Save transfered result",
223
- f"{config['gui']['openpath'].split('/')[0]}/transfer_result.xlsx",
223
+ f"{config['gui']['openpath']}",
224
224
  "*.xlsx;;")
225
225
  if fd == '':
226
226
  return
@@ -901,20 +901,26 @@ class AutoStageDialog(QDialog, Ui_AutoStageDialog):
901
901
  self.EMGchannelCombox.addItems(channels)
902
902
  self.EMGchannelCombox.setCurrentIndex(1)
903
903
 
904
- def auto_stage(self, midata):
904
+ def auto_stage(self, midata, mianno):
905
905
  """Auto stage with misleep data"""
906
906
 
907
907
  EEG_channel_idx = self.EEGChannelCombox.currentIndex()
908
908
  EMG_channel_idx = self.EMGchannelCombox.currentIndex()
909
909
  EEG = deepcopy(midata.signals[EEG_channel_idx])
910
910
  EMG = deepcopy(midata.signals[EMG_channel_idx])
911
+ label = deepcopy(mianno._sleep_state)
911
912
  sf = deepcopy(midata.sf[EEG_channel_idx])
912
913
 
913
914
  EEG_site = ['P', 'F'][self.EEGSiteCombox.currentIndex()]
915
+ mouse_age = ['adult', 'ado', 'P30'][self.AgeCombox.currentIndex()]
914
916
 
915
- pred_label = auto_stage_gbm(EEG=EEG, EMG=EMG, sf=sf, EEG_channel=EEG_site)
917
+ pred_label = auto_stage_gbm(EEG=EEG, EMG=EMG, label=label, sf=sf, EEG_channel=EEG_site, mouse_age=mouse_age)
918
+ if self.SaveAnnoCheckbox.isChecked():
919
+ save_anno = True
920
+ else:
921
+ save_anno = False
916
922
 
917
- return pred_label
923
+ return pred_label, save_anno
918
924
 
919
925
 
920
926
  def okEvent(self):
@@ -1624,11 +1624,13 @@ class main_window(QMainWindow, Ui_MiSleep):
1624
1624
  self.auto_stage_dialog.exec()
1625
1625
  if self.auto_stage_dialog.closed:
1626
1626
  return
1627
- auto_stage_lst = self.auto_stage_dialog.auto_stage(self.midata)
1627
+ auto_stage_lst, save_anno = self.auto_stage_dialog.auto_stage(self.midata, self.mianno)
1628
1628
 
1629
1629
  # Not sure which one is shorter, so get the minimum one
1630
1630
  self.mianno._sleep_state[:min(len(self.mianno._sleep_state),len(auto_stage_lst))] = auto_stage_lst[:min(len(self.mianno._sleep_state),len(auto_stage_lst))]
1631
1631
 
1632
+ if save_anno:
1633
+ self.save_anno()
1632
1634
  self.is_saved = False
1633
1635
  self.AnnotationPathLabel.setText('*Annotation path:')
1634
1636
  self.plot_signals()
@@ -1638,8 +1640,11 @@ class main_window(QMainWindow, Ui_MiSleep):
1638
1640
  QMessageBox.about(self, "Error", "Auto stage ERROR")
1639
1641
  return
1640
1642
 
1641
- def save_anno(self):
1642
- """Save annotation into file"""
1643
+ def save_anno(self, just_save=False):
1644
+ """Save annotation into file
1645
+ Just save: bool
1646
+ For when I only want to save a file but not cover the current labels
1647
+ """
1643
1648
  if self.anno_path == "":
1644
1649
  anno_path, _ = QFileDialog.getOpenFileName(
1645
1650
  self, "Select annotation file",
@@ -1649,15 +1654,15 @@ class main_window(QMainWindow, Ui_MiSleep):
1649
1654
 
1650
1655
  if anno_path == "":
1651
1656
  return
1652
- self.anno_path = anno_path
1653
- self.AnnoPathEdit.setText(self.anno_path)
1657
+ if not just_save:
1658
+ self.anno_path = anno_path
1659
+ self.AnnoPathEdit.setText(self.anno_path)
1654
1660
 
1655
1661
  save_thread = SaveThread(file=[self.mianno, self.midata],
1656
1662
  file_path=self.anno_path)
1657
1663
  saved = save_thread.save_anno()
1658
- if saved:
1664
+ if saved and not just_save:
1659
1665
  self.is_saved = True
1660
-
1661
1666
  self.AnnotationPathLabel.setText('Annotation path:')
1662
1667
  save_thread.quit()
1663
1668
 
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- # Form implementation generated from reading ui file '.\auto_stage_dialog.ui'
3
+ # Form implementation generated from reading ui file './misleep/gui/uis/auto_stage_dialog.ui'
4
4
  #
5
5
  # Created by: PyQt5 UI code generator 5.15.9
6
6
  #
@@ -14,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
14
14
  class Ui_AutoStageDialog(object):
15
15
  def setupUi(self, AutoStageDialog):
16
16
  AutoStageDialog.setObjectName("AutoStageDialog")
17
- AutoStageDialog.resize(347, 265)
17
+ AutoStageDialog.resize(408, 342)
18
18
  icon = QtGui.QIcon()
19
19
  icon.addPixmap(QtGui.QPixmap(":/logo/logo.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
20
20
  AutoStageDialog.setWindowIcon(icon)
@@ -30,26 +30,38 @@ class Ui_AutoStageDialog(object):
30
30
  self.groupBox.setObjectName("groupBox")
31
31
  self.gridLayout_2 = QtWidgets.QGridLayout(self.groupBox)
32
32
  self.gridLayout_2.setObjectName("gridLayout_2")
33
- self.label_2 = QtWidgets.QLabel(self.groupBox)
34
- self.label_2.setObjectName("label_2")
35
- self.gridLayout_2.addWidget(self.label_2, 2, 0, 1, 1)
33
+ self.AgeCombox = QtWidgets.QComboBox(self.groupBox)
34
+ self.AgeCombox.setObjectName("AgeCombox")
35
+ self.AgeCombox.addItem("")
36
+ self.AgeCombox.addItem("")
37
+ self.AgeCombox.addItem("")
38
+ self.gridLayout_2.addWidget(self.AgeCombox, 3, 1, 1, 2)
36
39
  self.label = QtWidgets.QLabel(self.groupBox)
37
40
  self.label.setObjectName("label")
38
41
  self.gridLayout_2.addWidget(self.label, 0, 0, 1, 1)
39
- self.label_8 = QtWidgets.QLabel(self.groupBox)
40
- self.label_8.setObjectName("label_8")
41
- self.gridLayout_2.addWidget(self.label_8, 1, 0, 1, 1)
42
+ self.label_3 = QtWidgets.QLabel(self.groupBox)
43
+ self.label_3.setObjectName("label_3")
44
+ self.gridLayout_2.addWidget(self.label_3, 3, 0, 1, 1)
42
45
  self.EMGchannelCombox = QtWidgets.QComboBox(self.groupBox)
43
46
  self.EMGchannelCombox.setObjectName("EMGchannelCombox")
44
47
  self.gridLayout_2.addWidget(self.EMGchannelCombox, 1, 1, 1, 2)
45
48
  self.EEGChannelCombox = QtWidgets.QComboBox(self.groupBox)
46
49
  self.EEGChannelCombox.setObjectName("EEGChannelCombox")
47
50
  self.gridLayout_2.addWidget(self.EEGChannelCombox, 0, 1, 1, 2)
51
+ self.label_2 = QtWidgets.QLabel(self.groupBox)
52
+ self.label_2.setObjectName("label_2")
53
+ self.gridLayout_2.addWidget(self.label_2, 2, 0, 1, 1)
54
+ self.label_8 = QtWidgets.QLabel(self.groupBox)
55
+ self.label_8.setObjectName("label_8")
56
+ self.gridLayout_2.addWidget(self.label_8, 1, 0, 1, 1)
48
57
  self.EEGSiteCombox = QtWidgets.QComboBox(self.groupBox)
49
58
  self.EEGSiteCombox.setObjectName("EEGSiteCombox")
50
59
  self.EEGSiteCombox.addItem("")
51
60
  self.EEGSiteCombox.addItem("")
52
61
  self.gridLayout_2.addWidget(self.EEGSiteCombox, 2, 1, 1, 2)
62
+ self.SaveAnnoCheckbox = QtWidgets.QCheckBox(self.groupBox)
63
+ self.SaveAnnoCheckbox.setObjectName("SaveAnnoCheckbox")
64
+ self.gridLayout_2.addWidget(self.SaveAnnoCheckbox, 4, 0, 1, 3)
53
65
  self.gridLayout.addWidget(self.groupBox, 0, 0, 1, 2)
54
66
 
55
67
  self.retranslateUi(AutoStageDialog)
@@ -61,9 +73,14 @@ class Ui_AutoStageDialog(object):
61
73
  self.OKBt.setText(_translate("AutoStageDialog", "Ok"))
62
74
  self.CancelBt.setText(_translate("AutoStageDialog", "Cancel"))
63
75
  self.groupBox.setTitle(_translate("AutoStageDialog", "Auto Stage options"))
64
- self.label_2.setText(_translate("AutoStageDialog", "EEG site:"))
76
+ self.AgeCombox.setItemText(0, _translate("AutoStageDialog", "> P56"))
77
+ self.AgeCombox.setItemText(1, _translate("AutoStageDialog", "P30 - P56"))
78
+ self.AgeCombox.setItemText(2, _translate("AutoStageDialog", "< P30"))
65
79
  self.label.setText(_translate("AutoStageDialog", "EEG channel:"))
80
+ self.label_3.setText(_translate("AutoStageDialog", "Mouse age:"))
81
+ self.label_2.setText(_translate("AutoStageDialog", "EEG site:"))
66
82
  self.label_8.setText(_translate("AutoStageDialog", "EMG channel:"))
67
83
  self.EEGSiteCombox.setItemText(0, _translate("AutoStageDialog", "Parietal"))
68
84
  self.EEGSiteCombox.setItemText(1, _translate("AutoStageDialog", "Frontal"))
85
+ self.SaveAnnoCheckbox.setText(_translate("AutoStageDialog", "Cover current label"))
69
86
  from misleep.gui.resources import misleep
@@ -135,6 +135,34 @@ def transfer_result(mianno, ac_time):
135
135
  ] = analyse_df[
136
136
  ['NREM_duration', 'NREM_bout', 'REM_duration', 'REM_bout', 'WAKE_duration',
137
137
  'WAKE_bout', 'INIT_duration', 'INIT_bout']].astype(int)
138
+
139
+
140
+ # gather the 12-h data to output the light phase and dark phase, set the first hour as ZT0 by default
141
+
142
+ try:
143
+ phase_data = pd.DataFrame()
144
+ phase_data['date_time'] = ['ZT0-ZT12', 'ZT12-ZT24']
145
+ phase_data['NREM_duration'] = [analyse_df['NREM_duration'].iloc[:12].sum(), analyse_df['NREM_duration'].iloc[12:24].sum()]
146
+ phase_data['NREM_bout'] = [analyse_df['NREM_bout'].iloc[:12].sum(), analyse_df['NREM_bout'].iloc[12:24].sum()]
147
+ phase_data['NREM_ave'] = phase_data.apply(lambda x: x['NREM_duration']/x['NREM_bout'] if x['NREM_bout']!=0 else 0, axis=1)
148
+ phase_data['NREM_percentage'] = phase_data.apply(lambda x: x['NREM_duration'] / 3600*12, axis=1)
149
+ phase_data['REM_duration'] = [analyse_df['REM_duration'].iloc[:12].sum(), analyse_df['REM_duration'].iloc[12:24].sum()]
150
+ phase_data['REM_bout'] = [analyse_df['REM_bout'].iloc[:12].sum(), analyse_df['REM_bout'].iloc[12:24].sum()]
151
+ phase_data['REM_ave'] = phase_data.apply(lambda x: x['REM_duration']/x['REM_bout'] if x['REM_bout']!=0 else 0, axis=1)
152
+ phase_data['REM_percentage'] = phase_data.apply(lambda x: x['REM_duration'] / 3600*12, axis=1)
153
+ phase_data['WAKE_duration'] = [analyse_df['WAKE_duration'].iloc[:12].sum(), analyse_df['WAKE_duration'].iloc[12:24].sum()]
154
+ phase_data['WAKE_bout'] = [analyse_df['WAKE_bout'].iloc[:12].sum(), analyse_df['WAKE_bout'].iloc[12:24].sum()]
155
+ phase_data['WAKE_ave'] = phase_data.apply(lambda x: x['WAKE_duration']/x['WAKE_bout'] if x['WAKE_bout']!=0 else 0, axis=1)
156
+ phase_data['WAKE_percentage'] = phase_data.apply(lambda x: x['WAKE_duration'] / 3600*12, axis=1)
157
+ phase_data['INIT_duration'] = [analyse_df['INIT_duration'].iloc[:12].sum(), analyse_df['INIT_duration'].iloc[12:24].sum()]
158
+ phase_data['INIT_bout'] = [analyse_df['INIT_bout'].iloc[:12].sum(), analyse_df['INIT_bout'].iloc[12:24].sum()]
159
+ phase_data['INIT_ave'] = phase_data.apply(lambda x: x['INIT_duration']/x['INIT_bout'] if x['INIT_bout']!=0 else 0, axis=1)
160
+ phase_data['INIT_percentage'] = phase_data.apply(lambda x: x['INIT_duration'] / 3600*12, axis=1)
161
+
162
+ analyse_df = pd.concat([analyse_df, phase_data])
163
+ analyse_df.reset_index(inplace=True)
164
+ except Exception as e:
165
+ pass
138
166
 
139
167
  start_end_df = pd.DataFrame(start_end_label,
140
168
  columns=['start_time', 'start_time_sec',
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: misleep
3
- Version: 0.2.3
3
+ Version: 0.2.4
4
4
  Summary: MiSleep: Mice Sleep EEG/EMG visualization, scoring and analysis.
5
5
  Home-page: https://github.com/BryanWang0702/MiSleep/
6
6
  Download-URL: https://github.com/BryanWang0702/MiSleep/
@@ -11,10 +11,13 @@ misleep.egg-info/requires.txt
11
11
  misleep.egg-info/top_level.txt
12
12
  misleep/analysis/__init__.py
13
13
  misleep/analysis/auto_stage.py
14
- misleep/analysis/classification.py
15
14
  misleep/analysis/detection.py
16
- misleep/analysis/auto_stage_model/EEG_F_lightgbm_20241221.pkl
17
- misleep/analysis/auto_stage_model/EEG_P_lightgbm_20241221.pkl
15
+ misleep/analysis/auto_stage_model/P30_EEG_F_lightgbm.pkl
16
+ misleep/analysis/auto_stage_model/P30_EEG_P_lightgbm.pkl
17
+ misleep/analysis/auto_stage_model/ado_EEG_F_lightgbm.pkl
18
+ misleep/analysis/auto_stage_model/ado_EEG_P_lightgbm.pkl
19
+ misleep/analysis/auto_stage_model/adult_EEG_F_lightgbm.pkl
20
+ misleep/analysis/auto_stage_model/adult_EEG_P_lightgbm.pkl
18
21
  misleep/gui/__init__.py
19
22
  misleep/gui/about.py
20
23
  misleep/gui/dialog.py
@@ -11,7 +11,7 @@ MAINTAINER_EMAIL = "swang@gmail.com"
11
11
  URL = "https://github.com/BryanWang0702/MiSleep/"
12
12
  LICENSE = "BSD (3-clause)"
13
13
  DOWNLOAD_URL = "https://github.com/BryanWang0702/MiSleep/"
14
- VERSION = "0.2.3"
14
+ VERSION = "0.2.4"
15
15
 
16
16
  INSTALL_REQUIRES = [
17
17
  "numpy>=1.18.1",
@@ -51,8 +51,12 @@ DATA_FILES = [
51
51
  "misleep/gui/resources/misleep.qrc",
52
52
  "misleep/gui/resources/logo.png",
53
53
  "misleep/gui/resources/entire_logo.png",
54
- "misleep/analysis/auto_stage_model/EEG_F_lightgbm_20241221.pkl",
55
- "misleep/analysis/auto_stage_model/EEG_P_lightgbm_20241221.pkl"
54
+ "misleep/analysis/auto_stage_model/adult_EEG_F_lightgbm.pkl",
55
+ "misleep/analysis/auto_stage_model/adult_EEG_P_lightgbm.pkl",
56
+ "misleep/analysis/auto_stage_model/ado_EEG_F_lightgbm.pkl",
57
+ "misleep/analysis/auto_stage_model/ado_EEG_P_lightgbm.pkl",
58
+ "misleep/analysis/auto_stage_model/P30_EEG_F_lightgbm.pkl",
59
+ "misleep/analysis/auto_stage_model/P30_EEG_P_lightgbm.pkl"
56
60
  ],
57
61
  )
58
62
  ]
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