File size: 10,042 Bytes
d6e019d
 
 
32eb178
d6e019d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7eb4bc2
d6e019d
 
 
8538962
d6e019d
 
8538962
d6e019d
 
8538962
fe2688d
 
8538962
fe2688d
 
d6e019d
 
8538962
 
 
 
 
 
 
 
 
d6e019d
 
 
 
 
8538962
d6e019d
 
 
51bb6a3
d6e019d
 
 
 
ace6264
d6e019d
32eb178
 
 
 
 
 
 
fe2688d
32eb178
 
 
 
 
 
d6e019d
51bb6a3
d6e019d
 
 
 
 
 
 
 
 
 
ace6264
d6e019d
 
32eb178
 
 
 
 
 
fe2688d
 
32eb178
 
 
 
 
d6e019d
32eb178
51bb6a3
d6e019d
 
 
 
 
 
 
 
 
 
 
ace6264
d6e019d
 
32eb178
 
 
 
 
 
fe2688d
32eb178
 
 
 
 
51bb6a3
32eb178
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fe2688d
32eb178
 
 
 
 
 
 
 
 
 
d6e019d
32eb178
 
 
51bb6a3
32eb178
 
 
 
 
d6e019d
32eb178
 
 
 
 
 
fe2688d
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import detrend,savgol_filter
from scipy.ndimage import gaussian_filter1d
import streamlit as st


def moving_average(signal, window_size=7):
    return np.convolve(signal, np.ones(window_size) / window_size, mode='full')[window_size:-window_size+1]

def window_detrend(signal, window_size=20,trend='linear'):
    """
    Calculate mean of every window_size elements and subtract the mean from the window.
    """
    out = np.array([])
    for i in range(0, len(signal)-window_size):
        # out.append(detrend(signal[i:i+window_size])[-1])
        out = np.append(out, detrend(signal[i:i+window_size],type=trend)[-1])
    return out


