Signal Processing
Link to page

1. Muscle Artifacts Tend to Occur in High-Frequency Bands

Muscle movements, such as jaw clenching, teeth grinding, or neck tension, generate high-frequency noise in EEG recordings.
This noise typically affects frequencies above 20 Hz, with the most prominent artifacts appearing in the 20–100 Hz range, depending on the type of muscle activity.

2. Protecting SSVEP Frequencies

Since your SSVEP signals include 5, 10, 15, 20, and 30 Hz, we need to:
Avoid affecting 20 Hz and 30 Hz because they correspond to your stimuli.
Focus on frequencies above 30 Hz to reduce the risk of suppressing SSVEP-related activity.
By selecting the 35–50 Hz range, you can:
Detect muscle artifacts without interfering with your critical SSVEP signals.
Still capture part of the typical muscle noise spectrum.

3. Why 35–50 Hz?

The 35–50 Hz range is often recommended for muscle artifacts because:
35 Hz and above:
Muscle artifacts from jaw, neck, or scalp movements often exhibit high power in this range.
This band avoids SSVEP signals and their harmonics.
50 Hz:
Some muscle noise can overlap with powerline noise harmonics at 50 Hz.
If the powerline noise is already removed (via a 50 Hz notch filter), muscle artifacts might still show power in adjacent frequencies.

4. Beyond 50 Hz

If you notice significant muscle activity beyond 50 Hz, you can extend the detection range:
35–100 Hz: Captures broader muscle noise.
Adjust Dynamically: Depending on your data, you can inspect power spectra and adjust the range.

5. Why Not Lower Than 35 Hz?

Frequencies below 35 Hz overlap with your SSVEP signals (e.g., 20 Hz and 30 Hz).
Including these frequencies in muscle artifact detection may falsely label useful SSVEP components as artifacts, reducing important signal information.

Summary of Plots:

Table 3
Plot
Purpose
Function
Time-Series of Artifacts
Visualize temporal patterns of artifact components
ica.plot_sources()
Spatial Patterns
Identify scalp regions affected by artifacts
ica.plot_components()
Power Spectral Density
Confirm artifact frequency range
Custom PSD plot using compute_psd()
Overlay Plot
Compare original and cleaned EEG data
ica.plot_overlay()
There are no rows in this table
"""import pandas as pd
import mne
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt
import matplotlib

# Use 'Agg' backend to avoid tkinter issues
matplotlib.use('Agg')

# File paths
input_file_path = '/media/ghada/Expansion/Data/Merged EEG-Joystick Data/S01/S01S01_labeled_eeg_data.csv'
output_file_path = '/media/ghada/Expansion/Data/Preprocessed Data/S01/S01S01_preprocessed_eeg_data.csv'

# Load the merged EEG-Joystick data
eeg_df = pd.read_csv(input_file_path)

# Extract channel columns (assuming they start with 'channel_')
channel_columns = [col for col in eeg_df.columns if col.startswith('channel_')]

# Extract the actual time in seconds from the timestamp column
time_column = eeg_df['timestamp']

# Transpose the data for MNE (channel-time)
eeg_data = eeg_df[channel_columns].values.T # Transpose to (n_channels, n_times)

# Create MNE RawArray
sfreq = 125 # Sampling frequency
info = mne.create_info(ch_names=channel_columns, sfreq=sfreq, ch_types='eeg')
raw = mne.io.RawArray(eeg_data, info)

# --- Step 1: Plot Raw EEG Data (before any filtering) ---
for ch in channel_columns:
plt.figure()
plt.plot(time_column, eeg_df[ch], label='Raw')
plt.title(f'Raw EEG Data for {ch}')
plt.xlabel('Time (seconds)')
plt.ylabel('Amplitude')
plt.legend()
plt.savefig(f'/media/ghada/Expansion/Data/Preprocessed Data/S01/EEG_Raw_{ch}.png')
plt.close()

# --- Step 2: Apply Notch Filter (50 Hz) ---
raw_notched = raw.copy().notch_filter(freqs=[50])
eeg_notched = raw_notched.get_data().T

# Plot after Notch Filtering
for ch in channel_columns:
plt.figure()
plt.plot(time_column, eeg_df[ch], label='Original')
plt.plot(time_column, eeg_notched[:, channel_columns.index(ch)], label='Notched')
plt.title(f'Notch Filtered EEG Data for {ch}')
plt.xlabel('Time (seconds)')
plt.ylabel('Amplitude')
plt.legend()
plt.savefig(f'/media/ghada/Expansion/Data/Preprocessed Data/S01/EEG_Notched_{ch}.png')
plt.close()

# --- Step 3: Apply Band-pass Filter (1-40 Hz) ---
raw_filtered = raw_notched.copy().filter(l_freq=1.0, h_freq=40.0)
print(type(raw_filtered))
eeg_filtered = raw_filtered.get_data().T

# Plot after Band-pass Filtering
for ch in channel_columns:
plt.figure()
plt.plot(time_column, eeg_notched[:, channel_columns.index(ch)], label='Notched')
plt.plot(time_column, eeg_filtered[:, channel_columns.index(ch)], label='Filtered (1-40 Hz)')
plt.title(f'Filtered EEG Data for {ch}')
plt.xlabel('Time (seconds)')
plt.ylabel('Amplitude')
plt.legend()
plt.savefig(f'/media/ghada/Expansion/Data/Preprocessed Data/S01/EEG_Filtered_{ch}.png')
plt.close()

# --- Step 4: Normalize the Filtered Data ---
scaler = StandardScaler()
normalized_eeg_data = scaler.fit_transform(eeg_filtered)

# Convert back to DataFrame with labels and timestamps
normalized_eeg_df = pd.DataFrame(normalized_eeg_data, columns=channel_columns)
normalized_eeg_df['timestamp'] = eeg_df['timestamp']
normalized_eeg_df['label'] = eeg_df['label']

# Plot EEG Data After Normalization
scaling_factor = 100 # Adjust this value as needed

# Plot EEG Data After Normalization with Amplification
for ch in channel_columns:
plt.figure()
plt.plot(time_column, eeg_filtered[:, channel_columns.index(ch)], label='Filtered')
plt.plot(time_column, normalized_eeg_data[:, channel_columns.index(ch)] * scaling_factor, label='Normalized (Amplified)')
plt.title(f'Normalized EEG Data for {ch}')
plt.xlabel('Time (seconds)')
plt.ylabel('Amplitude (z-score * {scaling_factor})')
plt.legend()
plt.savefig(f'/media/ghada/Expansion/Data/Preprocessed Data/S01/EEG_Normalized_{ch}.png')
plt.close()

for ch in channel_columns:
plt.figure()
plt.plot(time_column, normalized_eeg_data[:, channel_columns.index(ch)], label='Normalized')
plt.title(f'Normalized EEG Data for {ch}')
plt.xlabel('Time (seconds)')
plt.ylabel('Amplitude (z-score)')
plt.legend()
plt.savefig(f'/media/ghada/Expansion/Data/Preprocessed Data/S01/EEG_Only_Normalized_{ch}.png')
plt.close()


# --- Step 5: Reorder the columns ---
ordered_columns = ['timestamp', 'label'] + channel_columns
normalized_eeg_df = normalized_eeg_df[ordered_columns]

# --- Step 6: Round the values (optional, adjust decimal places as needed) ---
normalized_eeg_df = normalized_eeg_df.round(6) # Round to 6 decimal places

# --- Step 7: Save the Preprocessed Data ---
# Save the normalized data to a CSV file
normalized_eeg_df.to_csv(output_file_path, index=False)

print(f"Preprocessed EEG data saved to {output_file_path}")
"""

