OSCR

Neural Mechanisms of Self-Generated Action Sequences.

Code ↔ Paper

2 matches between paragraphs of the paper and lines of its authors' code, computed by the harvester (lexical-v1). Click a colored paragraph or line to see its counterpart.

The 2 matches
  1. [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. [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

  1. %% EEGlab preprocessing sample script
  2. % UCL, ICN - London
  3. clc
  4. clear
  5. %% Set experimental analysis parameters
  6. % If you are working with your own data, please change this code to match
  7. % your datafiles.
  8. exp.name = 'S3'
  9. % Change to your computer's directories
  10. exp.behpath = ['/Volumes/T7/02UCL/07EEGVolition&ProblemSolving/'];
  11. exp.database = ['/Volumes/T7/02UCL/07EEGVolition&ProblemSolving/00EEG/01ConvertedData']
  12. exp.filepath = ['/Volumes/T7/02UCL/07EEGVolition&ProblemSolving/00EEG/02Preprocessing'];
  13. exp.sub_id = [1];
  14. exp.nsub = length(exp.sub_id);
  15. exp.sr = 200; % sampling rate after downsampling
  16. exp.Chans = [1:3,7,17];
  17. exp.ChanLabels = {'Fz,FCz,Cz,FC1,FC2'};
  18. exp.filter.lowerbound = 0; % high pass
  19. exp.filter.upperbound = 30; % low pass
  20. exp.downsampling_rate = 200; % downsampling rate
  21. exp.Epoch = [-1 0.5]; %s
  22. exp.Baseline = [-5 5]; %ms
  23. exp.artefact = 120
  24. % Indices of channels to include in the ICA.
  25. % Include only one of the VEOG (27), and one of the HEOG (29).
  26. exp.icachanind = [1:27,29]
  27. %% Pre-ICA pipeline, preprocessing
  28. for sub = exp.sub_id(1:end)
  29. % Load file
  30. EEG = pop_loadset([exp.database '/' 'P' num2str(sub) '.set']);
  31. EEG.setname=['P' num2str(sub)];
  32. EEG = pop_chanedit(EEG, 'lookup','/Applications/eeglab2021.0/functions/supportfiles/Standard-10-5-Cap385_witheog.elp');
  33. EEG = eeg_checkset( EEG );
  34. clear_boundary=true;
  35. % Clean triggers
  36. % This is usually not a required step - but we have been having issues
  37. % with the NIDaq box, resulting in extra, non-task related triggers
  38. % being recorded. This function cleans them.
  39. %EEG = O1_cleanTriggers(sub,exp); % remove extra triggers
  40. %O1_checkTriggerNumbers(sub,exp)
  41. % Clean triggers
  42. all_latencies= [EEG.event.latency]';
  43. for index= 1: size(all_latencies,1)
  44. if index < size(all_latencies,1)&& index >1
  45. if all_latencies(index)~= all_latencies(index+1) && all_latencies(index)~= all_latencies(index-1)
  46. wrong_trigger_filter(index)= 1;
  47. else
  48. wrong_trigger_filter(index)= 0;
  49. wrong_trigger_filter(index+1)= 0;
  50. end
  51. elseif index < size(all_latencies,1)&& index ==1
  52. if all_latencies(index)~= all_latencies(index+1)
  53. wrong_trigger_filter(index)= 1;
  54. else
  55. wrong_trigger_filter(index)= 0;
  56. wrong_trigger_filter(index+1)= 0;
  57. end
  58. else
  59. if all_latencies(index)~= all_latencies(index-1)
  60. wrong_trigger_filter(index)= 1;
  61. else
  62. wrong_trigger_filter(index)= 0;
  63. end
  64. end
  65. end
  66. all_latencies(:,2)= wrong_trigger_filter;
  67. EEG.event = EEG.event(wrong_trigger_filter==1);
  68. % Add metadata
  69. clear BEHAVIORAL;
  70. clear b1;
  71. clear b2;
  72. clear b3;
  73. clear b4;
  74. clear b5;
  75. clear b6;
  76. clear p1;
  77. clear p2;
  78. clear p3;
  79. clear p4;
  80. clear p5;
  81. clear p6;
  82. p1= ['00Behavioural/P' num2str(sub),'/ToL_fMRI_LOG_P', num2str(sub),'_Random',num2str(sub), 'Run1.xls'];
  83. p2= ['00Behavioural/P' num2str(sub),'/ToL_fMRI_LOG_P', num2str(sub),'_Random',num2str(sub), 'Run2.xls'];
  84. p3= ['00Behavioural/P' num2str(sub),'/ToL_fMRI_LOG_P', num2str(sub),'_Random',num2str(sub), 'Run3.xls'];
  85. p4= ['00Behavioural/P' num2str(sub),'/ToL_fMRI_LOG_P', num2str(sub),'_Random',num2str(sub), 'Run4.xls'];
  86. p5= ['00Behavioural/P' num2str(sub),'/ToL_fMRI_LOG_P', num2str(sub),'_Random',num2str(sub), 'Run5.xls'];
  87. p6= ['00Behavioural/P' num2str(sub),'/ToL_fMRI_LOG_P', num2str(sub),'_Random',num2str(sub), 'Run6.xls'];
  88. %initialize BEHAVIORAL file
  89. [~,~,b1] = xlsread(p1);
  90. behnames= b1(1,:);
  91. b1= b1(2:size(b1,1), :); %eliminate first row
  92. b1= b1(1:(size(b1,1)-1), :); %eliminate last row
  93. for IND= 1:size(b1,1) %look for jitters
  94. JF(IND)= (strcmp(b1{IND,11}, 'Choice_Jitter')|strcmp(b1{IND,11}, 'Release_Jitter'))==false;
  95. end
  96. b1=b1(JF,:);
  97. BEHAVIORAL= b1;
  98. clear JF;
  99. if exist(p2)==2
  100. [~,~,b2] = xlsread(p2);
  101. b2= b2(2:size(b2,1), :); %eliminate first row
  102. b2= b2(1:(size(b2,1)-1), :); %eliminate last row
  103. for IND= 1:size(b2,1) %look for jitters
  104. JF(IND)= (strcmp(b2{IND,11}, 'Choice_Jitter')|strcmp(b2{IND,11}, 'Release_Jitter'))==false;
  105. end
  106. b2=b2(JF,:);
  107. BEHAVIORAL= [BEHAVIORAL; b2];
  108. end
  109. clear JF;
  110. if exist(p3)==2
  111. [~,~,b3] = xlsread(p3);
  112. b3= b3(2:size(b3,1), :); %eliminate first row
  113. b3= b3(1:(size(b3,1)-1), :); %eliminate last row
  114. for IND= 1:size(b3,1) %look for jitters
  115. JF(IND)= (strcmp(b3{IND,11}, 'Choice_Jitter')|strcmp(b3{IND,11}, 'Release_Jitter'))==false;
  116. end
  117. b3=b3(JF,:);
  118. BEHAVIORAL= [BEHAVIORAL; b3];
  119. end
  120. clear JF;
  121. if exist(p4)==2
  122. [~,~,b4] = xlsread(p4);
  123. b4= b4(2:size(b4,1), :); %eliminate first row
  124. b4= b4(1:(size(b4,1)-1), :); %eliminate last row
  125. for IND= 1:size(b4,1) %look for jitters
  126. JF(IND)= (strcmp(b4{IND,11}, 'Choice_Jitter')|strcmp(b4{IND,11}, 'Release_Jitter'))==false;
  127. end
  128. b4=b4(JF,:);
  129. BEHAVIORAL= [BEHAVIORAL; b4];
  130. end
  131. clear JF;
  132. if exist(p5)==2
  133. [~,~,b5] = xlsread(p5);
  134. b5= b5(2:size(b5,1), :); %eliminate first row
  135. b5= b5(1:(size(b5,1)-1), :); %eliminate last row
  136. for IND= 1:size(b5,1) %look for jitters
  137. JF(IND)= (strcmp(b5{IND,11}, 'Choice_Jitter')|strcmp(b5{IND,11}, 'Release_Jitter'))==false;
  138. end
  139. b5=b5(JF,:);
  140. BEHAVIORAL= [BEHAVIORAL; b5];
  141. end
  142. clear JF;
  143. if exist(p6)==2
  144. [~,~,b6] = xlsread(p6);
  145. b6= b6(2:size(b6,1), :); %eliminate first row
  146. b6= b6(1:(size(b6,1)-1), :); %eliminate last row
  147. for IND= 1:size(b6,1) %look for jitters
  148. JF(IND)= (strcmp(b6{IND,11}, 'Choice_Jitter')|strcmp(b6{IND,11}, 'Release_Jitter'))==false;
  149. end
  150. b6=b6(JF,:);
  151. BEHAVIORAL= [BEHAVIORAL; b6];
  152. end
  153. %get rid of trigger 7
  154. for index6 =1:size(EEG.event,2)
  155. Filt(index6)= strcmp(EEG.event(index6).type, 'Trigger 7');
  156. end
  157. EEG.event=EEG.event(Filt==0);
  158. clear index6
  159. clear Filt
  160. %get rid of boundary
  161. if clear_boundary==true
  162. for index6 =1:size(EEG.event,2)
  163. Filt(index6)= strcmp(EEG.event(index6).type, 'boundary');
  164. end
  165. EEG.event=EEG.event(Filt==0);
  166. end
  167. counter=1; %use this to index the BEHAVIORAL file
  168. for index7 =1:size(EEG.event,2)
  169. if strcmp(EEG.event(index7).type, 'Trigger 7')
  170. else
  171. EEG.event(index7).ID= num2str(BEHAVIORAL{counter,1});
  172. EEG.event(index7).Random= num2str(BEHAVIORAL{counter,2});
  173. EEG.event(index7).Run= num2str(BEHAVIORAL{counter,3});
  174. EEG.event(index7).Active_Passive= num2str(BEHAVIORAL{counter,4});
  175. EEG.event(index7).Problem_code= num2str(BEHAVIORAL{counter,5});
  176. EEG.event(index7).min_number_of_moves= num2str(BEHAVIORAL{counter,6});
  177. EEG.event(index7).Factor1= num2str(BEHAVIORAL{counter,7});
  178. EEG.event(index7).Factor2= num2str(BEHAVIORAL{counter,8});
  179. EEG.event(index7).Factor3= num2str(BEHAVIORAL{counter,9});
  180. EEG.event(index7).Counter= num2str(BEHAVIORAL{counter,10});
  181. EEG.event(index7).EventName= num2str(BEHAVIORAL{counter,11});
  182. EEG.event(index7).Onset= num2str(BEHAVIORAL{counter,12});
  183. EEG.event(index7).Duration= num2str(BEHAVIORAL{counter,13});
  184. EEG.event(index7).Wrong_Choice= num2str(BEHAVIORAL{counter,14});
  185. EEG.event(index7).Wrong_Release= num2str(BEHAVIORAL{counter,15});
  186. counter= counter+1;
  187. end
  188. end
  189. end
  190. %%
  191. for sub = exp.sub_id(1:end)
  192. %% Re-reference to average of mastoids
  193. % There are many ways to re-reference EEG data. T
  194. EEG = pop_reref( EEG, [27 28] ); % re-reference to average of mastoids *channels
  195. EEG = eeg_checkset( EEG );
  196. filename = ['r' exp.name '_P' num2str(sub)];
  197. EEG = pop_saveset( EEG, filename, exp.filepath);
  198. % Identify bad channels based on kurtosis
  199. % Note - there are other methods.
  200. % Take this only as a hint - always check
  201. % visually!
  202. [iEEG,indelec] = pop_rejchan(EEG,'elec',[1:30],'threshold',5,'norm','on','measure','kurt');
  203. EEG.badChan = indelec;
  204. % Interpolate bad channels
  205. % EEG = eeg_interp(EEG,indelec);
  206. %% Filter
  207. % This is an important step. The parameters chosen vary depending on
  208. % which kind of analyses need to be run. In our case, we will use a
  209. % relatively low high-pass filter because we may want to look at the
  210. % RP, and a low low-pass filter as well, because we are not interested
  211. % in high-frequency EEG activity. To decide which parameters to use,
  212. % check previous papers analysing your signal of interest and follow
  213. % their guidelines.
  214. EEG = pop_basicfilter(EEG, 1:30 , 'Boundary', 'boundary', 'Cutoff', [exp.filter.lowerbound exp.filter.upperbound], 'Design', 'butter', 'Filter', 'bandpass', 'order',8);
  215. EEG = eeg_checkset( EEG );
  216. filename = ['fr' exp.name '_P' num2str(sub)];
  217. EEG = pop_saveset( EEG, filename, exp.filepath);
  218. % Let's see what the filtered data look like...
  219. EEG1 = pop_loadset([exp.filepath '/r' exp.name '_P' num2str(sub) '.set']);
  220. EEG2 = eeg_checkset( EEG );
  221. eegplot([EEG1.data], 'data2', [EEG2.data], 'color','off')
  222. %% Downsample
  223. % This is not strictly necessary, especially if the recording sampling
  224. % rate is already low as in our case (256Hz). I include it for
  225. % completion purposes.
  226. EEG = eeg_checkset( EEG );
  227. EEG = pop_resample( EEG, exp.downsampling_rate);
  228. EEG = eeg_checkset( EEG );
  229. filename = ['df8r' exp.name '_P' num2str(sub)];
  230. EEG = pop_saveset( EEG, filename, exp.filepath);
  231. %% Epoch around events of interest (e.g. Trigger 2)
  232. % In your experiment, you may have different types of events that you want to look at,
  233. % requiring different epoching parameters. In that case, you would need
  234. % to specify the various Triggers of interest and their respective
  235. % epoching times.
  236. EEG = pop_loadset([exp.filepath '/' 'df8r' exp.name '_P' num2str(sub) '.set']);
  237. EEG = pop_epoch( EEG, {'Trigger 2'}, exp.Epoch, 'epochinfo', 'yes');
  238. EEG = eeg_checkset( EEG );
  239. EEG = pop_saveset( EEG, ['e_df8r' exp.name '_P' num2str(sub)], exp.filepath);
  240. %% Baseline correct
  241. % Baselining takes the baseline epoch and moves the whole epoch "up" or
  242. % "down" so that the average baseline signal is 0. This allows
  243. % comparing multiple epochs.
  244. EEG = pop_loadset([exp.filepath '/' '/e_df8r' exp.name '_P' num2str(sub) '.set']);
  245. EEG = pop_rmbase( EEG, exp.Baseline);
  246. EEG = pop_saveset( EEG, ['be_df8r' exp.name '_P' num2str(sub)], exp.filepath);
  247. %% Let's see what the baselined data look like...
  248. EEG1 = pop_loadset([exp.filepath '/' '/e_df8r' exp.name '_P' num2str(sub) '.set']);
  249. EEG2 = eeg_checkset( EEG );
  250. eegplot([EEG1.data], 'data2', [EEG2.data], 'color','off')
  251. %% Run ICA & plot component maps
  252. % We use the Independent Component Analysis to identify eye movements
  253. % and remove them from the signal.
  254. % ICA can also be used to identify physiological / cognitive components
  255. % of interest, and use them for analysis instead of using raw channel
  256. % data. We will not do this here, but it is an approach worth
  257. % investigating.
  258. EEG = eeg_checkset( EEG ); % set right channel names before ICA
  259. EEG = pop_runica(EEG, 'extended',0,'interupt','on', 'chanind', exp.icachanind);
  260. EEG = pop_chanedit(EEG, 'lookup','/Applications/eeglab2021.0/functions/supportfiles/Standard-10-5-Cap385_witheog.elp');
  261. EEG = eeg_checkset( EEG );
  262. EEG = pop_saveset( EEG, ['ICAbe_df8r' exp.name '_P' num2str(sub)], exp.filepath);
  263. % Plot ICA result
  264. pop_topoplot(EEG,0, [1:28] ,'O1_P0 resampled epochs',[5 6] ,0,'electrodes','on');
  265. % % If you want to use the EEGlab GUI:
  266. % % Start the GUI by typing eeglab
  267. % % Plot -> component maps -> 2D
  268. % % Tools -> remove components from data -> type component to remove ... -> plot single trials ->
  269. % % acccept -> save
  270. % In this example dataset, components 1 and 2 are clearly eye movement
  271. % components. Component 1 corresponds to eye blinks, and component 4 to
  272. % horizontal eye movements. Let's see what happens when we remove them.
  273. % Go to the GUI and run
  274. % Tools -> remove components from data -> type "1 2" in component to remove ... -> plot single trials ->
  275. % In this dataset, Channel 27 corresponds to VEOG, and 28 to HEOG. You
  276. % can look this up in the EEG.chanlocs field.
  277. % Red lines are after correction, blue lines before correction.
  278. % Notice how in epochs containing eyeblinks (e.g. epoch 6) channel 27 (VEOG) is completely flat after
  279. % correction. Notice how EEG channels with eyeblink artefacts are also
  280. % fully corrected.
  281. % Similarly, in epochs containin horizontal eye movements (e.g. epoch
  282. % 62) channel 28 (HEOG) is completely flat after correction. EEG
  283. % channels should be corrected too.
  284. % Once you've checked that the components you identified as eye
  285. % movements are correct, you can accept removing them and save the new
  286. % dataset.
  287. end
  288. %% Post-ICA correction pipeline
  289. for sub = exp.sub_id(1:end)
  290. %% Artefact rejection
  291. % This is one additional artefact rejection step to ensure that no
  292. % epochs contain excessive fluctuations. We use a thresholding
  293. % procedure, and reject any epochs with voltages spanning +/- 120uV
  294. % from baseline. This value is reasonable, but arbitrary - many papers
  295. % use a 80uV threshold, but given that we use a very low high pass
  296. % filter, our epochs contain a greater degree of drift. Thus, we allow
  297. % for wider fluctuations.
  298. % Note: there are many other approaches to artefact rejection - you may
  299. % wish to pick your own.
  300. EEG = pop_loadset([exp.filepath '/' 'cICAbe_df8r' exp.name '_P' num2str(sub) '.set']);
  301. [EEG, iart] = pop_eegthresh(EEG,1,exp.Chans ,-120,120, -2.5,0.995,0,1);
  302. EEG.iart = iart; % We need to save the artefact indices so we can remove them from the behavioural data too.
  303. EEG = pop_saveset( EEG, ['acICAbe_df8r' exp.name '_P' num2str(sub)], exp.filepath);
  304. end
  305. %% Plot
  306. for sub = exp.sub_id(1:end)i = 0
  307. figure
  308. for sub = exp.sub_id(1:end)
  309. EEG = pop_loadset(['/Volumes/T7/02UCL/07EEGVolition&ProblemSolving/00EEG/02Preprocessing/acICAbe_df8rS3_P' num2str(sub) '.set']);
  310. i = i+1
  311. %subplot(7,4,i)
  312. plot(mean(EEG.data(exp.Chans,:,:),3)') % Plot channel of interest
  313. xline(201)
  314. end
  315. end
  316. %% Extract figure data
  317. for sub = exp.sub_id(1:end)
  318. EEG = pop_loadset(['/Volumes/S/02UCL/07EEGVolition&ProblemSolving/00EEG/02Preprocessing/acICAbe_df8rS3_P' num2str(sub) '.set']);
  319. %check how many epochs contain more than one event of interest
  320. for indx= 1: size(EEG.epoch,2)
  321. EOI(indx)=sum(strcmp(EEG.epoch(indx).eventtype, 'Trigger 2'));
  322. EOI_f(indx)=sum(strcmp(EEG.epoch(indx).eventtype, 'Trigger 2'))==1;
  323. end
  324. clear indx
  325. %keep only channels we need
  326. eeg=EEG.data(exp.Chans,:,:);
  327. %initialize filters
  328. active_2_1_f=zeros(1,size(EEG.epoch,2));
  329. active_2_other_f=zeros(1,size(EEG.epoch,2));
  330. active_4_1_f=zeros(1,size(EEG.epoch,2));
  331. active_4_other_f=zeros(1,size(EEG.epoch,2));
  332. passive_2_1_f=zeros(1,size(EEG.epoch,2));
  333. passive_2_other_f=zeros(1,size(EEG.epoch,2));
  334. passive_4_1_f=zeros(1,size(EEG.epoch,2));
  335. passive_4_other_f=zeros(1,size(EEG.epoch,2));
  336. %we need four datasets: (1) active; (2) passive; (3) 1 active; (4) no1 active
  337. for indx= 1: size(EEG.epoch,2)
  338. if EOI(indx)==1 && EOI_f(indx)==1 && strcmp(EEG.epoch(indx).eventActive_Passive(strcmp(EEG.epoch(indx).eventtype, 'Trigger 2')), 'active'); %create active
  339. if strcmp(EEG.epoch(indx).eventCounter(strcmp(EEG.epoch(indx).eventtype, 'Trigger 2')), '1')
  340. if strcmp(EEG.epoch(indx).eventmin_number_of_moves(strcmp(EEG.epoch(indx).eventtype, 'Trigger 2')), '2')
  341. active_2_1_f(indx)=1;
  342. elseif strcmp(EEG.epoch(indx).eventmin_number_of_moves(strcmp(EEG.epoch(indx).eventtype, 'Trigger 2')), '4')
  343. active_4_1_f(indx)=1;
  344. end
  345. else
  346. if strcmp(EEG.epoch(indx).eventmin_number_of_moves(strcmp(EEG.epoch(indx).eventtype, 'Trigger 2')), '2')
  347. active_2_other_f(indx)=1;
  348. elseif strcmp(EEG.epoch(indx).eventmin_number_of_moves(strcmp(EEG.epoch(indx).eventtype, 'Trigger 2')), '4')
  349. active_4_other_f(indx)=1;
  350. end
  351. end
  352. elseif EOI(indx)==1 && EOI_f(indx)==1 && strcmp(EEG.epoch(indx).eventActive_Passive(strcmp(EEG.epoch(indx).eventtype, 'Trigger 2')), 'passive'); %create passive
  353. if strcmp(EEG.epoch(indx).eventCounter(strcmp(EEG.epoch(indx).eventtype, 'Trigger 2')), '1')
  354. if strcmp(EEG.epoch(indx).eventmin_number_of_moves(strcmp(EEG.epoch(indx).eventtype, 'Trigger 2')), '2')
  355. passive_2_1_f(indx)=1;
  356. elseif strcmp(EEG.epoch(indx).eventmin_number_of_moves(strcmp(EEG.epoch(indx).eventtype, 'Trigger 2')), '4')
  357. passive_4_1_f(indx)=1;
  358. end
  359. else
  360. if strcmp(EEG.epoch(indx).eventmin_number_of_moves(strcmp(EEG.epoch(indx).eventtype, 'Trigger 2')), '2')
  361. passive_2_other_f(indx)=1;
  362. elseif strcmp(EEG.epoch(indx).eventmin_number_of_moves(strcmp(EEG.epoch(indx).eventtype, 'Trigger 2')), '4')
  363. passive_4_other_f(indx)=1;
  364. end
  365. end
  366. end
  367. end
  368. ACTIVE_2_1=eeg(:,:,active_2_1_f==1);
  369. ACTIVE_2_1=mean(ACTIVE_2_1,1);
  370. ACTIVE_2_1=mean(ACTIVE_2_1,3);
  371. ACTIVE_2_1=squeeze(ACTIVE_2_1);
  372. ACTIVE_4_1=eeg(:,:,active_4_1_f==1);
  373. ACTIVE_4_1=mean(ACTIVE_4_1,1);
  374. ACTIVE_4_1=mean(ACTIVE_4_1,3);
  375. ACTIVE_4_1=squeeze(ACTIVE_4_1);
  376. ACTIVE_2_other=eeg(:,:,active_2_other_f==1);
  377. ACTIVE_2_other=mean(ACTIVE_2_other,1);
  378. ACTIVE_2_other=mean(ACTIVE_2_other,3);
  379. ACTIVE_2_other=squeeze(ACTIVE_2_other);
  380. ACTIVE_4_other=eeg(:,:,active_4_other_f==1);
  381. ACTIVE_4_other=mean(ACTIVE_4_other,1);
  382. ACTIVE_4_other=mean(ACTIVE_4_other,3);
  383. ACTIVE_4_other=squeeze(ACTIVE_4_other);
  384. PASSIVE_2_1=eeg(:,:,passive_2_1_f==1);
  385. PASSIVE_2_1=mean(PASSIVE_2_1,1);
  386. PASSIVE_2_1=mean(PASSIVE_2_1,3);
  387. PASSIVE_2_1=squeeze(PASSIVE_2_1);
  388. PASSIVE_4_1=eeg(:,:,passive_4_1_f==1);
  389. PASSIVE_4_1=mean(PASSIVE_4_1,1);
  390. PASSIVE_4_1=mean(PASSIVE_4_1,3);
  391. PASSIVE_4_1=squeeze(PASSIVE_4_1);
  392. PASSIVE_2_other=eeg(:,:,passive_2_other_f==1);
  393. PASSIVE_2_other=mean(PASSIVE_2_other,1);
  394. PASSIVE_2_other=mean(PASSIVE_2_other,3);
  395. PASSIVE_2_other=squeeze(PASSIVE_2_other);
  396. PASSIVE_4_other=eeg(:,:,passive_4_other_f==1);
  397. PASSIVE_4_other=mean(PASSIVE_4_other,1);
  398. PASSIVE_4_other=mean(PASSIVE_4_other,3);
  399. PASSIVE_4_other=squeeze(PASSIVE_4_other);
  400. time= -1000:5:495;
  401. 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));
  402. 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));
  403. 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));
  404. 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));
  405. 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));
  406. 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));
  407. 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));
  408. 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));
  409. 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);
  410. out= cat(2, num2cell(repmat(sub, size(out,1),1)), out);
  411. T=table(out(:,1),out(:,2), out(:,3), out(:,4), out(:,5), out(:,6));
  412. T.Properties.VariableNames={'ID', 'Time', 'Amplitude', 'Condition', 'Moves','Trial'};
  413. % % % writetable(t_OUT,strcat('Proccessed_FiveChannelsAverage_S', num2str(sub), '.xlsx')); %write output
  414. writetable(T,strcat('Tol4Plot_S', num2str(sub), '.xlsx')); %write output
  415. clear TL;
  416. clear TL_f;
  417. clear OUT;
  418. clear t_OUT;
  419. clear index8;
  420. clear index9;
  421. clear average1;
  422. clear average2;
  423. clear average3;
  424. clear average4;
  425. clear ch_average500;
  426. clear ch_average1000;
  427. clear ch_std500;
  428. clear ch_std1000;
  429. clear ch_std;
  430. clear filter_event_3;
  431. end
  432. %% Extract action data
  433. for sub = exp.sub_id(1:end)
  434. EEG = pop_loadset(['/Volumes/S/02UCL/07EEGVolition&ProblemSolving/00EEG/02Preprocessing/acICAbe_df8rS3_P' num2str(sub) '.set']);
  435. %mean Amplitude 50ms%
  436. average1 = mean(EEG.data(:,191:200,:),2); %here
  437. ch_average50 = squeeze(mean(average1(exp.Chans,:,:),1)); %hered
  438. %mean Amplitude 100ms%
  439. average2 = mean(EEG.data(:,181:200,:),2); %here
  440. ch_average100 = squeeze(mean(average2(exp.Chans,:,:),1)); %hered
  441. %mean Amplitude 500ms%
  442. average3 = mean(EEG.data(:,101:200,:),2); %here
  443. ch_average500 = squeeze(mean(average3(exp.Chans,:,:),1)); %hered
  444. %mean Amplitude 1000ms%
  445. average4 = mean(EEG.data(:,1:200,:),2); %here
  446. ch_average1000 = squeeze(mean(average4(exp.Chans,:,:),1)); %hered
  447. %STD 50ms%
  448. average5 = mean(EEG.data(exp.Chans,191:200,:),1); %here
  449. ch_std50 = squeeze(std(average5(:,:,:),0,2)); %hered
  450. %STD 100ms%
  451. average6 = mean(EEG.data(exp.Chans,181:200,:),1); %here
  452. ch_std100 = squeeze(std(average6(:,:,:),0,2)); %hered
  453. %STD 500ms%
  454. average7 = mean(EEG.data(exp.Chans,101:200,:),1); %here
  455. ch_std500 = squeeze(std(average7(:,:,:),0,2)); %hered
  456. %STD 1000ms%
  457. average8 = mean(EEG.data(exp.Chans,1:200,:),1); %here
  458. ch_std1000 = squeeze(std(average8(:,:,:),0,2)); %hered
  459. % %mean and sd for 20 bins of 50 (49) ms (10 samples) each%
  460. avg_mtx= zeros(size(EEG.data,3),21) ; %initialize matrix of Average Amplitudes in 20 bins + 1 vector for slope
  461. sd_mtx= zeros(size(EEG.data,3),21) ; %initialize matrix of sd Amplitudes in 20 bins + 1 vector for slope
  462. for bin= 1:20
  463. sample_ini=1+(10*bin) -10;
  464. sample_end= 0+(10*bin);
  465. %average for each bin
  466. average_bin = mean(EEG.data(:,sample_ini:sample_end,:),2); %
  467. ch_average_bin = squeeze(mean(average_bin(exp.Chans,:,:),1)); %
  468. avg_mtx(:,bin)= ch_average_bin;
  469. clear average_bin;
  470. clear ch_average_bin;
  471. %sd for each bin
  472. sd_bin = std(EEG.data(:,sample_ini:sample_end,:),0,2); %
  473. ch_sd_bin = squeeze(mean(sd_bin(exp.Chans,:,:),1)); %
  474. sd_mtx(:,bin)= ch_sd_bin;
  475. clear average_bin;
  476. clear ch_average_bin;
  477. end
  478. %slope for 20 bins of 10 samples each
  479. for TRIAL = 1:size(avg_mtx,1)
  480. %get slope and write it in colum 21
  481. mod = fitlm([1:20],avg_mtx(TRIAL,1:size(avg_mtx,2)-1));
  482. avg_mtx(TRIAL,21)= mod.Coefficients.Estimate(2);
  483. mod_sd = fitlm([1:20],sd_mtx(TRIAL,1:size(sd_mtx,2)-1));
  484. sd_mtx(TRIAL,21)= mod_sd.Coefficients.Estimate(2);
  485. clear mod
  486. clear mod_sd
  487. end
  488. %slope for all samples
  489. for TRIAL = 1:size(avg_mtx,1)
  490. %get slope and write it in colum 21
  491. AMP=squeeze(mean(EEG.data(exp.Chans,1:200,TRIAL),1));
  492. mod_all = fitlm([1:200],AMP);
  493. ALL(TRIAL,1)= mod_all.Coefficients.Estimate(2);
  494. clear AMP
  495. clear mod_all
  496. end
  497. %get trial info
  498. % for index9= 1: size(EEG.event,2)
  499. % TL {index9,1}= EEG.event(index9).ID;
  500. % TL {index9,2}= EEG.event(index9).Random;
  501. % TL {index9,3}= EEG.event(index9).Run;
  502. % TL {index9,4}= EEG.event(index9).Active_Passive;
  503. % TL {index9,5}= EEG.event(index9).Problem_code;
  504. % TL {index9,6}= EEG.event(index9).min_number_of_moves;
  505. % TL {index9,7}= EEG.event(index9).Factor1;
  506. % TL {index9,8}= EEG.event(index9).Factor2;
  507. % TL {index9,9}= EEG.event(index9).Factor3;
  508. % TL {index9,10}= EEG.event(index9).Counter;
  509. % TL {index9,11}= EEG.event(index9).EventName;
  510. % TL {index9,12}= EEG.event(index9).Onset;
  511. % TL {index9,13}= EEG.event(index9).Duration;
  512. % TL {index9,14}= EEG.event(index9).Wrong_Choice;
  513. % TL {index9,15}= EEG.event(index9).Wrong_Release;
  514. % TL {index9,16}= EEG.event(index9).epoch;
  515. %
  516. % TL {index9,17}= EEG.event(index9).type(9); %n trigger
  517. % end
  518. for index9= 1: size(EEG.epoch,2)
  519. TL {index9,1}= EEG.epoch(index9).eventID{strcmp(EEG.epoch(index9).eventtype, 'Trigger 2')};
  520. TL {index9,2}= EEG.epoch(index9).eventRandom{strcmp(EEG.epoch(index9).eventtype, 'Trigger 2')};
  521. TL {index9,3}= EEG.epoch(index9).eventRun{strcmp(EEG.epoch(index9).eventtype, 'Trigger 2')};
  522. TL {index9,4}= EEG.epoch(index9).eventActive_Passive{strcmp(EEG.epoch(index9).eventtype, 'Trigger 2')};
  523. TL {index9,5}= EEG.epoch(index9).eventProblem_code{strcmp(EEG.epoch(index9).eventtype, 'Trigger 2')};
  524. TL {index9,6}= EEG.epoch(index9).eventmin_number_of_moves{strcmp(EEG.epoch(index9).eventtype, 'Trigger 2')};
  525. TL {index9,7}= EEG.epoch(index9).eventFactor1{strcmp(EEG.epoch(index9).eventtype, 'Trigger 2')};
  526. TL {index9,8}= EEG.epoch(index9).eventFactor2{strcmp(EEG.epoch(index9).eventtype, 'Trigger 2')};
  527. TL {index9,9}= EEG.epoch(index9).eventFactor3{strcmp(EEG.epoch(index9).eventtype, 'Trigger 2')};
  528. TL {index9,10}= EEG.epoch(index9).eventCounter{strcmp(EEG.epoch(index9).eventtype, 'Trigger 2')};
  529. TL {index9,11}= EEG.epoch(index9).eventEventName{strcmp(EEG.epoch(index9).eventtype, 'Trigger 2')};
  530. TL {index9,12}= EEG.epoch(index9).eventOnset{strcmp(EEG.epoch(index9).eventtype, 'Trigger 2')};
  531. TL {index9,13}= EEG.epoch(index9).eventDuration{strcmp(EEG.epoch(index9).eventtype, 'Trigger 2')};
  532. TL {index9,14}= EEG.epoch(index9).eventWrong_Choice{strcmp(EEG.epoch(index9).eventtype, 'Trigger 2')};
  533. TL {index9,15}= EEG.epoch(index9).eventWrong_Release{strcmp(EEG.epoch(index9).eventtype, 'Trigger 2')};
  534. end
  535. % for index8 = 1:size(TL,1)
  536. % filter_event_3(index8)= TL{index8,17}=='2'; %create filter that selects only rows with event = 2 (Action Choice)
  537. % end
  538. for label_number = 1:20
  539. if label_number==1
  540. avg_labels={['avg_Amplitude_bin' num2str(label_number)]};
  541. sd_labels={['sd_Amplitude_bin' num2str(label_number)]};
  542. end
  543. avg_labels{label_number}= ['avg_Amplitude_bin' num2str(label_number)];
  544. sd_labels{label_number}= ['sd_Amplitude_bin' num2str(label_number)];
  545. end
  546. avg_labels{21}= 'avg_Amplitude_SLOPE';
  547. sd_labels{21}= 'sd_Amplitude_SLOPE';
  548. %TL_f = TL(filter_event_3,:); %filtered trial info
  549. 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)); %
  550. t_OUT= cell2table(OUT);%convert into table
  551. t_OUT.Properties.VariableNames = cat(2, behnames, {'Average50', 'Average100', 'Average500', 'Average1000','SD50' , 'SD100', 'SD500', 'SD1000'}, avg_labels, sd_labels, {'SlopeAllSamples'} );%
  552. writetable(t_OUT,strcat('ToL_Proccessed_S', num2str(sub), '.xlsx')); %write output
  553. clear TL;
  554. clear TL_f;
  555. clear OUT;
  556. clear t_OUT;
  557. clear index8;
  558. clear index9;
  559. clear average1;
  560. clear average2;
  561. clear average3;
  562. clear average4;
  563. clear ch_average500;
  564. clear ch_average1000;
  565. clear ch_std500;
  566. clear ch_std1000;
  567. clear ch_std;
  568. clear filter_event_3;
  569. end

