HengJay commited on
Commit
4699f43
·
1 Parent(s): 86464b3

Stable version_1001

Browse files
Files changed (2) hide show
  1. app.py +180 -49
  2. data-processing.ipynb +0 -0
app.py CHANGED
@@ -3,75 +3,206 @@ import matplotlib.pyplot as plt
3
  import pandas as pd
4
  import numpy as np
5
 
6
- # Set streamlit configuration with wide mode
7
- st.set_page_config(layout="wide")
8
  st.config.set_option("server.enableXsrfProtection", False)
 
9
 
10
- def plot_signal(signal, index):
11
- # Assuming df is your DataFrame and 'Signal1', 'Signal2', 'Signal3' are your columns
12
- ch1 = pd.to_numeric(signal[index], errors='coerce')
 
13
 
14
- # Define the moving average window size
15
- N = 25
 
 
 
 
16
 
17
- # Function to calculate moving RMS
18
- def moving_rms(signal, window_size):
19
- return np.sqrt(pd.Series(signal).rolling(window=window_size).mean()**2)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
 
21
- # Calculate moving RMS for each channel
22
- ch1_rms = moving_rms(ch1, N)
 
23
 
24
- # Calculate mean and standard deviation of the RMS signals
25
- mean_ch1_rms = np.mean(ch1_rms)
26
- std_ch1_rms = np.std(ch1_rms)
 
27
 
28
- # Print mean and standard deviation values
29
- st.write(f'Mean of RMS Signal {int(index)}: {mean_ch1_rms:.3f}, Std Dev of RMS Signal 1: {std_ch1_rms:.3f}')
 
 
 
30
 
31
- # Plot the RMS signals
32
- plt.figure(figsize=(15,6))
33
- plt.plot(ch1_rms, label='Signal 1 RMS')
34
- plt.title('RMS Signal Values, Moving Average Window Size N=25')
35
- plt.xlabel('Index')
36
- plt.ylabel('RMS Value')
37
- plt.legend()
 
38
  st.pyplot(plt.gcf())
39
- # plt.show()
 
40
 
41
-
42
  def main():
43
  st.title('👅Dysphagia Analysis - by ITRI BDL')
 
 
 
 
 
 
 
 
 
 
 
 
44
  uploaded_file1 = st.file_uploader("Choose the EMG_data CSV file", type="csv")
45
  uploaded_file2 = st.file_uploader("Choose the time_marker CSV file", type="csv")
46
- if uploaded_file1 is not None:
47
- try:
48
- data1 = pd.read_csv(uploaded_file1, skiprows=[0,1,3,4])
49
- # st.dataframe(data1)
50
- except Exception as e:
51
- st.error(f"Error: {e}")
52
 
53
- if uploaded_file2 is not None:
 
54
  try:
55
- data2 = pd.read_csv(uploaded_file2, skiprows=[0,1])
56
- # st.dataframe(data2)
 
 
57
  except Exception as e:
58
  st.error(f"Error: {e}")
59
-
60
- # Detect Upload File and choose signal with sidebar menu
61
- if uploaded_file1 is not None and uploaded_file2 is not None:
62
- signal = st.sidebar.selectbox('Select EMG Signal', data1.columns)
63
- st.write(f'You selected: channel {signal}')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
 
65
- # Plot the selected signal
66
- st.line_chart(data1[signal])
 
 
 
 
 
 
67
 
68
- # Analysis button
69
- if st.button('Start Analysis'):
70
- st.write('Analysis started...')
71
- # Add analysis code here
72
- plot_signal(data1, signal)
73
- st.write('Analysis completed...')
74
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
 
 
 
76
  if __name__ == '__main__':
77
  main()
 
3
  import pandas as pd
4
  import numpy as np
5
 
6
+ # Set streamlit configuration with disable XSRF protection
 
7
  st.config.set_option("server.enableXsrfProtection", False)
8
+ st.set_page_config(page_title="Dysphagia Analysis", page_icon="👅")
9
 
10
+ # Function to plot the EMG signal Coordination Analysis
11
+ def emg_plot(event_index, event_plot_name, left_std_ratio, left_delta_t, right_std_ratio, right_delta_t):
12
+ """
13
+ Plots a 2D quadrant chart for EMG signal analysis with colored squares indicating the quadrant.
14
 
15
+ Parameters:
16
+ std (float): Standard deviation value of the EMG signal.
17
+ delta_t (float): Delta T value of the EMG signal.
18
+ """
19
+ # Create a new figure
20
+ fig, ax = plt.subplots(figsize=(8, 8))
21
 
