EMG bandwidth to calculate Shannon–Hartley theorem
Hi, I'm currently trying with a team to calculate an estimative channel capacity of a human arm for EMG signals. For that we are applying the Shannon-Hartley theorem that implies some calculations. What we're struggling the most it's to justify an appropriate bandwidth for this theorem. We know in OpenBCI GUI and projects you usually use a bandpass filter from 0.5 to 45.0Hz but we don't quite understand why. The thing is that for our calculation the SNR always wive us close to 1 so the bandwidth becomes crucial in the final result and we can't find anywhere some justification for which bandwidth to use to isolate the most only EMG signals. Any help on this matter would be appreciated. Thank you in advance.
Here is basically the calculation we are doing.
And this is our python code if needed:
import numpy as np
import pandas as pd
from scipy.signal import find_peaks
import matplotlib.pyplot as plt
from brainflow.data_filter import DataFilter, FilterTypes, NoiseTypes, AggOperations, DetrendOperations
from brainflow.board_shim import BoardShim, BoardIds
def main():
test_name = "Ian-BB-3.1(unfiltered).csv"
data_file = f"../official-tests/{test_name}"
bandpass_low_limit = 0.5
bandpass_high_limit = 45.0
data = DataFilter.read_file(data_file)
data_ch1 = data[1]
sampling_rate = BoardShim.get_sampling_rate(BoardIds.GANGLION_BOARD.value)
# Filters
DataFilter.perform_rolling_filter(data_ch1, 2, AggOperations.MEAN.value)
DataFilter.detrend(data_ch1, DetrendOperations.CONSTANT)
DataFilter.perform_bandpass(data_ch1, sampling_rate, bandpass_low_limit, bandpass_high_limit, 2, FilterTypes.BUTTERWORTH_ZERO_PHASE, 0)
DataFilter.remove_environmental_noise(data_ch1, sampling_rate, NoiseTypes.FIFTY.value)
plt.figure()
pd.DataFrame(data_ch1).plot(subplots=True)
plt.savefig('original_signal.png')
# Testing peak detection from Brainflow
df_peaks = pd.DataFrame(np.transpose(data))
df_peaks[1] = DataFilter.detect_peaks_z_score(data_ch1, lag=5, influence=0.1, threshold=10)
plt.figure()
df_peaks[1].plot(subplots=True)
plt.savefig('peaks.png')
# Plot
plot_fft(data_ch1, 1, 200)
bandwidth = bandpass_high_limit - bandpass_low_limit
print("Bandwidth: %f" % bandwidth)
SNR = calculate_snr(data_ch1)
channel_capacity = calculate_channel_capacity(bandwidth, SNR)
print("\nChannel Capacity: %.5f bps" % channel_capacity)
def calculate_snr(data):
plt.figure()
peaks, _ = find_peaks(data, prominence=(100, None))
plt.plot(data)
plt.plot(peaks, data[peaks], "x")
plt.plot(np.zeros_like(data), "--", color="gray")
plt.savefig("peaks2.png")
# Peaks Standard Deviation
peak_std = np.std(data[peaks])
# Noise mask
mask = np.ones(len(data), dtype=bool)
mask[peaks] = False
# Noise Standard Deviation
noise_signal = data[mask]
noise_signal_std = np.std(noise_signal)
# Signal Standard Deviation
signal_std = np.std(data)
SNR = signal_std / noise_signal_std
return SNR
def calculate_channel_capacity(bandwidth, snr):
return bandwidth * np.log2(1 + snr)
Comments
That bandpass recommendation is mainly based on EEG usage. EEG below .5 Hz (even lower, below .1 Hz or .01 Hz) is considered a "DC offset" and generally not useful. EEG above 45 Hz (gamma band) gets close to mains frequencies and lower signal quality due to this noise.
EMG in labs sometimes use higher sample rates, for example 500 Hz or 1000 Hz. However with Ganglion you are limited to 200 Hz sample rate. Technically by the Nyquist rule that would limit you to waveforms 100 Hz and below. But... a 100 Hz sine wave sampled at 200 Hz has tremendous alias effects. Imagine that the null points coincide with the sample times. Bad news. A better rule for maximum signal fidelity is to collect say 5 samples per waveform, instead of 2 or 3 or 4. So at 200 Hz you can get 'acceptable' fidelity for signals about (200 / 5 = 40) 40 Hz and below.
Most EMG gathered with these types of sample rates is mainly interested in the 'envelope' of the maximum EMG samples voltage amplitudes. If you are doing EMG lab research and really need the high frequency details, then you want to use higher sample rates.
https://www.google.com/search?q=emg+sample+rates
https://www.sciencedirect.com/science/article/abs/pii/S1050641104000926
"The effect of sampling frequency on EMG measures of occupational mechanical exposure"
William