Preprocessing.m, no license · at the source

Overview

  1. University College London, London WC1 3AZ, United Kingdom
  2. Birkbeck, University of London, London WC1E 7HX, United Kingdom
Institutions: University College London (United Kingdom); Birkbeck, University of London (United Kingdom)
Journal: eNeuro, volume 13, issue 5, pages ENEURO.0316-25.2026
Dates: received 25 August 2025; accepted 17 April 2026; published online 22 May 2026; in print May 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.1523/eneuro.0316-25.2026 · PMID 42120201 · PMCID PMC13197169 · OpenAlex W7160927533
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: EEG (modality), human (organism), cognitive (subfield)
Methods: Spectral & time-frequency, Connectivity, Statistics, Smoothing, state filtering, decompositions, Machine learning, Preprocessing, Evoked potentials, fMRI & imaging, Physiology & signal measures
Keywords: EEG, executive functions, problem-solving, readiness potential, volition
MeSH: Brain*, Executive Function*, Motor Activity*, Problem Solving*, Psychomotor Performance*, Contingent Negative Variation, Electroencephalography, Female, Humans, Male, Neuropsychological Tests, Young Adult (* major topic)
Topic: Neural and Behavioral Psychology Studies (Cognitive Neuroscience, Neuroscience), according to OpenAlex
Funding: Fetzer Institute (4189); John Templeton Fondation (61283)
Citations: not cited yet (Europe PMC); 54 references in the paper

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