"""import pandas as pd
import mne
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt
import seaborn as sns
import os


# Set Seaborn style for better visual representation
sns.set_style("whitegrid")
sns.set_context("talk") # Large context for better readability in plots

# File paths
input_file_path = '/media/ghada/Expansion/Data/Merged EEG-Joystick Data/S01/S01S01_labeled_eeg_data.csv'
output_file_path = '/media/ghada/Expansion/Data/Preprocessed Data/S01/S01S01_preprocessed_eeg_data.csv'

# Extract the prefix from the input file name (e.g., 'S01S01')
file_prefix = os.path.basename(input_file_path).split('_')[0]

# Load the merged EEG-Joystick data
eeg_df = pd.read_csv(input_file_path)

# Extract channel columns (assuming they start with 'channel_')
channel_columns = [col for col in eeg_df.columns if col.startswith('channel_')]

# Extract the actual time in seconds from the timestamp column
time_column = eeg_df['timestamp']

# Transpose the data for MNE (channel-time)
eeg_data = eeg_df[channel_columns].values.T # Transpose to (n_channels, n_times)

# Create MNE RawArray
sfreq = 125 # Sampling frequency
info = mne.create_info(ch_names=channel_columns, sfreq=sfreq, ch_types='eeg')
raw = mne.io.RawArray(eeg_data, info)

# --- Step 1: Plot Raw EEG Data (before any filtering) ---
for ch in channel_columns:
plt.figure(figsize=(12, 6)) # Larger figure size for better readability
sns.lineplot(x=time_column, y=eeg_df[ch], label='Raw', color='blue')
plt.title(f'{file_prefix} - Raw EEG Data for {ch}', fontsize=16)
plt.xlabel('Time (seconds)', fontsize=14)
plt.ylabel('Amplitude', fontsize=14)
plt.legend()
plt.savefig(f'/media/ghada/Expansion/Data/Preprocessed Data/S01/{file_prefix}_EEG_Raw_{ch}.png')
plt.close()

Want to print your doc?
This is not the way.
Try clicking the ⋯ next to your doc name or using a keyboard shortcut (
CtrlP
) instead.