EEGLab pop_spectopo()报错:非整数段数问题求助
问题:处理8-10号受试者时Spectopo报错“非整数epochs”
我在从顶叶电极提取alpha功率,代码在1-7号受试者上运行正常,但处理8、9、10号受试者时触发如下报错。
主处理代码
baseDir = 'my local folder'; %directory where everything is based resultsFileName = [baseDir 'trialResultsAllSubjects.xlsx']; allResultsTable = readmatrix(resultsFileName,'Basic',false); %load the matrix of trial timings eeglabDir = 'C:\Users\hype2\Documents\MATLAB\eeglab2022.0'; %eeglab directory as we need some functions addpath(genpath(eeglabDir)); %add folders and subfolders to path channelsToPlot = [21 22 25 26 27]; channelsLabel = {'cp1', 'cp2', 'p3', 'pz', 'p4'}; % these are the electrodes names doFig = 0; %if set to 1 then a time frequency figure for every trial will be plotted, this is 4s before and after the midpoint for thisSubjectNum = 8 %the number of subject whose EEG is currently loaded subjectString = sprintf('%02d',thisSubjectNum); eegFileName = [baseDir subjectString '\pilot_' subjectString '_filt_postICA_lowfilt_reref.set']; [ALLEEG, EEG, CURRENTSET, ALLCOM] = eeglab; EEG = pop_loadset('filename', eegFileName); [ALLEEG, EEG, CURRENTSET] = eeg_store(ALLEEG, EEG, 0); trialList = find(allResultsTable(:,1)==thisSubjectNum); for trialNum = trialList' timeMid = allResultsTable(trialNum,13); if doFig figure; out = pop_newtimef( EEG, 1, 26, [timeMid*1000-4000 timeMid*1000+4000], 0); end out = pop_spectopo( EEG, 1, [timeMid*1000-1000 timeMid*1000+1000],'EEG','freqrange',[2 35],'freqs',5); %get the average pwoer in the 8:12 Hz frequency band for the channels %of interest bandMus = mean(out(channelsToPlot,8:12),2); %copy to correct columns of results table allResultsTable(trialNum,7:11) = bandMus; end end %now save writematrix(allResultsTable,'.\trialResultsAllSubjectsComplete.xlsx')
报错信息
Error using spectopo Spectopo: non-integer number of epochs Error in pop_spectopo (line 331) eval(com) Error in getTfrFromMidPoint (line 32) out = pop_spectopo( EEG, 1, [timeMid*1000-1000 timeMid*1000+1000],'EEG','freqrange',[2 35],'freqs',5)
报错触发代码(来自spectopo函数)
epochs = round(size(data,2)/frames); if frames*epochs ~= size(data,2) error('Spectopo: non-integer number of epochs'); end
时间同步表生成脚本(依赖代码)
%in the table (when loaded as a matrix): %for each trial to understand which time point to extract from the EEG we %need to find the mid point of the ball movement to the corner. %this is % column 3 is overall trial number (including practice trials and isntruction screens) % 4 is block number: % (1= practice1 instruction, 2= practice 1, 3= practice 2 instruction,... % 4 = practice 2, 5 = block 1 instruction, 6= block 1, 7 = block 2 % instruction, 8 = block 2, 9 = block 3 instruction, 10 = block 3) %ballstart time is column 9 %estimated mid time (light off) is 10 %actual mid time is 11 %estimated end time is 12 %actual end time is 13 (but need to subtract 5s from this) %15 is which corner the ball goes to (1=BL,2=BR,3=FL,4=FR) %16 is movement speed of the ball. eegVRTimeLags = [213.6 545.64 929.2 nan 469.87 200.84 320 710.8 573.6 774.5]; %when VR was time 0, EEG was this time in seconds %in results table columns will be %1 = subjectnum %2 = trialnumber (only real trials so 1:96) %3 = end point of the ball (1=BL,2=BR,3=FL,4=FR) %4 = speed of the ball (0.5, 1, 1.5 or 2) %5 = the estiamted time length of ball travel %6 = the actual time length of ball travel %7 = alpha power at 'cp1' %8 = 'cp2' %9 = 'p3' %10 = 'pz' %11 = 'p4' %12 = time point in eeg to extract in VR headset time %13 = time point in EEG time to extract in EEG time %TODO need to think about how to save synchronsiation information trialsToAnalyse = [12:43 45:76 78:109]; %this refers to row numbers in the data matrix loaded here numSubjects = 10; allResultsTable = nan(numSubjects*96,11); trialCounter = 1; for subjectNum = 1:numSubjects thisSubFolder = ['C:\Users\ASUS\OneDrive - Goldsmiths College\Attachments\DISSERTATION\' sprintf('%02d',subjectNum),'\']; trialData = readmatrix([thisSubFolder 'trial_results.csv']); tempTrialCounter = 1; for trialNum = trialsToAnalyse allResultsTable(trialCounter,1) = subjectNum; allResultsTable(trialCounter,2) = trialCounter; allResultsTable(trialCounter,3) = trialData(trialNum,15); allResultsTable(trialCounter,4) = trialData(trialNum,16); allResultsTable(trialCounter,5) = trialData(trialNum,12)-trialData(trialNum,10); allResultsTable(trialCounter,6) = trialData(trialNum,13)-trialData(trialNum,11)-5; allResultsTable(trialCounter,12) = (trialData(trialNum,13)+trialData(trialNum,11)-5)/2; allResultsTable(trialCounter,13) = allResultsTable(trialCounter,12)+eegVRTimeLags(subjectNum); tempTrialCounter = tempTrialCounter +1; trialCounter = trialCounter+1; end end writematrix(allResultsTable,'.\trialResultsAllSubjects.xlsx')
原因分析
frames的含义:在EEGLAB的spectopo函数中,frames指的是频谱分析时使用的单段数据采样点数(即FFT窗口长度)。函数会把指定时间窗口内的EEG数据拆分成若干个frames长度的段(epochs)计算频谱,若总采样点数不是frames的整数倍,就会触发报错。- 为何仅8-10号受试者报错:时间同步脚本里的
eegVRTimeLags中,8-10号的时间偏移是710.8、573.6、774.5这类带小数的数值,计算出的timeMid(EEG时间,对应allResultsTable第13列)是带小数的浮点数。转换为毫秒后,对应的采样点范围不是整数边界,导致提取的总采样点数无法被frames整除。而1-7号的时间偏移计算后,timeMid对应的毫秒范围刚好匹配整数采样点,因此不会触发报错。
解决方案
方案1:用采样点索引替代毫秒时间范围(推荐)
直接基于EEG采样率计算窗口的起始/结束采样点,确保提取的总点数是整数且能被frames整除:
% 在循环内添加这段代码,替换原pop_spectopo调用 timeMid = allResultsTable(trialNum,13); srate = EEG.srate; % 获取当前EEG数据的采样率 % 计算1秒前到1秒后的采样点索引(取整确保是整数) win_start = round((timeMid - 1) * srate); win_end = round((timeMid + 1) * srate); % 调整窗口长度,确保是frames的整数倍(frames通常为256,或用round(srate * 0.25)取默认值) frames = 256; win_length = win_end - win_start + 1; adjusted_win_length = floor(win_length / frames) * frames; win_end = win_start + adjusted_win_length - 1; % 调用pop_spectopo,传入采样点范围 out = pop_spectopo(EEG, 1, [win_start win_end], 'EEG', 'freqrange', [2 35], 'freqs', 5);
方案2:对毫秒时间取整
如果不想调整采样点,可直接对timeMid*1000取整,确保时间窗口是整数毫秒,减少采样点计算误差:
timeMid = allResultsTable(trialNum,13); timeMid_ms = round(timeMid * 1000); % 取整为整数毫秒 out = pop_spectopo( EEG, 1, [timeMid_ms-1000 timeMid_ms+1000],'EEG','freqrange',[2 35],'freqs',5);
方案3:检查EEG数据一致性
确认8-10号受试者的EEG数据采样率与1-7号是否一致:加载EEG后查看EEG.srate,若采样率不同,需统一处理或调整时间转换逻辑。
内容的提问来源于stack exchange,提问作者DerKeller
相关产品推荐
相关产品推荐