License: none: the authors keep all their rights
State: the link answers, verified on 28 September 2026
Evidence: files inventoried
Size: 2 files
Software Heritage: not checked
Found in: the text, “Behavioral data analysis”
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: Statistics and Machine Learning Toolbox (6 files), FieldTrip (5 files), EEGLAB (4 files), brms (1 file), emmeans (1 file), ERPLAB (1 file), ggplot2 (1 file), lme4 (1 file), lmerTest (1 file), reshape2 (1 file), tidyverse (1 file)
Availability: 1 check, the latest on 28 September 2026: the link answers (HTTP 200)
  • 28 September 2026: the link answers (HTTP 200)
10 files

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://doi.org/10.1523/eneuro.0316-25.2026

BibTeX

@article{seghezzi2026neural,
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/eneuro.0316-25.2026},
url = {https://doi.org/10.1523/eneuro.0316-25.2026},
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/05/22
VL - 13
IS - 5
SP - ENEURO.0316
EP - 25.2026
SN - 2373-2822
PB - Society for Neuroscience
DO - 10.1523/eneuro.0316-25.2026
UR - https://doi.org/10.1523/eneuro.0316-25.2026
LA - en
ER -

CSL-JSON

{
"id": "10.1523/eneuro.0316-25.2026",
"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": "eNeuro",
"volume": "13",
"issue": "5",
"page": "ENEURO.0316-25.2026",
"DOI": "10.1523/eneuro.0316-25.2026",
"PMID": "42120201",
"PMCID": "PMC13197169",
"ISSN": "2373-2822",
"publisher": "Society for Neuroscience",
"URL": "https://doi.org/10.1523/eneuro.0316-25.2026",
"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 one
In 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 science
In 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: eNeuro
In 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 biology
In 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 communications
In 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: eLife
In 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 research
In 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: NeuroImage
In 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: Psychophysiology
In 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.

Request its removal

To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).

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.