Python实现从GDF文件导入BCI Competition IV-2b的MRCP信号并应用STFT
Got it, let's walk through this step by step—from importing your GDF files to applying the STFT exactly as you specified for the 2-second motor imagery trials. We'll use Python's go-to libraries for neurosignal processing to make this smooth.
1. First, install the required libraries
You'll need these packages to load GDF files, handle signals, and compute STFT:
pip install mne scipy numpy
mneis purpose-built for EEG/neuro signals and has native support for GDF filesscipygives us a robust STFT implementationnumpyhandles all the heavy lifting for numerical operations
2. Import the GDF file
BCI Competition IV-2b's GDF files include raw signals and event markers (to identify individual trials). mne makes parsing these trivial:
import mne import numpy as np from scipy import signal # Load your GDF file raw = mne.io.read_raw_gdf('your_dataset.gdf', preload=True, verbose=False) # Quick sanity check (optional) print(f"Sampling rate: {raw.info['sfreq']} Hz") print(f"Number of channels: {len(raw.info['ch_names'])}")
3. Extract 2-second trials (500 samples at 250Hz)
The dataset uses event markers to flag the start of each motor imagery trial. We'll use these markers to slice out exactly 2-second segments (250Hz * 2 = 500 samples):
# Pull event markers from the GDF file events, event_id = mne.events_from_annotations(raw) # Define the trial window: adjust tmin/tmax if your trials start offset from the marker # Here, we're taking 0 to 2 seconds relative to the marker (exactly 500 samples) epochs = mne.Epochs(raw, events, event_id, tmin=0, tmax=2, preload=True, verbose=False) # Convert to a numpy array for easier processing: shape = (num_trials, num_channels, num_samples) trial_data = epochs.get_data() print(f"Extracted trial data shape: {trial_data.shape}") # Should look like (N, C, 500) where N = number of trials, C = number of channels
4. Apply STFT with window size 64
Now we'll run STFT on each trial's time series. We'll use scipy.signal.stft with your specified window size of 64:
# STFT parameters sfreq = raw.info['sfreq'] # 250Hz, matches your dataset window_size = 64 noverlap = window_size // 2 # 50% overlap is standard for balancing time/freq resolution # Compute STFT for every trial and channel stft_output = [] for trial in trial_data: channel_stfts = [] for channel_signal in trial: # Run STFT: returns frequency axis, time axis, and complex STFT values freq_bins, time_bins, stft_vals = signal.stft( channel_signal, fs=sfreq, nperseg=window_size, noverlap=noverlap ) channel_stfts.append(stft_vals) stft_output.append(channel_stfts) # Convert to numpy array: shape = (num_trials, num_channels, num_freq_bins, num_time_bins) stft_output = np.array(stft_output) print(f"STFT result shape: {stft_output.shape}")
Quick notes on the STFT:
nperseg=window_sizesets the window length to 64 as requested- The 50% overlap (
noverlap=32) ensures we don't miss transient signals while keeping computation manageable stft_valsis complex—usenp.abs(stft_vals)if you need the amplitude spectrum, ornp.angle(stft_vals)for phase
Bonus tip
If your trials don't start exactly at the event marker (e.g., the motor imagery starts 1 second after the cue), just adjust tmin and tmax in the Epochs call—like tmin=1, tmax=3 to grab 2 seconds starting 1 second post-marker.
内容的提问来源于stack exchange,提问作者Wajdan Ali

