Neural Mechanisms of Self-Generated Action Sequences.
The 2 matches
- [1] § Materials and Methods › EEG analyses › Preprocessing ↔ 01Scripts.zip/01Scripts/Preprocessing.m, lines 304–350 · score 0.81 · horizontal eye movement, Independent component, runica, EEGLAB, preprocessing, electrodes
- [2] § Materials and Methods › Behavioral data analysis ↔ 01Scripts.zip/01Scripts/ToL_EEG_BEH_analyses.R, lines 150–230 · score 0.63 · Post hoc, MovementType, transformed, sequence length, stimulus driven, ID
Paper
Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC
The paper is loaded when this pane is shown.
The authors' code
MATLAB · 718 lines · 29 KB · no license · 1 match
- %% EEGlab preprocessing sample script
- % UCL, ICN - London
- clc
- clear
- %% Set experimental analysis parameters
- % If you are working with your own data, please change this code to match
- % your datafiles.
- exp.name = 'S3'
- % Change to your computer's directories
- exp.behpath = ['/Volumes/T7/02UCL/07EEGVolition&ProblemSolving/'];
- exp.database = ['/Volumes/T7/02UCL/07EEGVolition&ProblemSolving/00EEG/01ConvertedData']
- exp.filepath = ['/Volumes/T7/02UCL/07EEGVolition&ProblemSolving/00EEG/02Preprocessing'];
- exp.sub_id = [1];
- exp.nsub = length(exp.sub_id);
- exp.sr = 200; % sampling rate after downsampling
- exp.Chans = [1:3,7,17];
- exp.ChanLabels = {'Fz,FCz,Cz,FC1,FC2'};
- exp.filter.lowerbound = 0; % high pass
- exp.filter.upperbound = 30; % low pass
- exp.downsampling_rate = 200; % downsampling rate
- exp.Epoch = [-1 0.5]; %s
- exp.Baseline = [-5 5]; %ms
- exp.artefact = 120
- % Indices of channels to include in the ICA.
- % Include only one of the VEOG (27), and one of the HEOG (29).
- exp.icachanind = [1:27,29]
- %% Pre-ICA pipeline, preprocessing
- for sub = exp.sub_id(1:end)
- % Load file
- EEG = pop_loadset([exp.database '/' 'P' num2str(sub) '.set']);
- EEG.setname=['P' num2str(sub)];
- EEG = pop_chanedit(EEG, 'lookup','/Applications/eeglab2021.0/functions/supportfiles/Standard-10-5-Cap385_witheog.elp');
- EEG = eeg_checkset( EEG );
- clear_boundary=true;
- % Clean triggers
- % This is usually not a required step - but we have been having issues
- % with the NIDaq box, resulting in extra, non-task related triggers
- % being recorded. This function cleans them.
- %EEG = O1_cleanTriggers(sub,exp); % remove extra triggers
- %O1_checkTriggerNumbers(sub,exp)
- % Clean triggers
- all_latencies= [EEG.event.latency]';
- for index= 1: size(all_latencies,1)
- if index < size(all_latencies,1)&& index >1
- if all_latencies(index)~= all_latencies(index+1) && all_latencies(index)~= all_latencies(index-1)
- wrong_trigger_filter(index)= 1;
- else
- wrong_trigger_filter(index)= 0;
- wrong_trigger_filter(index+1)= 0;
- end
- elseif index < size(all_latencies,1)&& index ==1
- if all_latencies(index)~= all_latencies(index+1)
- wrong_trigger_filter(index)= 1;
- else
- wrong_trigger_filter(index)= 0;
- wrong_trigger_filter(index+1)= 0;
- end
- else
- if all_latencies(index)~= all_latencies(index-1)
- wrong_trigger_filter(index)= 1;
- else
- wrong_trigger_filter(index)= 0;
- end
- end
- end
- all_latencies(:,2)= wrong_trigger_filter;
- EEG.event = EEG.event(wrong_trigger_filter==1);
- % Add metadata
- clear BEHAVIORAL;
- clear b1;
- clear b2;
- clear b3;
- clear b4;
- clear b5;
- clear b6;
- clear p1;
- clear p2;
- clear p3;
- clear p4;
- clear p5;
- clear p6;
- p1= ['00Behavioural/P' num2str(sub),'/ToL_fMRI_LOG_P', num2str(sub),'_Random',num2str(sub), 'Run1.xls'];
- p2= ['00Behavioural/P' num2str(sub),'/ToL_fMRI_LOG_P', num2str(sub),'_Random',num2str(sub), 'Run2.xls'];
- p3= ['00Behavioural/P' num2str(sub),'/ToL_fMRI_LOG_P', num2str(sub),'_Random',num2str(sub), 'Run3.xls'];
- p4= ['00Behavioural/P' num2str(sub),'/ToL_fMRI_LOG_P', num2str(sub),'_Random',num2str(sub), 'Run4.xls'];
- p5= ['00Behavioural/P' num2str(sub),'/ToL_fMRI_LOG_P', num2str(sub),'_Random',num2str(sub), 'Run5.xls'];
- p6= ['00Behavioural/P' num2str(sub),'/ToL_fMRI_LOG_P', num2str(sub),'_Random',num2str(sub), 'Run6.xls'];
- %initialize BEHAVIORAL file
- [~,~,b1] = xlsread(p1);
- behnames= b1(1,:);
- b1= b1(2:size(b1,1), :); %eliminate first row
- b1= b1(1:(size(b1,1)-1), :); %eliminate last row
- for IND= 1:size(b1,1) %look for jitters
- JF(IND)= (strcmp(b1{IND,11}, 'Choice_Jitter')|strcmp(b1{IND,11}, 'Release_Jitter'))==false;
- end
- b1=b1(JF,:);
- BEHAVIORAL= b1;
- clear JF;
- if exist(p2)==2
- [~,~,b2] = xlsread(p2);
- b2= b2(2:size(b2,1), :); %eliminate first row
- b2= b2(1:(size(b2,1)-1), :); %eliminate last row
- for IND= 1:size(b2,1) %look for jitters
- JF(IND)= (strcmp(b2{IND,11}, 'Choice_Jitter')|strcmp(b2{IND,11}, 'Release_Jitter'))==false;
- end
- b2=b2(JF,:);
- BEHAVIORAL= [BEHAVIORAL; b2];
- end
- clear JF;
- if exist(p3)==2
- [~,~,b3] = xlsread(p3);
- b3= b3(2:size(b3,1), :); %eliminate first row
- b3= b3(1:(size(b3,1)-1), :); %eliminate last row
- for IND= 1:size(b3,1) %look for jitters
- JF(IND)= (strcmp(b3{IND,11}, 'Choice_Jitter')|strcmp(b3{IND,11}, 'Release_Jitter'))==false;
- end
- b3=b3(JF,:);
- BEHAVIORAL= [BEHAVIORAL; b3];
- end
- clear JF;
- if exist(p4)==2
- [~,~,b4] = xlsread(p4);
- b4= b4(2:size(b4,1), :); %eliminate first row
- b4= b4(1:(size(b4,1)-1), :); %eliminate last row
- for IND= 1:size(b4,1) %look for jitters
- JF(IND)= (strcmp(b4{IND,11}, 'Choice_Jitter')|strcmp(b4{IND,11}, 'Release_Jitter'))==false;
- end
- b4=b4(JF,:);
- BEHAVIORAL= [BEHAVIORAL; b4];
- end
- clear JF;
- if exist(p5)==2
- [~,~,b5] = xlsread(p5);
- b5= b5(2:size(b5,1), :); %eliminate first row
- b5= b5(1:(size(b5,1)-1), :); %eliminate last row
- for IND= 1:size(b5,1) %look for jitters
- JF(IND)= (strcmp(b5{IND,11}, 'Choice_Jitter')|strcmp(b5{IND,11}, 'Release_Jitter'))==false;
- end
- b5=b5(JF,:);
- BEHAVIORAL= [BEHAVIORAL; b5];
- end
- clear JF;
- if exist(p6)==2
- [~,~,b6] = xlsread(p6);
- b6= b6(2:size(b6,1), :); %eliminate first row
- b6= b6(1:(size(b6,1)-1), :); %eliminate last row
- for IND= 1:size(b6,1) %look for jitters
- JF(IND)= (strcmp(b6{IND,11}, 'Choice_Jitter')|strcmp(b6{IND,11}, 'Release_Jitter'))==false;
- end
- b6=b6(JF,:);
- BEHAVIORAL= [BEHAVIORAL; b6];
- end
- %get rid of trigger 7
- for index6 =1:size(EEG.event,2)
- Filt(index6)= strcmp(EEG.event(index6).type, 'Trigger 7');
- end
- EEG.event=EEG.event(Filt==0);
- clear index6
- clear Filt
- %get rid of boundary
- if clear_boundary==true
- for index6 =1:size(EEG.event,2)
- Filt(index6)= strcmp(EEG.event(index6).type, 'boundary');
- end
- EEG.event=EEG.event(Filt==0);
- end
- counter=1; %use this to index the BEHAVIORAL file
- for index7 =1:size(EEG.event,2)
- if strcmp(EEG.event(index7).type, 'Trigger 7')
- else
- EEG.event(index7).ID= num2str(BEHAVIORAL{counter,1});
- EEG.event(index7).Random= num2str(BEHAVIORAL{counter,2});
- EEG.event(index7).Run= num2str(BEHAVIORAL{counter,3});
- EEG.event(index7).Active_Passive= num2str(BEHAVIORAL{counter,4});
- EEG.event(index7).Problem_code= num2str(BEHAVIORAL{counter,5});
- EEG.event(index7).min_number_of_moves= num2str(BEHAVIORAL{counter,6});
- EEG.event(index7).Factor1= num2str(BEHAVIORAL{counter,7});
- EEG.event(index7).Factor2= num2str(BEHAVIORAL{counter,8});
- EEG.event(index7).Factor3= num2str(BEHAVIORAL{counter,9});
- EEG.event(index7).Counter= num2str(BEHAVIORAL{counter,10});
- EEG.event(index7).EventName= num2str(BEHAVIORAL{counter,11});
- EEG.event(index7).Onset= num2str(BEHAVIORAL{counter,12});
- EEG.event(index7).Duration= num2str(BEHAVIORAL{counter,13});
- EEG.event(index7).Wrong_Choice= num2str(BEHAVIORAL{counter,14});
- EEG.event(index7).Wrong_Release= num2str(BEHAVIORAL{counter,15});
- counter= counter+1;
- end
- end
- end
- %%
- for sub = exp.sub_id(1:end)
- %% Re-reference to average of mastoids
- % There are many ways to re-reference EEG data. T
- EEG = pop_reref( EEG, [27 28] ); % re-reference to average of mastoids *channels
- EEG = eeg_checkset( EEG );
- filename = ['r' exp.name '_P' num2str(sub)];
- EEG = pop_saveset( EEG, filename, exp.filepath);
- % Identify bad channels based on kurtosis
- % Note - there are other methods.
- % Take this only as a hint - always check
- % visually!
- [iEEG,indelec] = pop_rejchan(EEG,'elec',[1:30],'threshold',5,'norm','on','measure','kurt');
- EEG.badChan = indelec;
- % Interpolate bad channels
- % EEG = eeg_interp(EEG,indelec);
- %% Filter
- % This is an important step. The parameters chosen vary depending on
- % which kind of analyses need to be run. In our case, we will use a
- % relatively low high-pass filter because we may want to look at the
- % RP, and a low low-pass filter as well, because we are not interested
- % in high-frequency EEG activity. To decide which parameters to use,
- % check previous papers analysing your signal of interest and follow
- % their guidelines.
- EEG = pop_basicfilter(EEG, 1:30 , 'Boundary', 'boundary', 'Cutoff', [exp.filter.lowerbound exp.filter.upperbound], 'Design', 'butter', 'Filter', 'bandpass', 'order',8);
- EEG = eeg_checkset( EEG );
- filename = ['fr' exp.name '_P' num2str(sub)];
- EEG = pop_saveset( EEG, filename, exp.filepath);
- % Let's see what the filtered data look like...
- EEG1 = pop_loadset([exp.filepath '/r' exp.name '_P' num2str(sub) '.set']);
- EEG2 = eeg_checkset( EEG );
- eegplot([EEG1.data], 'data2', [EEG2.data], 'color','off')
- %% Downsample
- % This is not strictly necessary, especially if the recording sampling
- % rate is already low as in our case (256Hz). I include it for
- % completion purposes.
- EEG = eeg_checkset( EEG );
- EEG = pop_resample( EEG, exp.downsampling_rate);
- EEG = eeg_checkset( EEG );
- filename = ['df8r' exp.name '_P' num2str(sub)];
- EEG = pop_saveset( EEG, filename, exp.filepath);
- %% Epoch around events of interest (e.g. Trigger 2)
- % In your experiment, you may have different types of events that you want to look at,
- % requiring different epoching parameters. In that case, you would need
- % to specify the various Triggers of interest and their respective
- % epoching times.
- EEG = pop_loadset([exp.filepath '/' 'df8r' exp.name '_P' num2str(sub) '.set']);
- EEG = pop_epoch( EEG, {'Trigger 2'}, exp.Epoch, 'epochinfo', 'yes');
- EEG = eeg_checkset( EEG );
- EEG = pop_saveset( EEG, ['e_df8r' exp.name '_P' num2str(sub)], exp.filepath);
- %% Baseline correct
- % Baselining takes the baseline epoch and moves the whole epoch "up" or
- % "down" so that the average baseline signal is 0. This allows
- % comparing multiple epochs.
- EEG = pop_loadset([exp.filepath '/' '/e_df8r' exp.name '_P' num2str(sub) '.set']);
- EEG = pop_rmbase( EEG, exp.Baseline);
- EEG = pop_saveset( EEG, ['be_df8r' exp.name '_P' num2str(sub)], exp.filepath);
- %% Let's see what the baselined data look like...
- EEG1 = pop_loadset([exp.filepath '/' '/e_df8r' exp.name '_P' num2str(sub) '.set']);
- EEG2 = eeg_checkset( EEG );
- eegplot([EEG1.data], 'data2', [EEG2.data], 'color','off')
- %% Run ICA & plot component maps
- % We use the Independent Component Analysis to identify eye movements
- % and remove them from the signal.
- % ICA can also be used to identify physiological / cognitive components
- % of interest, and use them for analysis instead of using raw channel
- % data. We will not do this here, but it is an approach worth
- % investigating.
- EEG = eeg_checkset( EEG ); % set right channel names before ICA
- EEG = pop_runica(EEG, 'extended',0,'interupt','on', 'chanind', exp.icachanind);
- EEG = pop_chanedit(EEG, 'lookup','/Applications/eeglab2021.0/functions/supportfiles/Standard-10-5-Cap385_witheog.elp');
- EEG = eeg_checkset( EEG );
- EEG = pop_saveset( EEG, ['ICAbe_df8r' exp.name '_P' num2str(sub)], exp.filepath);
- % Plot ICA result
- pop_topoplot(EEG,0, [1:28] ,'O1_P0 resampled epochs',[5 6] ,0,'electrodes','on');
- % % If you want to use the EEGlab GUI:
- % % Start the GUI by typing eeglab
- % % Plot -> component maps -> 2D
- % % Tools -> remove components from data -> type component to remove ... -> plot single trials ->
- % % acccept -> save
- % In this example dataset, components 1 and 2 are clearly eye movement
- % components. Component 1 corresponds to eye blinks, and component 4 to
- % horizontal eye movements. Let's see what happens when we remove them.
- % Go to the GUI and run
- % Tools -> remove components from data -> type "1 2" in component to remove ... -> plot single trials ->
- % In this dataset, Channel 27 corresponds to VEOG, and 28 to HEOG. You
- % can look this up in the EEG.chanlocs field.
- % Red lines are after correction, blue lines before correction.
- % Notice how in epochs containing eyeblinks (e.g. epoch 6) channel 27 (VEOG) is completely flat after
- % correction. Notice how EEG channels with eyeblink artefacts are also
- % fully corrected.
- % Similarly, in epochs containin horizontal eye movements (e.g. epoch
- % 62) channel 28 (HEOG) is completely flat after correction. EEG
- % channels should be corrected too.
- % Once you've checked that the components you identified as eye
- % movements are correct, you can accept removing them and save the new
- % dataset.
- end
- %% Post-ICA correction pipeline
- for sub = exp.sub_id(1:end)
- %% Artefact rejection
- % This is one additional artefact rejection step to ensure that no
- % epochs contain excessive fluctuations. We use a thresholding
- % procedure, and reject any epochs with voltages spanning +/- 120uV
- % from baseline. This value is reasonable, but arbitrary - many papers
- % use a 80uV threshold, but given that we use a very low high pass
- % filter, our epochs contain a greater degree of drift. Thus, we allow
- % for wider fluctuations.
- % Note: there are many other approaches to artefact rejection - you may
- % wish to pick your own.
- EEG = pop_loadset([exp.filepath '/' 'cICAbe_df8r' exp.name '_P' num2str(sub) '.set']);
- [EEG, iart] = pop_eegthresh(EEG,1,exp.Chans ,-120,120, -2.5,0.995,0,1);
- EEG.iart = iart; % We need to save the artefact indices so we can remove them from the behavioural data too.
- EEG = pop_saveset( EEG, ['acICAbe_df8r' exp.name '_P' num2str(sub)], exp.filepath);
- end
- %% Plot
- for sub = exp.sub_id(1:end)i = 0
- figure
- for sub = exp.sub_id(1:end)
- EEG = pop_loadset(['/Volumes/T7/02UCL/07EEGVolition&ProblemSolving/00EEG/02Preprocessing/acICAbe_df8rS3_P' num2str(sub) '.set']);
- i = i+1
- %subplot(7,4,i)
- plot(mean(EEG.data(exp.Chans,:,:),3)') % Plot channel of interest
- xline(201)
- end
- end
- %% Extract figure data
- for sub = exp.sub_id(1:end)
- EEG = pop_loadset(['/Volumes/S/02UCL/07EEGVolition&ProblemSolving/00EEG/02Preprocessing/acICAbe_df8rS3_P' num2str(sub) '.set']);
- %check how many epochs contain more than one event of interest
- for indx= 1: size(EEG.epoch,2)
- EOI(indx)=sum(strcmp(EEG.epoch(indx).eventtype, 'Trigger 2'));
- EOI_f(indx)=sum(strcmp(EEG.epoch(indx).eventtype, 'Trigger 2'))==1;
- end
- clear indx
- %keep only channels we need
- eeg=EEG.data(exp.Chans,:,:);
- %initialize filters
- active_2_1_f=zeros(1,size(EEG.epoch,2));
- active_2_other_f=zeros(1,size(EEG.epoch,2));
- active_4_1_f=zeros(1,size(EEG.epoch,2));
- active_4_other_f=zeros(1,size(EEG.epoch,2));
- passive_2_1_f=zeros(1,size(EEG.epoch,2));
- passive_2_other_f=zeros(1,size(EEG.epoch,2));
- passive_4_1_f=zeros(1,size(EEG.epoch,2));
- passive_4_other_f=zeros(1,size(EEG.epoch,2));
- %we need four datasets: (1) active; (2) passive; (3) 1 active; (4) no1 active
- for indx= 1: size(EEG.epoch,2)
- if EOI(indx)==1 && EOI_f(indx)==1 && strcmp(EEG.epoch(indx).eventActive_Passive(strcmp(EEG.epoch(indx).eventtype, 'Trigger 2')), 'active'); %create active
- if strcmp(EEG.epoch(indx).eventCounter(strcmp(EEG.epoch(indx).eventtype, 'Trigger 2')), '1')
- if strcmp(EEG.epoch(indx).eventmin_number_of_moves(strcmp(EEG.epoch(indx).eventtype, 'Trigger 2')), '2')
- active_2_1_f(indx)=1;
- elseif strcmp(EEG.epoch(indx).eventmin_number_of_moves(strcmp(EEG.epoch(indx).eventtype, 'Trigger 2')), '4')
- active_4_1_f(indx)=1;
- end
- else
- if strcmp(EEG.epoch(indx).eventmin_number_of_moves(strcmp(EEG.epoch(indx).eventtype, 'Trigger 2')), '2')
- active_2_other_f(indx)=1;
- elseif strcmp(EEG.epoch(indx).eventmin_number_of_moves(strcmp(EEG.epoch(indx).eventtype, 'Trigger 2')), '4')
- active_4_other_f(indx)=1;
- end
- end
- elseif EOI(indx)==1 && EOI_f(indx)==1 && strcmp(EEG.epoch(indx).eventActive_Passive(strcmp(EEG.epoch(indx).eventtype, 'Trigger 2')), 'passive'); %create passive
- if strcmp(EEG.epoch(indx).eventCounter(strcmp(EEG.epoch(indx).eventtype, 'Trigger 2')), '1')
- if strcmp(EEG.epoch(indx).eventmin_number_of_moves(strcmp(EEG.epoch(indx).eventtype, 'Trigger 2')), '2')
- passive_2_1_f(indx)=1;
- elseif strcmp(EEG.epoch(indx).eventmin_number_of_moves(strcmp(EEG.epoch(indx).eventtype, 'Trigger 2')), '4')
- passive_4_1_f(indx)=1;
- end
- else
- if strcmp(EEG.epoch(indx).eventmin_number_of_moves(strcmp(EEG.epoch(indx).eventtype, 'Trigger 2')), '2')
- passive_2_other_f(indx)=1;
- elseif strcmp(EEG.epoch(indx).eventmin_number_of_moves(strcmp(EEG.epoch(indx).eventtype, 'Trigger 2')), '4')
- passive_4_other_f(indx)=1;
- end
- end
- end
- end
- ACTIVE_2_1=eeg(:,:,active_2_1_f==1);
- ACTIVE_2_1=mean(ACTIVE_2_1,1);
- ACTIVE_2_1=mean(ACTIVE_2_1,3);
- ACTIVE_2_1=squeeze(ACTIVE_2_1);
- ACTIVE_4_1=eeg(:,:,active_4_1_f==1);
- ACTIVE_4_1=mean(ACTIVE_4_1,1);
- ACTIVE_4_1=mean(ACTIVE_4_1,3);
- ACTIVE_4_1=squeeze(ACTIVE_4_1);
- ACTIVE_2_other=eeg(:,:,active_2_other_f==1);
- ACTIVE_2_other=mean(ACTIVE_2_other,1);
- ACTIVE_2_other=mean(ACTIVE_2_other,3);
- ACTIVE_2_other=squeeze(ACTIVE_2_other);
- ACTIVE_4_other=eeg(:,:,active_4_other_f==1);
- ACTIVE_4_other=mean(ACTIVE_4_other,1);
- ACTIVE_4_other=mean(ACTIVE_4_other,3);
- ACTIVE_4_other=squeeze(ACTIVE_4_other);
- PASSIVE_2_1=eeg(:,:,passive_2_1_f==1);
- PASSIVE_2_1=mean(PASSIVE_2_1,1);
- PASSIVE_2_1=mean(PASSIVE_2_1,3);
- PASSIVE_2_1=squeeze(PASSIVE_2_1);
- PASSIVE_4_1=eeg(:,:,passive_4_1_f==1);
- PASSIVE_4_1=mean(PASSIVE_4_1,1);
- PASSIVE_4_1=mean(PASSIVE_4_1,3);
- PASSIVE_4_1=squeeze(PASSIVE_4_1);
- PASSIVE_2_other=eeg(:,:,passive_2_other_f==1);
- PASSIVE_2_other=mean(PASSIVE_2_other,1);
- PASSIVE_2_other=mean(PASSIVE_2_other,3);
- PASSIVE_2_other=squeeze(PASSIVE_2_other);
- PASSIVE_4_other=eeg(:,:,passive_4_other_f==1);
- PASSIVE_4_other=mean(PASSIVE_4_other,1);
- PASSIVE_4_other=mean(PASSIVE_4_other,3);
- PASSIVE_4_other=squeeze(PASSIVE_4_other);
- time= -1000:5:495;
- A_2_1= cat(2, num2cell(time'), num2cell(ACTIVE_2_1'), repmat({'Intention'}, length(ACTIVE_2_1),1), repmat({'2'}, length(ACTIVE_2_1),1), repmat({'First'}, length(ACTIVE_2_1),1));
- A_2_other= cat(2,num2cell(time'),num2cell(ACTIVE_2_other'), repmat({'Intention'}, length(ACTIVE_2_other),1), repmat({'2'}, length(ACTIVE_2_other),1), repmat({'Other'}, length(ACTIVE_2_other),1));
- A_4_1= cat(2,num2cell(time'),num2cell(ACTIVE_4_1'), repmat({'Intention'}, length(ACTIVE_4_1),1), repmat({'4'}, length(ACTIVE_4_1),1), repmat({'First'}, length(ACTIVE_4_1),1));
- A_4_other= cat(2,num2cell(time'),num2cell(ACTIVE_4_other'), repmat({'Intention'}, length(ACTIVE_4_other),1), repmat({'4'}, length(ACTIVE_4_other),1), repmat({'Other'}, length(ACTIVE_4_other),1));
- P_2_1= cat(2,num2cell(time'),num2cell(PASSIVE_2_1'), repmat({'Stimulus'}, length(PASSIVE_2_1),1), repmat({'2'}, length(PASSIVE_2_1),1), repmat({'First'}, length(PASSIVE_2_1),1));
- P_2_other= cat(2,num2cell(time'),num2cell(PASSIVE_2_other'), repmat({'Stimulus'}, length(PASSIVE_2_other),1), repmat({'2'}, length(PASSIVE_2_other),1), repmat({'Other'}, length(PASSIVE_2_other),1));
- P_4_1= cat(2,num2cell(time'),num2cell(PASSIVE_4_1'), repmat({'Stimulus'}, length(PASSIVE_4_1),1), repmat({'4'}, length(PASSIVE_4_1),1), repmat({'First'}, length(PASSIVE_4_1),1));
- P_4_other= cat(2,num2cell(time'),num2cell(PASSIVE_4_other'), repmat({'Stimulus'}, length(PASSIVE_4_other),1), repmat({'4'}, length(PASSIVE_4_other),1), repmat({'Other'}, length(PASSIVE_4_other),1));
- out= cat(1,A_2_1, A_2_other, A_4_1, A_4_other, P_2_1, P_2_other, P_4_1, P_4_other);
- out= cat(2, num2cell(repmat(sub, size(out,1),1)), out);
- T=table(out(:,1),out(:,2), out(:,3), out(:,4), out(:,5), out(:,6));
- T.Properties.VariableNames={'ID', 'Time', 'Amplitude', 'Condition', 'Moves','Trial'};
- % % % writetable(t_OUT,strcat('Proccessed_FiveChannelsAverage_S', num2str(sub), '.xlsx')); %write output
- writetable(T,strcat('Tol4Plot_S', num2str(sub), '.xlsx')); %write output
- clear TL;
- clear TL_f;
- clear OUT;
- clear t_OUT;
- clear index8;
- clear index9;
- clear average1;
- clear average2;
- clear average3;
- clear average4;
- clear ch_average500;
- clear ch_average1000;
- clear ch_std500;
- clear ch_std1000;
- clear ch_std;
- clear filter_event_3;
- end
- %% Extract action data
- for sub = exp.sub_id(1:end)
- EEG = pop_loadset(['/Volumes/S/02UCL/07EEGVolition&ProblemSolving/00EEG/02Preprocessing/acICAbe_df8rS3_P' num2str(sub) '.set']);
- %mean Amplitude 50ms%
- average1 = mean(EEG.data(:,191:200,:),2); %here
- ch_average50 = squeeze(mean(average1(exp.Chans,:,:),1)); %hered
- %mean Amplitude 100ms%
- average2 = mean(EEG.data(:,181:200,:),2); %here
- ch_average100 = squeeze(mean(average2(exp.Chans,:,:),1)); %hered
- %mean Amplitude 500ms%
- average3 = mean(EEG.data(:,101:200,:),2); %here
- ch_average500 = squeeze(mean(average3(exp.Chans,:,:),1)); %hered
- %mean Amplitude 1000ms%
- average4 = mean(EEG.data(:,1:200,:),2); %here
- ch_average1000 = squeeze(mean(average4(exp.Chans,:,:),1)); %hered
- %STD 50ms%
- average5 = mean(EEG.data(exp.Chans,191:200,:),1); %here
- ch_std50 = squeeze(std(average5(:,:,:),0,2)); %hered
- %STD 100ms%
- average6 = mean(EEG.data(exp.Chans,181:200,:),1); %here
- ch_std100 = squeeze(std(average6(:,:,:),0,2)); %hered
- %STD 500ms%
- average7 = mean(EEG.data(exp.Chans,101:200,:),1); %here
- ch_std500 = squeeze(std(average7(:,:,:),0,2)); %hered
- %STD 1000ms%
- average8 = mean(EEG.data(exp.Chans,1:200,:),1); %here
- ch_std1000 = squeeze(std(average8(:,:,:),0,2)); %hered
- % %mean and sd for 20 bins of 50 (49) ms (10 samples) each%
- avg_mtx= zeros(size(EEG.data,3),21) ; %initialize matrix of Average Amplitudes in 20 bins + 1 vector for slope
- sd_mtx= zeros(size(EEG.data,3),21) ; %initialize matrix of sd Amplitudes in 20 bins + 1 vector for slope
- for bin= 1:20
- sample_ini=1+(10*bin) -10;
- sample_end= 0+(10*bin);
- %average for each bin
- average_bin = mean(EEG.data(:,sample_ini:sample_end,:),2); %
- ch_average_bin = squeeze(mean(average_bin(exp.Chans,:,:),1)); %
- avg_mtx(:,bin)= ch_average_bin;
- clear average_bin;
- clear ch_average_bin;
- %sd for each bin
- sd_bin = std(EEG.data(:,sample_ini:sample_end,:),0,2); %
- ch_sd_bin = squeeze(mean(sd_bin(exp.Chans,:,:),1)); %
- sd_mtx(:,bin)= ch_sd_bin;
- clear average_bin;
- clear ch_average_bin;
- end
- %slope for 20 bins of 10 samples each
- for TRIAL = 1:size(avg_mtx,1)
- %get slope and write it in colum 21
- mod = fitlm([1:20],avg_mtx(TRIAL,1:size(avg_mtx,2)-1));
- avg_mtx(TRIAL,21)= mod.Coefficients.Estimate(2);
- mod_sd = fitlm([1:20],sd_mtx(TRIAL,1:size(sd_mtx,2)-1));
- sd_mtx(TRIAL,21)= mod_sd.Coefficients.Estimate(2);
- clear mod
- clear mod_sd
- end
- %slope for all samples
- for TRIAL = 1:size(avg_mtx,1)
- %get slope and write it in colum 21
- AMP=squeeze(mean(EEG.data(exp.Chans,1:200,TRIAL),1));
- mod_all = fitlm([1:200],AMP);
- ALL(TRIAL,1)= mod_all.Coefficients.Estimate(2);
- clear AMP
- clear mod_all
- end
- %get trial info
- % for index9= 1: size(EEG.event,2)
- % TL {index9,1}= EEG.event(index9).ID;
- % TL {index9,2}= EEG.event(index9).Random;
- % TL {index9,3}= EEG.event(index9).Run;
- % TL {index9,4}= EEG.event(index9).Active_Passive;
- % TL {index9,5}= EEG.event(index9).Problem_code;
- % TL {index9,6}= EEG.event(index9).min_number_of_moves;
- % TL {index9,7}= EEG.event(index9).Factor1;
- % TL {index9,8}= EEG.event(index9).Factor2;
- % TL {index9,9}= EEG.event(index9).Factor3;
- % TL {index9,10}= EEG.event(index9).Counter;
- % TL {index9,11}= EEG.event(index9).EventName;
- % TL {index9,12}= EEG.event(index9).Onset;
- % TL {index9,13}= EEG.event(index9).Duration;
- % TL {index9,14}= EEG.event(index9).Wrong_Choice;
- % TL {index9,15}= EEG.event(index9).Wrong_Release;
- % TL {index9,16}= EEG.event(index9).epoch;
- %
- % TL {index9,17}= EEG.event(index9).type(9); %n trigger
- % end
- for index9= 1: size(EEG.epoch,2)
- TL {index9,1}= EEG.epoch(index9).eventID{strcmp(EEG.epoch(index9).eventtype, 'Trigger 2')};
- TL {index9,2}= EEG.epoch(index9).eventRandom{strcmp(EEG.epoch(index9).eventtype, 'Trigger 2')};
- TL {index9,3}= EEG.epoch(index9).eventRun{strcmp(EEG.epoch(index9).eventtype, 'Trigger 2')};
- TL {index9,4}= EEG.epoch(index9).eventActive_Passive{strcmp(EEG.epoch(index9).eventtype, 'Trigger 2')};
- TL {index9,5}= EEG.epoch(index9).eventProblem_code{strcmp(EEG.epoch(index9).eventtype, 'Trigger 2')};
- TL {index9,6}= EEG.epoch(index9).eventmin_number_of_moves{strcmp(EEG.epoch(index9).eventtype, 'Trigger 2')};
- TL {index9,7}= EEG.epoch(index9).eventFactor1{strcmp(EEG.epoch(index9).eventtype, 'Trigger 2')};
- TL {index9,8}= EEG.epoch(index9).eventFactor2{strcmp(EEG.epoch(index9).eventtype, 'Trigger 2')};
- TL {index9,9}= EEG.epoch(index9).eventFactor3{strcmp(EEG.epoch(index9).eventtype, 'Trigger 2')};
- TL {index9,10}= EEG.epoch(index9).eventCounter{strcmp(EEG.epoch(index9).eventtype, 'Trigger 2')};
- TL {index9,11}= EEG.epoch(index9).eventEventName{strcmp(EEG.epoch(index9).eventtype, 'Trigger 2')};
- TL {index9,12}= EEG.epoch(index9).eventOnset{strcmp(EEG.epoch(index9).eventtype, 'Trigger 2')};
- TL {index9,13}= EEG.epoch(index9).eventDuration{strcmp(EEG.epoch(index9).eventtype, 'Trigger 2')};
- TL {index9,14}= EEG.epoch(index9).eventWrong_Choice{strcmp(EEG.epoch(index9).eventtype, 'Trigger 2')};
- TL {index9,15}= EEG.epoch(index9).eventWrong_Release{strcmp(EEG.epoch(index9).eventtype, 'Trigger 2')};
- end
- % for index8 = 1:size(TL,1)
- % filter_event_3(index8)= TL{index8,17}=='2'; %create filter that selects only rows with event = 2 (Action Choice)
- % end
- for label_number = 1:20
- if label_number==1
- avg_labels={['avg_Amplitude_bin' num2str(label_number)]};
- sd_labels={['sd_Amplitude_bin' num2str(label_number)]};
- end
- avg_labels{label_number}= ['avg_Amplitude_bin' num2str(label_number)];
- sd_labels{label_number}= ['sd_Amplitude_bin' num2str(label_number)];
- end
- avg_labels{21}= 'avg_Amplitude_SLOPE';
- sd_labels{21}= 'sd_Amplitude_SLOPE';
- %TL_f = TL(filter_event_3,:); %filtered trial info
- OUT = cat(2, TL, num2cell(ch_average50), num2cell(ch_average100), num2cell(ch_average500), num2cell(ch_average1000),num2cell(ch_std50),num2cell(ch_std100),num2cell(ch_std500),num2cell(ch_std1000), num2cell(avg_mtx), num2cell(sd_mtx), num2cell(ALL)); %
- t_OUT= cell2table(OUT);%convert into table
- t_OUT.Properties.VariableNames = cat(2, behnames, {'Average50', 'Average100', 'Average500', 'Average1000','SD50' , 'SD100', 'SD500', 'SD1000'}, avg_labels, sd_labels, {'SlopeAllSamples'} );%
- writetable(t_OUT,strcat('ToL_Proccessed_S', num2str(sub), '.xlsx')); %write output
- clear TL;
- clear TL_f;
- clear OUT;
- clear t_OUT;
- clear index8;
- clear index9;
- clear average1;
- clear average2;
- clear average3;
- clear average4;
- clear ch_average500;
- clear ch_average1000;
- clear ch_std500;
- clear ch_std1000;
- clear ch_std;
- clear filter_event_3;
- end
Preprocessing.m, no license · at the source
Overview
- University College London, London WC1 3AZ, United Kingdom
- Birkbeck, University of London, London WC1E 7HX, United Kingdom
Abstract
Complex problems often allow multiple paths to a solution. Choosing and taking the best path is an important part of the executive cognition that underpins intelligent problem-solving behavior. However, once a path is chosen, the motor system must be activated for executing it. This interface between problem-solving and self-generated action has rarely been studied. We recorded EEG movement-related potentials while 25 participants (7 males, 18 females) performed the “Tower of London” problem-solving task. In a control condition, participants merely followed instructed steps without planning for any goal and thus without any sense that their movements solved a problem. Readiness potentials (RPs) preceding actions showed a more sustained preparatory negativity for self-generated than stimulus-driven movements. Critically, this effect was most pronounced at the first move of a sequence and diminished at later stages, indicating that preparatory activity is closely linked to the planning demands of sequence initiation. Consistent with this, contralateral motor β-band suppression was stronger for self-generated actions, particularly at sequence onset, but remained present across all moves, indicating that it is not selectively modulated by sequence position in the same way as the RP. Multivariate pattern analysis further showed that self-generated and stimulus-driven actions could be reliably distinguished throughout the entire preparatory period. Taken together, these results show a deep interaction between executive function and self-generated actions and draw attention to the fact that, if a problem can be solved, then actually solving it generally requires executive cognition to trigger self-generated actions, based on a plan.
Reproduced under the paper's license (CC BY), from the paper cited above.
Repository
Its files are read in the Code ↔ Paper reader above, with 2 matches between paragraphs and lines of code.
OSF c9yek
Availability: 1 check, the latest on 28 September 2026: the link answers (HTTP 200)
- 28 September 2026: the link answers (HTTP 200)
10 files
- 01Scripts.zip/
01Scripts/ , MATLAB, 171 lines01run_MVPA_ALL channels.m - 01Scripts.zip/
01Scripts/ , MATLAB, 66 lines02run_stats_MVPA.m - 01Scripts.zip/
01Scripts/ , MATLAB, 79 lines03run_stats_cluster_MVPA .m - 01Scripts.zip/
01Scripts/ , MATLAB, 163 lines1Topo.m - 01Scripts.zip/
01Scripts/ , MATLAB, 591 lines2Topo.m - 01Scripts.zip/
01Scripts/ , MATLAB, 195 linesPermutation_RL.m - 01Scripts.zip/
01Scripts/ , MATLAB, 178 linesPermutation_TS.m - 01Scripts.zip/
01Scripts/ , MATLAB, 718 lines, 1 matchPreprocessing.m - 01Scripts.zip/
01Scripts/ , MATLAB, 226 linesTimeFrequency_ALLsubjs.m - 01Scripts.zip/
01Scripts/ , R, 292 lines, 1 matchToL_EEG_BEH_analyses.R
Tracing map
Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.
What the map holds:
- 1 repository of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
- 10 scripts, each with its path and the digest of its content;
- 2 matches between paragraphs of the paper and lines of the code (method lexical-v1);
- neither the text of the paper nor the code itself.
Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.
Data
No dataset and no data link were found in the paper.
Versions
The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.
Version 1, 28 September 2026: the first record
Recorded: type, language, journal, volume, issue, pages, dates, 2 authors, 5 keywords, 12 MeSH terms, 2 funders, 51 references.
Cite
This paper
Seghezzi, S., & Haggard, P. (2026). Neural Mechanisms of Self-Generated Action Sequences. eNeuro, 13(5), ENEURO.0316-25.2026. https://
BibTeX
@article{seghezzi2026neu
author = {Seghezzi, Silvia and Haggard, Patrick},
title = {{Neural Mechanisms of Self-Generated Action Sequences}},
journal = {eNeuro},
year = {2026},
month = may,
volume = {13},
number = {5},
pages = {ENEURO.0316--25.2026},
publisher = {Society for Neuroscience},
issn = {2373-2822},
doi = {10.1523/
url = {https://
pmid = {42120201},
pmcid = {PMC13197169}
}
RIS
TY - JOUR
AU - Seghezzi, Silvia
AU - Haggard, Patrick
TI - Neural Mechanisms of Self-Generated Action Sequences
T2 - eNeuro
J2 - eNeuro
PY - 2026
DA - 2026/
VL - 13
IS - 5
SP - ENEURO.0316
EP - 25.2026
SN - 2373-2822
PB - Society for Neuroscience
DO - 10.1523/
UR - https://
LA - en
ER -
CSL-JSON
{
"id": "10.1523/
"type": "article-journal",
"title": "Neural Mechanisms of Self-Generated Action Sequences",
"container-title": "eNeuro",
"author": [
{
"family": "Seghezzi",
"given": "Silvia"
},
{
"family": "Haggard",
"given": "Patrick"
}
],
"container-title-short":
"volume": "13",
"issue": "5",
"page": "ENEURO.0316-25.2026",
"DOI": "10.1523/
"PMID": "42120201",
"PMCID": "PMC13197169",
"ISSN": "2373-2822",
"publisher": "Society for Neuroscience",
"URL": "https://
"language": "en",
"issued": {
"date-parts": [
[
2026,
5,
22
]
]
}
}
The tracing map gets a citation of its own once an author has validated it and it has a DOI.
Similar papers
The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.
- [1] doi:10.1093/cercor/bhag108 [code]
- Action fluency and conscious intention: being aware of what we are about to do.Journal: Cerebral cortex (New York, N.Y. : 1991)In common: EEG, cognitive, 10 references, 2 authors
- [2] doi:10.1371/journal.pone.0353990 [code]
- Positive mood enhances accessibility of unrelated concepts in the first language but not in the foreign language.Journal: PloS oneIn common: ERPLAB, EEGLAB, emmeans, 5 other tools, EEG, cognitive, 1 reference
- [3] doi:10.1162/opmi.a.372 [code]
- Broadening the Agent Preference Hypothesis Through Experiencers: Eye-Tracking and EEG Evidence of Proto-Agents and Proto-Patients.Journal: Open mind : discoveries in cognitive scienceIn common: ERPLAB, brms, EEGLAB, 4 other tools, EEG, 2 references
- [4] doi:10.1523/eneuro.0076-26.2026 [code]
- Exogenously Driven Neural Reactivation of Spatially Matching Visual Working-Memory Contents.Journal: eNeuroIn common: brms, FieldTrip, emmeans, 5 other tools, EEG, cognitive, 1 reference
- [5] doi:10.1371/journal.pbio.3003979 [code]
- Impaired midfrontal‑motor theta phase synchronization characterizes maladaptive motivational behavior in people with obsessive‑compulsive disorder.Journal: PLoS biologyIn common: EEGLAB, FieldTrip, emmeans, 5 other tools, EEG, 2 references
- [6] doi:10.1038/s41467-026-75799-8 [code]
- Behaviourally driven closed-loop beta-tACS enhances beta activity and motor behaviour.Journal: Nature communicationsIn common: EEGLAB, FieldTrip, emmeans, 5 other tools, 2 references
- [7] doi:10.7554/elife.107088 [code]
- Development of auditory and spontaneous movement responses to music over the first postnatal year.Journal: eLifeIn common: EEGLAB, FieldTrip, emmeans, 5 other tools, EEG, 2 references
- [8] doi:10.1007/s00221-026-07304-y
- Anxiety disorders alter cognitive-motor integration during visuomotor adaptation and retention.Journal: Experimental brain researchIn common: EEG, cognitive, 8 references
- [9] doi:10.1016/j.neuroimage.2026.122115 [code]
- Midfrontal theta power relates to response speeding following frustrative nonreward.Journal: NeuroImageIn common: EEGLAB, emmeans, lmerTest, 5 other tools, EEG, cognitive, 1 reference
- [10] doi:10.1111/psyp.70280 [code]
- Spatial Distance and Temporal Attentional Focus Modulate Voluntary Action Preparation and Awareness.Journal: PsychophysiologyIn common: EEG, cognitive, 7 references
Contribute
The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.
Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.
Claim this paper
Correct its record
Say what each link of this record is, remove the ones that are not the paper's, add the ones that are missing. The correction becomes a new version of the record, in its Versions section.
Validate its tracing map
You validate the map as this page shows it: 1 repository of the authors' code, each at its verified commit and with its license, 10 scripts, and 2 matches between paragraphs and code (see the Code and Map sections). It then receives a DOI on Zenodo, with you (your ORCID iD) and OSCR as its creators; the code itself is not deposited.
The map's fingerprint: sha256:6b911985cef3bac6…
Add the badge to its README
The badge links the code to this page. Copy one of these into the README of the paper's code: only you decide where it goes, and nothing is changed for you.
Markdown
[.
Discussion, reproductions, activity
Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.
Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.
Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.
