Spaces:
Sleeping
Sleeping
Stable version_1001
Browse files- app.py +180 -49
- 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
|
7 |
-
st.set_page_config(layout="wide")
|
8 |
st.config.set_option("server.enableXsrfProtection", False)
|
|
|
9 |
|
10 |
-
|
11 |
-
|
12 |
-
|
|
|
13 |
|
14 |
-
|
15 |
-
|
|
|
|
|
|
|
|
|
16 |
|
17 |
-
#
|
18 |
-
|
19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
|
21 |
-
#
|
22 |
-
|
|
|
23 |
|
24 |
-
#
|
25 |
-
|
26 |
-
|
|
|
27 |
|
28 |
-
#
|
29 |
-
|
|
|
|
|
|
|
30 |
|
31 |
-
#
|
32 |
-
plt.
|
33 |
-
|
34 |
-
|
35 |
-
plt.
|
36 |
-
plt.
|
37 |
-
|
|
|
38 |
st.pyplot(plt.gcf())
|
39 |
-
#
|
|
|
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 |
-
|
|
|
54 |
try:
|
55 |
-
|
56 |
-
|
|
|
|
|
57 |
except Exception as e:
|
58 |
st.error(f"Error: {e}")
|
59 |
-
|
60 |
-
#
|
61 |
-
if
|
62 |
-
|
63 |
-
st.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
|
65 |
-
#
|
66 |
-
st.
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
|
68 |
-
#
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
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
|
|