if __name__ == '__main__':

    signal = dict()
    signal['Linearly increasing sine wave'] = np.sin(np.linspace(0, 100, 1000)) + np.linspace(0, 100, 1000)
    signal['Resp Signal sample 1'] = np.load('./RR_signal1.npy')
    signal['Resp Signal sample 2'] = np.load('./RR_signal2.npy')
    signal['Resp Signal sample 3'] = np.load('./RR_signal3.npy')

    st.set_page_config(layout="wide")

    # with st.sidebar:
    #     st.markdown(
    #                     """
    #                     <style>
    #                         section[data-testid="stSidebar"] {
    #                             width: 300px !important; # Set the width to your desired value
    #                         }
    #                     </style>
    #                     """,
    #                     unsafe_allow_html=True,
    #                 )
    #     st.header('Detrend and Savitzky-Golay Filter')
    #     st.write('This app demonstrated the effect of detrending and Savitzky-Golay filter to the signal.')
    #     st.header('Detrending : ')
    #     st.write('The detrend function removes the trend from a signal. Trend could either be linear or constant.')
    #     st.header('Savitzky-Golay Filter : ')
    #     st.write('The Savitzky-Golay filter is a filter that fits a polynomial to a window of data and returns the fitted value ')

    st.title('Detrend and Savitzky-Golay Filter')
    st.write('This Space demonstrates the effect of Detrending and Savitzky-Golay filter to Respiratory signals.')

    st.write('---')

    st.subheader('Detrending : ')
    st.write('Detrending means removal of the mean value as well as any linear trend that may be in the measurements. A linear trend could be caused by e.g. drift and it is removed by fitting a first order polynomial to each of the measurement channels and then subtracting it afterwards. By default linear trends should be removed since they can disturb the signal processing and modal analysis.')

    st.subheader('Savitzky-Golay Filter : ')
    st.write('Savitzky-Golay smoothing filters are typically used to "smooth out" a noisy signal. They are also called digital smoothing polynomial filters or least-squares smoothing filters. Savitzky-Golay filters perform better in some applications than standard averaging FIR filters, which tend to filter high-frequency content along with the noise. Savitzky-Golay filters are more effective at preserving high frequency signal components but less successful at rejecting noise.Savitzky-Golay filters are optimal in the sense that they minimize the least-squares error in fitting a polynomial to frames of noisy data.')

    st.subheader('Moving Average Filter : ')
    st.write('The moving average is the most common filter in Signal Processing , mainly because it is the easiest digital filter to understand and use. The moving average filter is optimal for a common task: reducing random noise while retaining a sharp step response.This makes it the premier filter for time domain encoded signals.')

    st.subheader('Gaussian Filter : ')
    st.write('Gaussian filters are widely used for noise reduction due to their edge preserving properties. Gaussian filters are also used as smoothing filters. The Gaussian filter is a low-pass filter that removes the high-frequency components.')

    st.write('---')

    with st.container():
        # show video
        st.header('Video Demonstration of gathering a respiratory signal')
        st.video('./SpeedUP_Supine.mp4')


    st.write('---')

    st.header('Signal Processing')

    with st.container():
        left,right = st.columns(2)

        with left:
            signal_select = st.selectbox('*Please select a signal*',['Linearly increasing sine wave','Resp Signal sample 1','Resp Signal sample 2','Resp Signal sample 3'],index=1)

        with right:
            st.subheader('Original Signal')
            fig1, ax1 = plt.figure(figsize=(10,5),dpi=150), plt.gca()
            ax1.plot(signal[signal_select])
            ax1.set_xlabel('Time')
            ax1.set_ylabel('Amplitude')
            ax1.set_title('Original Signal')
            # ax1.legend()
            st.pyplot(fig1)
    
    st.write('---')

    with st.container():
        left,right = st.columns(2)

        with left:
            st.subheader('Detrending')
            window_size_dt = st.slider('*Window Size for Detrending*',min_value=1,max_value=100,value=20,step=1)
            st.write('Window size is the number of samples to be considered for detrending.')
            trend_type = st.selectbox('*Trend Type*',['linear','constant','Dont Remove'])
            st.write('Trend type is the type of trend to be removed from the signal.')

        with right:
            st.subheader('Detrended Signal')
            fig2, ax2 = plt.figure(figsize=(10,5),dpi=150), plt.gca()

            if trend_type == 'Dont Remove':
                detrend_signal = signal[signal_select]
            else:
                detrend_signal = window_detrend(signal[signal_select], window_size=window_size_dt, trend=trend_type)

            ax2.plot(detrend_signal)
            ax2.set_xlabel('Time')
            ax2.set_ylabel('Amplitude')
            ax2.set_title('Detrended Signal')
            # ax2.legend()
            st.pyplot(fig2)

    st.write('---')
    
    with st.container():
        left,right = st.columns(2)

        with left:
            st.subheader('Savitzky-Golay Filter')
            window_size_sg = st.slider('*Window Size for Savitzky-Golay filter*',min_value=1,max_value=100,value=20,step=1)
            st.write('Window size is the number of samples to be considered for filtering.')
            order = st.slider('*Polynomial Order*',min_value=1,max_value=10,value=3,step=1)
            st.write('Order is the order of the polynomial to be fitted to the window of data.')


        with right:
            st.subheader('Savitzky-Golay Filter applied to Detrended Signal')
            fig3, ax3 = plt.figure(figsize=(10,5),dpi=150), plt.gca()

            if trend_type == 'Dont Remove':
                detrend_signal = signal[signal_select]
            else:
                detrend_signal = window_detrend(signal[signal_select], window_size=window_size_dt, trend=trend_type)

            sg_signal = savgol_filter(detrend_signal, window_size_sg, order)
            ax3.plot(sg_signal)
            ax3.set_xlabel('Time')
            ax3.set_ylabel('Amplitude')
            ax3.set_title('Savitzky-Golay Filtered Signal')
            # ax3.legend()
            st.pyplot(fig3)

    st.write('---')

    with st.container():
        left,right = st.columns(2)

        with left:
            st.subheader('Moving Average Filter')
            window_size_ma = st.slider('*Window Size for Moving Average filter*',min_value=1,max_value=100,value=20,step=1)
            st.write('Window size is the number of samples to be considered for filtering.')
        
        with right:
            st.subheader('Moving Average Filter applied to Detrended Signal')
            fig4, ax4 = plt.figure(figsize=(10,5),dpi=150), plt.gca()

            if trend_type == 'Dont Remove':
                detrend_signal = signal[signal_select]
            else:
                detrend_signal = window_detrend(signal[signal_select], window_size=window_size_dt, trend=trend_type)

            ma_signal = moving_average(detrend_signal, window_size_ma)
            ax4.plot(ma_signal)
            ax4.set_xlabel('Time')
            ax4.set_ylabel('Amplitude')
            ax4.set_title('Moving Average Filtered Signal')
            # ax4.legend()
            st.pyplot(fig4)

    st.write('---')

    with st.container():
        left,right = st.columns(2)

        with left:
            st.subheader('Gaussian Filter')
            sigma_gf = st.slider('*Sigma*',min_value=0.1,max_value=10.0,value=3.0,step=0.1)
            st.write('Sigma is the standard deviation for Gaussian kernel.')

            mode_gf = st.selectbox('*Mode*',['reflect','constant','nearest','mirror','wrap'])
            st.write('Mode is the type of boundary condition to be applied to the filter.')
            st.write('*Reflect :* The input is extended by reflecting about the edge of the last pixel.')
            st.write('*Constant :* The input is extended by filling all values beyond the edge with the value 0.0')
            st.write('*Nearest :* The input is extended by replicating the last pixel.')
            st.write('*Mirror :* The input is extended by reflecting about the center of the last pixel.')
            st.write('*Wrap :* The input is extended by wrapping around to the opposite edge.')

        
        with right:
            st.subheader('Gaussian Filter apllied to Detrended Signal')
            fig5, ax5 = plt.figure(figsize=(10,5),dpi=150), plt.gca()

            if trend_type == 'Dont Remove':
                detrend_signal = signal[signal_select]
            else:
                detrend_signal = window_detrend(signal[signal_select], window_size=window_size_dt, trend=trend_type)

            gf_signal = gaussian_filter1d(detrend_signal, sigma=sigma_gf, mode=mode_gf)
            ax5.plot(gf_signal)
            ax5.set_xlabel('Time')
            ax5.set_ylabel('Amplitude')
            ax5.set_title('Gaussian Filtered Signal')
            st.pyplot(fig5)

    st.write('---')