22
+ # Determine the quadrant and plot the colored square
23
+ if left_std_ratio > 3 and left_delta_t > 0:
24
+ # First quadrant
25
+ ax.add_patch(plt.Rectangle((2, 2), 6, 6, color='blue', alpha=0.5))
26
+ elif left_std_ratio <= 3 and left_delta_t > 0:
27
+ # Second quadrant
28
+ ax.add_patch(plt.Rectangle((-8, 2), 6, 6, color='blue', alpha=0.5))
29
+ elif left_std_ratio <= 3 and left_delta_t <= 0:
30
+ # Third quadrant
31
+ ax.add_patch(plt.Rectangle((-8, -8), 6, 6, color='blue', alpha=0.5))
32
+ elif left_std_ratio > 3 and left_delta_t <= 0:
33
+ # Fourth quadrant
34
+ ax.add_patch(plt.Rectangle((2, -8), 6, 6, color='blue', alpha=0.5))
35
+
36
+ # Determine the quadrant and plot the colored square
37
+ if right_std_ratio > 3 and right_delta_t > 0:
38
+ # First quadrant
39
+ ax.add_patch(plt.Rectangle((1.5, 1.5), 6, 6, color='green', alpha=0.5))
40
+ elif right_std_ratio <= 3 and right_delta_t > 0:
41
+ # Second quadrant
42
+ ax.add_patch(plt.Rectangle((-8.5, 1.5), 6, 6, color='green', alpha=0.5))
43
+ elif right_std_ratio <= 3 and right_delta_t <= 0:
44
+ # Third quadrant
45
+ ax.add_patch(plt.Rectangle((-8.5, -8.5), 6, 6, color='green', alpha=0.5))
46
+ elif right_std_ratio > 3 and right_delta_t <= 0:
47
+ # Fourth quadrant
48
+ ax.add_patch(plt.Rectangle((1.5, -8.5), 6, 6, color='green', alpha=0.5))
49
 
50
+ # Add horizontal and vertical lines to create quadrants
51
+ plt.axhline(y=0, color='black', linestyle='--')
52
+ plt.axvline(x=0, color='black', linestyle='--')
53
 
54
+ # Add title and axis labels
55
+ plt.title(f'Muscle Coordination Analysis - {event_index}:{event_plot_name}', fontsize=14)
56
+ plt.xlabel('Std Ratio > 3', fontsize=12)
57
+ plt.ylabel('Delta T > 0', fontsize=12)
58
 
59
+ # Remove axis numbers and labels
60
+ ax.set_xticks([])
61
+ ax.set_yticks([])
62
+ ax.set_xticklabels([])
63
+ ax.set_yticklabels([])
64
 
65
+ # Set plot legend with color
66
+ plt.legend(['Left', 'Right'], loc='upper left', fontsize=10)
67
+
68
+ # Set the limits of the plot
69
+ plt.xlim(-10, 10)
70
+ plt.ylim(-10, 10)
71
+
72
+ # Display the plot
73
  st.pyplot(plt.gcf())
74
+ #plt.show()
75
+
76
 
 
77
  def main():
78
  st.title('👅Dysphagia Analysis - by ITRI BDL')
79
+
80
+ # Initialize session state variables
81
+ if 'emg_data' not in st.session_state:
82
+ st.session_state.emg_data = None
83
+ if 'time_marker' not in st.session_state:
84
+ st.session_state.time_marker = None
85
+ if 'analysis_started' not in st.session_state:
86
+ st.session_state.analysis_started = False
87
+ if 'data_isready' not in st.session_state:
88
+ st.session_state.data_isready = False
89
+
90
+ # File Uploaders
91
  uploaded_file1 = st.file_uploader("Choose the EMG_data CSV file", type="csv")
92
  uploaded_file2 = st.file_uploader("Choose the time_marker CSV file", type="csv")
 
 
 
 
 
 
93
 
94
+ # Load data when files are uploaded
95
+ if uploaded_file1 is not None and uploaded_file2 is not None:
96
  try:
97
+ st.session_state.emg_data = pd.read_csv(uploaded_file1, skiprows=[0,1,3,4])
98
+ st.session_state.time_marker = pd.read_csv(uploaded_file2)
99
+ st.success("Data loaded successfully!")
100
+ st.session_state.data_isready = True
101
  except Exception as e:
102
  st.error(f"Error: {e}")
103
+
104
+ # Load test data button
105
+ if st.button('Load Test Data', type="primary"):
106
+ st.session_state.emg_data = pd.read_csv('test-1/0-New_Task-recording-0.csv', skiprows=[0,1,3,4])
107
+ st.session_state.time_marker = pd.read_csv('test-1/time_marker.csv')
108
+ st.success("Test data loaded successfully!")
109
+ st.session_state.data_isready = True
110
+
111
+ # Display loaded data
112
+ if st.session_state.emg_data is not None:
113
+ st.subheader("EMG Data")
114
+ st.dataframe(st.session_state.emg_data)
115
+ if st.session_state.time_marker is not None:
116
+ st.subheader("Time Marker")
117
+ st.dataframe(st.session_state.time_marker)
118
+
119
+ # Analysis button
120
+ if st.session_state.data_isready:
121
+ st.subheader("Muscle Coordination Analysis")
122
+ if st.button('Start Analysis', type="primary"):
123
+ st.session_state.analysis_started = True
124
+
125
+ # Perform analysis if started
126
+ if st.session_state.analysis_started:
127
+ st.write('Analysis in progress...')
128
 
129
+ # Reset emg data index with Channels
130
+ emg_data = st.session_state.emg_data.set_index('Channels')
131
+ # Get signal data from difference of emg_data
132
+ signal_left_lateral = emg_data['21'] - emg_data['3']
133
+ signal_left_medial = emg_data['22'] - emg_data['2']
134
+
135
+ signal_right_lateral = emg_data['16'] - emg_data['6']
136
+ signal_right_medial = emg_data['17'] - emg_data['5']
137
 
138
+ # RMS caculation : Define the moving average window size
139
+ N = 25
140
+ # Function to calculate moving RMS
141
+ def moving_rms(signal, window_size):
142
+ rms = np.sqrt(pd.Series(signal).rolling(window=window_size).mean()**2)
143
+ rms.index = signal.index # Ensure the index matches the original signal
144
+ return rms
145
+ # Calculate moving RMS for each channel
146
+ signal_left_lateral_RMS = moving_rms(signal_left_lateral, N)
147
+ signal_left_medial_RMS = moving_rms(signal_left_medial, N)
148
+ signal_right_lateral_RMS = moving_rms(signal_right_lateral, N)
149
+ signal_right_medial_RMS = moving_rms(signal_right_medial, N)
150
+
151
+ # Time Marker Processing
152
+ time_marker = st.session_state.time_marker[['0-New_Task-recording_time(us)', 'name', 'tag']]
153
+ time_marker = time_marker.rename(columns={'0-New_Task-recording_time(us)': 'event_time'})
154
+
155
+ # Select column value with odd/even index
156
+ event_start_times = time_marker.loc[0::2]['event_time'].values.astype(int)
157
+ event_end_times = time_marker.loc[1::2]['event_time'].values.astype(int)
158
+ event_names = time_marker.loc[0::2]['name'].values
159
+
160
+ # Get signal basic 10s std
161
+ signal_left_lateral_basics_10s_std = signal_left_lateral_RMS.loc[: 10000000].std()
162
+ signal_right_lateral_basics_10s_std = signal_right_lateral_RMS.loc[: 10000000].std()
163
+
164
+ # Analyze event data
165
+ event_number = len(event_names)
166
+
167
+ for i in range(1, 2*event_number, 2):
168
+ event_name = event_names[i//2]
169
+ event_start_time = event_start_times[i//2]
170
+ event_end_time = event_end_times[i//2]
171
+
172
+ st.write(f"Event {i//2+1}: {event_name}")
173
+ st.write(f"Start time: {float(event_start_time)/1000000: .3f} sec, End time: {float(event_end_time)/1000000: .3f} sec")
174
+
175
+ # Get event signal data with event time duration
176
+ event_signal_LL = signal_left_lateral_RMS.loc[event_start_time:event_end_time]
177
+ event_signal_LM = signal_left_medial_RMS.loc[event_start_time:event_end_time]
178
+
179
+ event_signal_RL = signal_right_lateral_RMS.loc[event_start_time:event_end_time]
180
+ event_signal_RM = signal_right_medial_RMS.loc[event_start_time:event_end_time]
181
+
182
+ # Calculate std ratio
183
+ left_event_std = event_signal_LL.std()
184
+ left_std_ratio = left_event_std / signal_left_lateral_basics_10s_std
185
+
186
+ right_event_std = event_signal_RL.std()
187
+ right_std_ratio = right_event_std / signal_right_lateral_basics_10s_std
188
+
189
+ st.write(f"left std ratio: {left_std_ratio: .3f}, right std ratio: {right_std_ratio: .3f}")
190
+
191
+ # Get signal max value index
192
+ LL_max_index = event_signal_LL.idxmax()
193
+ LM_max_index = event_signal_LM.idxmax()
194
+ left_delta_t = LM_max_index - LL_max_index
195
+ st.write(f"LM_max_index: {float(LM_max_index)/1000000: .3f}, LL_max_index: {float(LL_max_index)/1000000: .3f}, left delta t: {float(left_delta_t)/1000000: .3f}")
196
+
197
+ RL_max_index = event_signal_RL.idxmax()
198
+ RM_max_index = event_signal_RM.idxmax()
199
+ right_delta_t = RM_max_index - RL_max_index
200
+ st.write(f"RM_max_index: {float(RM_max_index)/1000000: .3f}, RL_max_index: {float(RL_max_index)/1000000: .3f}, right delta t: {float(right_delta_t)/1000000: .3f}")
201
+
202
+ # Plot with each event data
203
+ emg_plot(i//2+1, event_name, left_std_ratio, left_delta_t, right_std_ratio, right_delta_t)
204
 
205
+ st.write('Analysis completed!')
206
+
207
  if __name__ == '__main__':
208
  main()
data-processing.ipynb ADDED
The diff for this file is too large to render. See raw diff