OSCR

Closed-loop readout of anterior insula high-gamma activity steers value-based decisions.

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] § Methods › Statistical analyses ↔ a1_behav_archoices_bci.m, lines 398–461 · score 0.67 · regression coefficients, random slopes, fitglme, linear, intercepts, predictor
  2. [2] § Methods › Statistical analyses › Behavioral effects of BCI-triggered neural states ↔ a1_behav_archoices_bci.m, lines 332–396 · score 0.54 · inter trial interval, reject, mixed, behavior, variables, aIns

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 · 837 lines · 40 KB · CC-BY-4.0 · 2 matches

  1. %% a1_behav_archoices_bci
  2. % Runs behavioural analyses for the simple choices stage.
  3. %
  4. % Input:
  5. % - analysis level: 1 for individual analyses, 2 for group analyses.
  6. % Lvl 1 must be run before lvl 2 (lvl 2 uses output saved during lvl 1).
  7. %
  8. % Output:
  9. % - none. Runs function of corresponding analysis level, which saves
  10. % its own output struct and plots to corresponding 'out' folder.
  11. %
  12. % Clarissa Baratin, April 2021 / G. Becq 20260603
  13. % parts of script adapted from Teddy Landron
  14. %% options struct
  15. options.smooth_fit = {'yes'}; % fit curve smoothing? 'yes' or 'no'
  16. options.n_eltBin = 10; %
  17. options.nBin = 7;
  18. options.prctile = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100];
  19. options.mean_med = 'mean'; % mean or median 'med'RT
  20. options.plot_optional_figI = false;
  21. options.plot_optional_figII = false;
  22. %% individual vs. multiple subjects scripts
  23. % subjects = importdata('./subjects.mat');
  24. subjects = get_subjects();
  25. [subjects, stats_Lvl1] = f_behav_archoices_lvl1_bci(options, subjects);
  26. f_behav_archoices_lvl2_bci(options, subjects, stats_Lvl1);
  27. %%
  28. % transform subjects. mat to readable csv files
  29. % change to true if you want to generate csv file from subjects.mat file.
  30. if false
  31. subids = ["sub-01", "sub-02", "sub-03", "sub-04", "sub-05", "sub-06", "sub-07", "sub-08", "sub-09", "sub-10", "sub-11", "sub-12"];
  32. colnames1 = {'stimnumber', 'type1', 'type2', 'value', 'RT', '1stRT', 'Z'};
  33. colnames3 = {'Spatial_configuration', 'Pleasant_stimulus_number', 'Unpleasant_stimulus_number', ...
  34. 'Pleasant_stimulus_value', 'Unpleasant_stimulus_value', 'Value_difference', ...
  35. 'Value_sum', 'Accept?', 'Reaction_time', 'Threshold_reached', 'Nothing', ...
  36. 'Trial_onset', 'Onset_of_confirmation_screen', 'col14'};
  37. for i = 1 : 12
  38. x1 = subjects(i).trial_characteristics1;
  39. T1 = array2table(x1, 'VariableNames', colnames1);
  40. fn1 = subids(i) + "_trialchar1.csv";
  41. writetable(T1, fn1);
  42. end
  43. rois = {'vmPFC', 'aIns'};
  44. for i = 1 : 12
  45. for iroi = 1 : 2
  46. roi = rois{iroi};
  47. if isfield(subjects(i).trial_characteristics3, roi)
  48. T3 = array2table(subjects(i).trial_characteristics3.(roi), 'VariableNames', colnames3);
  49. fn3 = subids(i) + "_trialchar3_" + roi + ".csv";
  50. writetable(T3, fn3);
  51. end
  52. end
  53. end
  54. end
  55. %%
  56. function subjects = get_subjects()
  57. subids = ["sub-01", "sub-02", "sub-03", "sub-04", "sub-05", "sub-06", "sub-07", "sub-08", "sub-09", "sub-10", "sub-11", "sub-12"];
  58. rois = {'vmPFC', 'aIns'};
  59. subjects = [];
  60. for isub = 1 : 12
  61. fn1 = subids(isub) + "_trialchar1.csv";
  62. T1 = readtable(fn1);
  63. subjects(isub).name = subids(isub);
  64. subjects(isub).trial_characteristics1 = table2array(T1);
  65. for iroi = 1 : 2
  66. roi = rois{iroi};
  67. fn3 = subids(isub) + "_trialchar3_" + roi + ".csv";
  68. disp(exist(fn3))
  69. if exist(fn3)
  70. T3 = readtable(fn3);
  71. subjects(isub).trial_characteristics3.(roi) = table2array(T3);
  72. end
  73. end
  74. end
  75. end
  76. %%
  77. function [subjects, stats_Lvl1] = f_behav_archoices_lvl1_bci(options, subjects)
  78. % # Initialize structures
  79. nSub = size(subjects, 2);
  80. stats = struct();
  81. stats_Lvl1 = [];
  82. % # MEDIAN PERCENTAGE YES RESPONSES
  83. % figure
  84. %
  85. % T_percentAccept = [];
  86. %
  87. % for iSub = 1:nSub
  88. %
  89. % % get percentage of trials where participant accepts
  90. % stats.percentAccept(iSub) = sum(subjects(iSub).trial_characteristics3(:,8) == 1)/length(subjects(iSub).trial_characteristics3(:,8))*100;
  91. %
  92. % % plot nb of trials where participant accepts
  93. % hold on
  94. % scatter(iSub, stats.percentAccept(iSub))
  95. % xlabel('Subjects')
  96. % ylabel('Acceptance %')
  97. % xlim([0 nSub + 1])
  98. % ylim([0 100])
  99. %
  100. % end
  101. %
  102. % f_saveToMultipleFormats(fullfile(PLOTS_PATH, 'AcceptancePercent'))
  103. % # P(accept) dependent on condition
  104. count_vmPFC = 0;
  105. count_aIns = 0;
  106. for iSub = 1:nSub
  107. fields = fieldnames(subjects(iSub).trial_characteristics3);
  108. for iROI = 1:size(fields, 1)
  109. roi_name = fields{iROI};
  110. switch roi_name
  111. case 'vmPFC'
  112. count_vmPFC = count_vmPFC + 1;
  113. count = count_vmPFC;
  114. case 'aIns'
  115. count_aIns = count_aIns + 1;
  116. count = count_aIns;
  117. end
  118. stats.(roi_name).subject{count} = subjects(iSub).name;
  119. UP_subset = find(subjects(iSub).trial_characteristics3.(roi_name)(:,10) == 2);
  120. DOWN_subset = find(subjects(iSub).trial_characteristics3.(roi_name)(:,10) == 1);
  121. stats.(roi_name).UP.percentAccept(count) = sum(subjects(iSub).trial_characteristics3.(roi_name)(UP_subset,8) == 1)/length(subjects(iSub).trial_characteristics3.(roi_name)(UP_subset,8))*100;
  122. UP_percentaccept = stats.(roi_name).UP.percentAccept(count);
  123. stats.(roi_name).DOWN.percentAccept(count) = sum(subjects(iSub).trial_characteristics3.(roi_name)(DOWN_subset,8) == 1)/length(subjects(iSub).trial_characteristics3.(roi_name)(DOWN_subset,8))*100;
  124. DOWN_percentaccept = stats.(roi_name).DOWN.percentAccept(count);
  125. %RT data
  126. stats.(roi_name).UP.RT(count) = mean(subjects(iSub).trial_characteristics3.(roi_name)(UP_subset,9));
  127. stats.(roi_name).DOWN.RT(count) = mean(subjects(iSub).trial_characteristics3.(roi_name)(DOWN_subset,9));
  128. if options.plot_optional_figI
  129. figure('Position',[100 100 150 150])
  130. X = categorical({'Up','Down'});
  131. b = bar(X, [UP_percentaccept, DOWN_percentaccept],0.5, 'EdgeColor',[0 0.4470 0.7410]);
  132. b.FaceColor = 'flat';
  133. b.CData(1,:) = [0.8500 0.3250 0.0980];
  134. ylim([0 100])
  135. title(sprintf('Subject %d', iSub))
  136. ylabel('Acceptance %')
  137. set(gca, 'box', 'off')
  138. % f_saveToMultipleFormats(fullfile(strcat(subjects(iSub).name,'_AcceptancePercent_UP_DOWN', roi_name)))
  139. end
  140. %%%%%%% Compare distributions of value differences between conditions
  141. value_diff_UP = subjects(iSub).trial_characteristics3.(roi_name)(UP_subset, 6);
  142. value_diff_DOWN = subjects(iSub).trial_characteristics3.(roi_name)(DOWN_subset, 6);
  143. if options.plot_optional_figI
  144. figure('Position',[100 100 250 170])
  145. histogram(value_diff_UP, 15, 'FaceColor',[0 0.4470 0.7410])
  146. hold on
  147. histogram(value_diff_DOWN, 15, 'FaceColor', [0.8500 0.3250 0.0980])
  148. xlabel('P-UP values')
  149. set(gca, 'box', 'off')
  150. % saveas(gcf, fullfile(strcat(subjects(iSub).name,'_ValueDistr_UP_DOWN', roi_name)),'epsc');
  151. end
  152. end
  153. end
  154. % # ANALYSES, per bin method, subject
  155. count_vmPFC = 0;
  156. count_aIns = 0;
  157. % supblot formatting
  158. binMethods = {'nBin', 'nElt', 'prctile'};
  159. % figure('Position',[100 100 11000 300]);
  160. for iSub = 1:nSub %GLMs per subject loop: layer 1
  161. fields = fieldnames(subjects(iSub).trial_characteristics3);
  162. for iROI = 1:size(fields, 1)
  163. roi_name = fields{iROI};
  164. switch roi_name
  165. case 'vmPFC'
  166. count_vmPFC = count_vmPFC + 1;
  167. count = count_vmPFC;
  168. case 'aIns'
  169. count_aIns = count_aIns + 1;
  170. count = count_aIns;
  171. end
  172. behav_data = subjects(iSub).trial_characteristics3.(roi_name);
  173. P_value = behav_data(:, 4);
  174. UP_value = behav_data(:, 5);
  175. P_UP_diff = behav_data(:, 6);
  176. RT = behav_data(:, 9);
  177. accept = behav_data(:, 8);
  178. P_value_zscored = normalize(behav_data(:, 4));
  179. UP_value_zscored = normalize(behav_data(:, 5));
  180. UP_subset = find(behav_data(:,10) == 2);
  181. DOWN_subset = find(behav_data(:,10) == 1);
  182. % DOWN trials
  183. % logistic regression: choice as a function of P-UP
  184. [DOWN_betas_P_UP_diff, ~, DOWN_stats_P_UP_diff] = glmfit(P_UP_diff(DOWN_subset), accept(DOWN_subset), 'binomial', 'logit');
  185. DOWN_P_UP_diff_fit = glmval(DOWN_betas_P_UP_diff, P_UP_diff(DOWN_subset), 'logit');
  186. DOWN_P_UP_diff_fit_toplot = sortrows([P_UP_diff(DOWN_subset), DOWN_P_UP_diff_fit]); % only to make plotting fit as line easier
  187. % UP trials
  188. % logistic regression: choice as a function of P-UP
  189. [UP_betas_P_UP_diff, ~, UP_stats_P_UP_diff] = glmfit(P_UP_diff(UP_subset), accept(UP_subset), 'binomial', 'logit');
  190. UP_P_UP_diff_fit = glmval(UP_betas_P_UP_diff, P_UP_diff(UP_subset), 'logit');
  191. UP_P_UP_diff_fit_toplot = sortrows([P_UP_diff(UP_subset), UP_P_UP_diff_fit]); % only to make plotting fit as line easier
  192. %%%% PSE calculation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  193. % calculate point of subjective equality
  194. %http://rstudio-pubs-static.s3.amazonaws.com/446272_5aa2c51c9e2d4e71b2cf8229e205ce64.html
  195. UP_PSE_P_UP_diff(iSub, 1) = -(UP_betas_P_UP_diff(1)/UP_betas_P_UP_diff(2)); % if you let a + BX =0, then p = .50
  196. DOWN_PSE_P_UP_diff(iSub, 1) = -(DOWN_betas_P_UP_diff(1)/DOWN_betas_P_UP_diff(2)); % if you let a + BX =0, then p = .50
  197. % plot glms
  198. if options.plot_optional_figI
  199. figure('Position',[100 100 150 150]);
  200. cmap = [[0.4660 0.6740 0.1880]; [0.6350 0.0780 0.1840]]; %red, green
  201. g1 = gramm('x', UP_P_UP_diff_fit_toplot(:,1), 'y', UP_P_UP_diff_fit_toplot(:,2));
  202. g1.geom_line();
  203. g1.set_line_options('base_size', 2);
  204. g1.set_title(sprintf('Subject %d', iSub));
  205. g1.set_names('x', 'P- UP value', 'y', 'Choice');
  206. g1.axe_property('YLim', [0 1], 'XGrid', 'on', 'YGrid', 'on');
  207. g1.set_color_options('map', [0.6350 0.0780 0.1840; 0 0 0]);
  208. g1.update('x', DOWN_P_UP_diff_fit_toplot(:,1), 'y', DOWN_P_UP_diff_fit_toplot(:,2));
  209. g1.geom_line();
  210. g1.set_color_options('map', [0.4660 0.6740 0.1880; 0 0 0]);
  211. g1.draw();
  212. end
  213. % f_saveToMultipleFormats(fullfile(PLOTS_PATH, strcat(subjects(iSub).name,'P_UP_diff_regression_', roi_name)));
  214. %%%%%%% MODEL FOR PAPER %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  215. % logistic regression: predict choice with weights for pleasant and unpleasant values, for up and down trials separately
  216. xP_UP = [P_value_zscored,UP_value_zscored]; % column 1: Pleasant rating values; 2: Unpleasant rating values
  217. % up trials
  218. [UP_betas_P_UP,~,UP_stats_P_UP] = glmfit(xP_UP(UP_subset, :), accept(UP_subset),'binomial','link','logit');
  219. UP_fit_pleasant = glmval(UP_betas_P_UP(1:2), xP_UP(UP_subset, 1), 'logit');
  220. UP_fit_toplot_pleasant = sortrows([xP_UP(UP_subset, 1), UP_fit_pleasant]); % only to make plotting fit as line easier
  221. UP_fit_unpleasant = glmval(UP_betas_P_UP([1, 3]), xP_UP(UP_subset, 2), 'logit');
  222. UP_fit_toplot_unpleasant = sortrows([xP_UP(UP_subset, 2), UP_fit_unpleasant]); % only to make plotting fit as line easier
  223. stats.(roi_name).UP.glm_P_UP_betas(count, :) = UP_betas_P_UP;
  224. % down trials
  225. [DOWN_betas_P_UP,~,DOWN_stats_P_UP] = glmfit(xP_UP(DOWN_subset, :),accept(DOWN_subset),'binomial','link','logit');
  226. DOWN_fit_pleasant = glmval(DOWN_betas_P_UP(1:2), xP_UP(DOWN_subset, 1), 'logit');
  227. DOWN_fit_toplot_pleasant = sortrows([xP_UP(DOWN_subset, 1), DOWN_fit_pleasant]); % only to make plotting fit as line easier
  228. DOWN_fit_unpleasant = glmval(DOWN_betas_P_UP([1, 3]), xP_UP(DOWN_subset, 2), 'logit');
  229. DOWN_fit_toplot_unpleasant = sortrows([xP_UP(DOWN_subset, 2), DOWN_fit_unpleasant]); % only to make plotting fit as line easier
  230. stats.(roi_name).DOWN.glm_P_UP_betas(count, :) = DOWN_betas_P_UP;
  231. % plot glms: pleasant trials in green, unpleasant in red
  232. if options.plot_optional_figI
  233. figure('Position',[100 100 600 150]);
  234. subplot(1, 4, 1);
  235. plot(UP_fit_toplot_pleasant(:, 1), UP_fit_toplot_pleasant(:, 2), 'LineWidth', 2);
  236. title('Pleasant - up');
  237. ylim([0 1]);
  238. xlabel('Value');
  239. ylabel('Choice');
  240. subplot(1, 4, 2);
  241. plot(UP_fit_toplot_unpleasant(:, 1), UP_fit_toplot_unpleasant(:, 2), 'LineWidth', 2);
  242. title('Unpleasant - up');
  243. ylim([0 1]);
  244. xlabel('Value');
  245. ylabel('Choice');
  246. subplot(1, 4, 3);
  247. plot(DOWN_fit_toplot_pleasant(:, 1), DOWN_fit_toplot_pleasant(:, 2), 'LineWidth', 2);
  248. title('Pleasant - down');
  249. ylim([0 1]);
  250. xlabel('Value');
  251. ylabel('Choice');
  252. subplot(1, 4, 4);
  253. plot(DOWN_fit_toplot_unpleasant(:, 1), DOWN_fit_toplot_unpleasant(:, 2), 'LineWidth', 2);
  254. title('Unpleasant - down');
  255. ylim([0 1]);
  256. xlabel('Value');
  257. ylabel('Choice');
  258. end
  259. % f_saveToMultipleFormats(fullfile(PLOTS_PATH, strcat(subjects(iSub).name,'glm_w_weights_', roi_name)));
  260. end
  261. end
  262. % stats.options = options;
  263. stats_Lvl1 = stats;
  264. % save(fullfile(OUT_PATH, 'subjects.mat'), 'subjects')
  265. % save(fullfile(OUT_PATH, 'stats_Lvl1.mat'), 'stats_Lvl1')
  266. end
  267. %%
  268. function f_behav_archoices_lvl2_bci(options, subjects, indiv_stats)
  269. % f_behav_rating_lvl2 Function used to analyze behavioural data from all
  270. % participants together.
  271. %
  272. %
  273. %
  274. % Clarissa Baratin, April 2021
  275. % parts of script adapted from Teddy Landron
  276. nSub = size(subjects, 2);
  277. % # create a table for the mixed models
  278. roidata_allsubs = [];
  279. for iSub = 1:nSub
  280. fields = fieldnames(subjects(iSub).trial_characteristics3);
  281. for iROI = 1:length(fields)
  282. roi = fields{iROI};
  283. if isequal(roi,'aIns'); roi_nb = 1; else roi_nb = 2; end
  284. %if ~exist(fullfile(PLOTS_PATH, roi), 'dir') % Si le dossier d'analyses n'existe pas on le créé
  285. % mkdir(fullfile(PLOTS_PATH, roi));
  286. %end
  287. subdata_forT = [];
  288. sesdata = subjects(iSub).trial_characteristics3.(roi);
  289. % get info
  290. ntrials = length(sesdata);
  291. subdata_forT(:, 1) = repelem(iSub, ntrials);
  292. subdata_forT(:, 2) = repelem(roi_nb, ntrials);
  293. subdata_forT(:, 3) = normalize(sesdata(:, 6)); %P-UP values
  294. subdata_forT(:, 4) = sesdata(:, 8); % accept = 1, reject = 0
  295. subdata_forT(:, 5) = sesdata(:, 10); % 1 = down, 2 = up
  296. subdata_forT(:, 6) = sesdata(:, 9); %RT
  297. subdata_forT(:, 7) = normalize(sesdata(:, 9)); %RT normalized
  298. %inter-trial interval
  299. subdata_forT(:, 8) = [NaN; subjects(iSub).trial_characteristics3.(roi)(2:ntrials, 12) - subjects(iSub).trial_characteristics3.(roi)(1:ntrials-1, 13)];
  300. subdata_forT(:, 9) = abs(sesdata(:, 6)); %P-UP values, not normalized
  301. % % add pleasant and unpleasant stimulus values, z-scored
  302. % subdata_forT(:, 9) = normalize(sesdata(:, 4)); %P value
  303. % subdata_forT(:, 10) = normalize(sesdata(:, 5)); %UP value
  304. for itrial = 1:ntrials
  305. if subdata_forT(itrial, 8) > 60 || subdata_forT(itrial, 8) == 0; subdata_forT(itrial, 8) = NaN; end %avoid counting re-launched trials or between different sessions
  306. end
  307. roidata_allsubs = vertcat(roidata_allsubs, subdata_forT);
  308. T_data = array2table(roidata_allsubs, 'VariableNames',{'Sub', 'ROI', 'Value_diff', 'Accept', 'Up_down', 'RT', 'RT-zscored', 'ItI_s', 'Value_diff_nonorm_abs'});
  309. end
  310. RT_meanpersub(iSub, 1) = mean(subdata_forT(:, 6));
  311. end
  312. %% ADDED 26/10/2025: PREDICT RT FROM UNSIGNED VALUE DIFF
  313. % #Mixed linear regression
  314. % predict RT with a random slope and intercept per subject
  315. glme2 = [];
  316. glme2 = fitglme(T_data,'RT~Value_diff_nonorm_abs+(Value_diff_nonorm_abs|Sub)', 'Distribution', 'Normal', 'Link', 'identity')
  317. [fixed_betas,fixedbetanames] = fixedEffects(glme2);
  318. fixed_rows_valuediff = strcmp(fixedbetanames.Name, 'Value_diff_nonorm_abs');
  319. [random_betas,beta_names] = randomEffects(glme2);
  320. fixed_effects_predictions_valuediff = glmval(fixed_betas(fixed_rows_valuediff, :), T_data.Value_diff_nonorm_abs, 'identity');
  321. fixed_effects_predictions_toplot_valuediff = sortrows([T_data.Value_diff_nonorm_abs, fixed_effects_predictions_valuediff]); %sorts the rows of a matrix in ascending order based on the elements in the first column
  322. if options.plot_optional_figII
  323. figure('Position',[100 100 130 130]);
  324. for iSub = 1:nSub
  325. rows = strcmp(beta_names.Level, num2str(iSub)) & (strcmp(beta_names.Name, 'Value_diff_nonorm_abs') | strcmp(beta_names.Name, '(Intercept)'));
  326. random_betas_persub = fixed_betas(fixed_rows_valuediff, :) + random_betas(rows);
  327. random_effects_predictions_persub = glmval(random_betas_persub, T_data.Value_diff_nonorm_abs, 'identity');
  328. random_effects_predictions_toplot_persub = sortrows([T_data.Value_diff_nonorm_abs, random_effects_predictions_persub]);
  329. hold on
  330. plot(random_effects_predictions_toplot_persub(:, 1), random_effects_predictions_toplot_persub(:, 2), 'Color', [0.8 0.8 0.8])
  331. end
  332. plot(fixed_effects_predictions_toplot_valuediff(:, 1), fixed_effects_predictions_toplot_valuediff(:, 2), 'LineWidth', 3, 'Color', 'black')
  333. % title(blk)
  334. xlabel('|Pleasant-unpleasant rating|')
  335. xticks([min(fixed_effects_predictions_toplot_valuediff(:, 1)) max(fixed_effects_predictions_toplot_valuediff(:, 1))])
  336. %xticklabels({'0', '100'})
  337. ylabel('RT')
  338. xlim([min(fixed_effects_predictions_toplot_valuediff(:, 1)) max(fixed_effects_predictions_toplot_valuediff(:, 1))])
  339. % saveas(gcf, fullfile('Mixed models - RT by abs(pleas-unpleas).png'));
  340. end
  341. % #GLM WEIGHTS for pleasant and unpleasant/up and down/vmPFC and aIns
  342. % Bar plots with two bars: up-down pleasant trials and up-down unpleasant trials %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  343. P_UP_col_vmPFC = [repelem({'Pleasant'}, length(indiv_stats.vmPFC.subject)), repelem({'Unpleasant'}, length(indiv_stats.vmPFC.subject))]';
  344. %UP_DOWN_col_vmPFC = [repelem({'Up'}, length(indiv_stats.vmPFC.subject)), repelem({'Up'}, length(indiv_stats.vmPFC.subject)), repelem({'Down'}, length(indiv_stats.vmPFC.subject)), repelem({'Down'}, length(indiv_stats.vmPFC.subject))]';
  345. UP_minus_DOWN_betas_col_vmPFC = [indiv_stats.vmPFC.UP.glm_P_UP_betas(:, 2)-indiv_stats.vmPFC.DOWN.glm_P_UP_betas(:, 2); indiv_stats.vmPFC.UP.glm_P_UP_betas(:, 3)-indiv_stats.vmPFC.DOWN.glm_P_UP_betas(:, 3)]; % col 2 = pleasant betas, col 3 = unpleasant betas
  346. T_glm_vmPFC = table(P_UP_col_vmPFC, UP_minus_DOWN_betas_col_vmPFC);
  347. if options.plot_optional_figII
  348. % Bar plot of pleasant vs unpleasant regression coefficients in the vmPFC for UP minus DOWN trials
  349. figure('Position',[100 100 300 300]);
  350. figfilename = 'barplot_betas_UPminusDOWN_vmPFC';
  351. g = gramm('x', T_glm_vmPFC.P_UP_col_vmPFC, 'y', T_glm_vmPFC.UP_minus_DOWN_betas_col_vmPFC);
  352. g.set_title('vmPFC');
  353. g.stat_summary('geom', {'bar', 'black_errorbar'}, 'width', 0.6);
  354. %g.set_color_options('map', [0.8 0.8 0.8]); %
  355. g.axe_property('FontName', 'Arial', 'FontSize', 8);
  356. %g.axe_property('XLim', [0.5 2.5], 'XTick', [0.75 2.25], 'XTickLabels', {'Pleas','Unpleas'}); %
  357. g.set_names('y', 'Regression coefficients', 'x', ' ');
  358. g.geom_hline('yintercept', 0);
  359. %g.no_legend();
  360. g.update('x', T_glm_vmPFC.P_UP_col_vmPFC, 'y', T_glm_vmPFC.UP_minus_DOWN_betas_col_vmPFC);
  361. g.geom_jitter('dodge', 0.5);
  362. g.set_point_options('base_size', 4);
  363. %g.set_color_options('map', [0.1 0.1 0.1]); %
  364. g.no_legend();
  365. g.draw();
  366. % saveas(gcf, fullfile(PLOTS_PATH,[figfilename '.png']));
  367. end
  368. % ttests against zero
  369. % Pleasant betas - vmPFC
  370. fprintf('T-test pleasant regression coefficients vmPFC \n')
  371. [h,p,ci,stats] = ttest(indiv_stats.vmPFC.UP.glm_P_UP_betas(:, 2)-indiv_stats.vmPFC.DOWN.glm_P_UP_betas(:, 2))
  372. % Unpleasant betas - vmPFC
  373. fprintf('T-test unpleasant regression coefficients vmPFC \n')
  374. %[h,p,ci,stats] = ttest(indiv_stats.vmPFC.UP.glm_P_UP_betas(:, 3)indiv_stats.vmPFC.DOWN.glm_P_UP_betas(:, 3))
  375. % Bar plot of pleasant vs unpleasant regression coefficients in the aIns for UP minus DOWN trials
  376. P_UP_col_aIns = [repelem({'Pleasant'}, length(indiv_stats.aIns.subject)), repelem({'Unpleasant'}, length(indiv_stats.aIns.subject))]';
  377. %UP_DOWN_col_vmPFC = [repelem({'Up'}, length(indiv_stats.vmPFC.subject)), repelem({'Up'}, length(indiv_stats.vmPFC.subject)), repelem({'Down'}, length(indiv_stats.vmPFC.subject)), repelem({'Down'}, length(indiv_stats.vmPFC.subject))]';
  378. UP_minus_DOWN_betas_col_aIns = [indiv_stats.aIns.UP.glm_P_UP_betas(:, 2)-indiv_stats.aIns.DOWN.glm_P_UP_betas(:, 2); indiv_stats.aIns.UP.glm_P_UP_betas(:, 3)-indiv_stats.aIns.DOWN.glm_P_UP_betas(:, 3)]; % col 2 = pleasant betas, col 3 = unpleasant betas
  379. T_glm_aIns = table(P_UP_col_aIns, UP_minus_DOWN_betas_col_aIns);
  380. if options.plot_optional_figII
  381. % Bar plot of pleasant vs unpleasant regression coefficients in the vmPFC for UP and DOWN trials
  382. figure('Position',[100 100 300 300]);
  383. figfilename = 'barplot_betas_UPminusDOWN_aIns';
  384. g = gramm('x', T_glm_aIns.P_UP_col_aIns, 'y', T_glm_aIns.UP_minus_DOWN_betas_col_aIns);
  385. g.set_title('aIns');
  386. g.stat_summary('geom', {'bar', 'black_errorbar'}, 'width', 0.6);
  387. %g.set_color_options('map', [0.8 0.8 0.8]); %
  388. g.axe_property('FontName', 'Arial', 'FontSize', 8);
  389. %g.axe_property('XLim', [0.5 2.5], 'XTick', [0.75 2.25], 'XTickLabels', {'Pleas','Unpleas'}); %
  390. g.set_names('y', 'Regression coefficients', 'x', ' ');
  391. g.geom_hline('yintercept', 0);
  392. %g.no_legend();
  393. g.update('x', T_glm_aIns.P_UP_col_aIns, 'y', T_glm_aIns.UP_minus_DOWN_betas_col_aIns);
  394. g.geom_jitter('dodge', 0.5);
  395. g.set_point_options('base_size', 4);
  396. %g.set_color_options('map', [0.1 0.1 0.1]); %
  397. g.no_legend();
  398. g.draw();
  399. % saveas(gcf, fullfile([figfilename '.png']));
  400. end
  401. % ttests against zero
  402. % Pleasant betas - aIns
  403. fprintf('T-test pleasant regression coefficients aIns \n')
  404. [h,p,ci,stats] = ttest(indiv_stats.aIns.UP.glm_P_UP_betas(:, 2)-indiv_stats.aIns.DOWN.glm_P_UP_betas(:, 2))
  405. % Unpleasant betas - aIns
  406. fprintf('T-test unpleasant regression coefficients aIns \n')
  407. [h,p,ci,stats] = ttest(indiv_stats.aIns.UP.glm_P_UP_betas(:, 3)-indiv_stats.aIns.DOWN.glm_P_UP_betas(:, 3))
  408. % Bar plots with four bars: up & down pleasant trials and up & down unpleasant trials %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  409. % VMPFC
  410. P_UP_col_vmPFC = [repelem({'Pleasant'}, length(indiv_stats.vmPFC.subject)), repelem({'Unpleasant'}, length(indiv_stats.vmPFC.subject)), repelem({'Pleasant'}, length(indiv_stats.vmPFC.subject)), repelem({'Unpleasant'}, length(indiv_stats.vmPFC.subject))]';
  411. UP_DOWN_col_vmPFC = [repelem({'Up'}, length(indiv_stats.vmPFC.subject)), repelem({'Up'}, length(indiv_stats.vmPFC.subject)), repelem({'Down'}, length(indiv_stats.vmPFC.subject)), repelem({'Down'}, length(indiv_stats.vmPFC.subject))]';
  412. UP_DOWN_betas_col_vmPFC = [indiv_stats.vmPFC.UP.glm_P_UP_betas(:, 2); indiv_stats.vmPFC.UP.glm_P_UP_betas(:, 3); indiv_stats.vmPFC.DOWN.glm_P_UP_betas(:, 2); indiv_stats.vmPFC.DOWN.glm_P_UP_betas(:, 3)]; % col 2 = pleasant betas, col 3 = unpleasant betas
  413. T_glm_vmPFC2 = table(P_UP_col_vmPFC, UP_DOWN_betas_col_vmPFC, UP_DOWN_col_vmPFC);
  414. if options.plot_optional_figII
  415. % Bar plot of pleasant vs unpleasant regression coefficients in the vmPFC for UP and DOWN trials
  416. figure('Position',[100 100 300 300]);
  417. figfilename = 'barplot_betas_UPandDOWN_vmPFC';
  418. g = gramm('x', T_glm_vmPFC2.P_UP_col_vmPFC, 'y', T_glm_vmPFC2.UP_DOWN_betas_col_vmPFC, 'color', T_glm_vmPFC2.UP_DOWN_col_vmPFC);
  419. g.set_title('vmPFC');
  420. g.stat_summary('geom', {'bar', 'black_errorbar'}, 'width', 0.6);
  421. %g.set_color_options('map', [0.8 0.8 0.8]); %
  422. g.axe_property('FontName', 'Arial', 'FontSize', 8);
  423. g.geom_hline('yintercept', 0)
  424. %g.axe_property('XLim', [0.5 2.5], 'XTick', [0.75 2.25], 'XTickLabels', {'Pleas','Unpleas'}); %
  425. g.set_names('y', 'Regression coefficients', 'x', ' ');
  426. %g.no_legend();
  427. g.update('x', T_glm_vmPFC2.P_UP_col_vmPFC, 'y', T_glm_vmPFC2.UP_DOWN_betas_col_vmPFC, 'color', T_glm_vmPFC2.UP_DOWN_col_vmPFC);
  428. g.geom_jitter('dodge', 0.5, 'alpha', 0.5);
  429. g.set_point_options('base_size', 4);
  430. %g.set_color_options('map', [0.1 0.1 0.1]); %
  431. g.no_legend();
  432. g.draw();
  433. % saveas(gcf, fullfile([figfilename '.png']));
  434. end
  435. % aINS
  436. P_UP_col_aINS = [repelem({'Pleasant'}, length(indiv_stats.aIns.subject)), repelem({'Unpleasant'}, length(indiv_stats.aIns.subject)), repelem({'Pleasant'}, length(indiv_stats.aIns.subject)), repelem({'Unpleasant'}, length(indiv_stats.aIns.subject))]';
  437. UP_DOWN_col_aINS = [repelem({'Up'}, length(indiv_stats.aIns.subject)), repelem({'Up'}, length(indiv_stats.aIns.subject)), repelem({'Down'}, length(indiv_stats.aIns.subject)), repelem({'Down'}, length(indiv_stats.aIns.subject))]';
  438. UP_DOWN_betas_col_aINS = [indiv_stats.aIns.UP.glm_P_UP_betas(:, 2); indiv_stats.aIns.UP.glm_P_UP_betas(:, 3); indiv_stats.aIns.DOWN.glm_P_UP_betas(:, 2); indiv_stats.aIns.DOWN.glm_P_UP_betas(:, 3)]; % col 2 = pleasant betas, col 3 = unpleasant betas
  439. T_glm_aINS2 = table(P_UP_col_aINS, UP_DOWN_betas_col_aINS, UP_DOWN_col_aINS);
  440. if options.plot_optional_figII
  441. % Bar plot of pleasant vs unpleasant regression coefficients in the vmPFC for UP and DOWN trials
  442. figure('Position',[100 100 300 300]);
  443. figfilename = 'barplot_betas_UPandDOWN_aIns';
  444. g = gramm('x', T_glm_aINS2.P_UP_col_aINS, 'y', T_glm_aINS2.UP_DOWN_betas_col_aINS, 'color', T_glm_aINS2.UP_DOWN_col_aINS);
  445. g.set_title('aIns');
  446. g.stat_summary('geom', {'bar', 'black_errorbar'}, 'width', 0.6);
  447. %g.set_color_options('map', [0.8 0.8 0.8]); %
  448. g.axe_property('FontName', 'Arial', 'FontSize', 8);
  449. g.geom_hline('yintercept', 0);
  450. %g.axe_property('XLim', [0.5 2.5], 'XTick', [0.75 2.25], 'XTickLabels', {'Pleas','Unpleas'}); %
  451. g.set_names('y', 'Regression coefficients', 'x', ' ');
  452. %g.no_legend();
  453. g.update('x', T_glm_aINS2.P_UP_col_aINS, 'y', T_glm_aINS2.UP_DOWN_betas_col_aINS, 'color', T_glm_aINS2.UP_DOWN_col_aINS);
  454. g.geom_jitter('dodge', 0.5, 'alpha', 0.5);
  455. g.set_point_options('base_size', 4);
  456. %g.set_color_options('map', [0.1 0.1 0.1]); %
  457. g.no_legend();
  458. g.draw();
  459. % saveas(gcf, fullfile([figfilename '.png']));
  460. end
  461. % #MIXED MODELS
  462. % Mixed logistic regression: overall subject performance
  463. % predict P(accept based on the Value diff (P-UP) with a random slope and intercept per subject
  464. glme1 = [];
  465. glme1 = fitglme(T_data,'Accept~Value_diff+(Value_diff|Sub)', 'Distribution', 'Binomial', 'Link', 'logit')
  466. [fixed_betas,fixedbetanames] = fixedEffects(glme1);
  467. fixed_rows_valuediff = strcmp(fixedbetanames.Name, 'Value_diff') | strcmp(fixedbetanames.Name, '(Intercept)');
  468. [random_betas,beta_names] = randomEffects(glme1);
  469. fixed_effects_predictions = glmval(fixed_betas, T_data.Value_diff, 'logit');
  470. fixed_effects_predictions_toplot = sortrows([T_data.Value_diff, fixed_effects_predictions]);
  471. figfilename = 'P_accept_overall';
  472. if true %Fig.1.d
  473. figure('Position',[100 100 130 130]);
  474. for iSub = 1:nSub
  475. rows = strcmp(beta_names.Level, num2str(iSub)) & (strcmp(beta_names.Name, 'Value_diff') | strcmp(beta_names.Name, '(Intercept)'));
  476. random_betas_persub = fixed_betas(fixed_rows_valuediff, :) + random_betas(rows);
  477. random_effects_predictions_persub = glmval(random_betas_persub, T_data.Value_diff, 'logit');
  478. random_effects_predictions_toplot_persub = sortrows([T_data.Value_diff, random_effects_predictions_persub]);
  479. hold on
  480. plot(random_effects_predictions_toplot_persub(:, 1), random_effects_predictions_toplot_persub(:, 2), 'Color', [0.8 0.8 0.8], 'LineWidth', 1)
  481. end
  482. plot(fixed_effects_predictions_toplot(:, 1), fixed_effects_predictions_toplot(:, 2), 'LineWidth', 2, 'Color', [0 0 0]) % , 'Color', options.aesthetics.choice_colors(iblk, :)
  483. % title(blk)
  484. xlabel({'Pleasant-unpleasant';'rating'})
  485. ylabel('P(accept)')
  486. xticks([min(fixed_effects_predictions_toplot(:, 1)) max(fixed_effects_predictions_toplot(:, 1))])
  487. xlim([min(fixed_effects_predictions_toplot(:, 1)) max(fixed_effects_predictions_toplot(:, 1))])
  488. xticklabels({'-100', '100'})
  489. ax = gca;
  490. ax.FontSize = 8;
  491. ax.FontName = 'arial';
  492. % saveas(gcf, fullfile([figfilename '.png']));
  493. % saveas(gcf, fullfile(figfilename), 'epsc');
  494. end
  495. if options.plot_optional_figII
  496. % Mixed logistic regressions: per roi and up/down block
  497. rois = {'aIns', 'vmPFC'};
  498. for iROI = 1:length(rois) % is aIns, 2 is vmPFC
  499. roi = rois{iROI};
  500. if isequal(roi,'aIns'); roi_nb = 1; else roi_nb = 2; end
  501. figure('Position',[100 100 150 150]);
  502. hold on
  503. condis = {'up', 'down'};
  504. for iCondi = 1:length(condis) % up or down
  505. condi = condis{iCondi};
  506. if isequal(condi,'up'); condi_nb = 2; else condi_nb = 1; end
  507. T = T_data;
  508. T([find(~(T_data.ROI == roi_nb) & ~(T_data.Up_down == condi_nb))], :) = []; % delete all rows which are not the correct roi and up/down
  509. glme = [];
  510. glme = fitglme(T,'Accept~Value_diff+(Value_diff|Sub)', 'Distribution', 'Binomial', 'Link', 'logit')
  511. fixed_betas = fixedEffects(glme);
  512. [random_betas1,beta_names] = randomEffects(glme);
  513. fixed_effects_predictions = glmval(fixed_betas, T.Value_diff, 'logit');
  514. fixed_effects_predictions_toplot = sortrows([T.Value_diff, fixed_effects_predictions]);
  515. plot(fixed_effects_predictions_toplot(:, 1), fixed_effects_predictions_toplot(:, 2), 'LineWidth', 2) % , 'Color', options.aesthetics.choice_colors(iblk, :)
  516. % title(blk)
  517. xlabel('Pleasant-unpleasant rating')
  518. ylabel('P(accept)')
  519. xticks([min(fixed_effects_predictions_toplot(:, 1)) max(fixed_effects_predictions_toplot(:, 1))])
  520. xlim([min(fixed_effects_predictions_toplot(:, 1)) max(fixed_effects_predictions_toplot(:, 1))])
  521. xticklabels({'-100', '100'})
  522. ax = gca;
  523. ax.FontSize = 8;
  524. ax.FontName = 'arial';
  525. end
  526. hold off
  527. end
  528. end
  529. % Mixed logistic regression: overall subject performance
  530. % predict P(accept based on the Value diff (P-UP) with a random slope and intercept per subject
  531. glme2 = [];
  532. glme2 = fitglme(T_data,'Accept~Value_diff+ItI_s+Up_down+ROI+ROI*Up_down+(Value_diff|Sub)', 'Distribution', 'Binomial', 'Link', 'logit')
  533. %% Bar plots: ALL BARS ON SAME PLOT %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  534. percent_accept_allcondis = nan(4, max(length(indiv_stats.vmPFC.UP.percentAccept), length(indiv_stats.aIns.UP.percentAccept)));
  535. percent_accept_allcondis(1, 1:length(indiv_stats.vmPFC.UP.percentAccept)) = indiv_stats.vmPFC.UP.percentAccept;
  536. percent_accept_allcondis(2, 1:length(indiv_stats.vmPFC.DOWN.percentAccept)) = indiv_stats.vmPFC.DOWN.percentAccept;
  537. percent_accept_allcondis(3, 1:length(indiv_stats.aIns.UP.percentAccept)) = indiv_stats.aIns.UP.percentAccept;
  538. percent_accept_allcondis(4, 1:length(indiv_stats.aIns.DOWN.percentAccept)) = indiv_stats.aIns.DOWN.percentAccept;
  539. if options.plot_optional_figII
  540. figure('Position',[100 100 150 150]);
  541. cat_vect = [repmat(0.5, length(percent_accept_allcondis), 1); repmat(1, length(percent_accept_allcondis), 1); repmat(2, length(percent_accept_allcondis), 1); repmat(2.5, length(percent_accept_allcondis), 1)];
  542. g = gramm('x', cat_vect, 'y', [percent_accept_allcondis(1, :)'; percent_accept_allcondis(2, :)'; percent_accept_allcondis(3, :)'; percent_accept_allcondis(4, :)'], 'color', cat_vect);
  543. g.stat_summary('geom', {'bar', 'black_errorbar'},'width', 3);
  544. %g.set_color_options('map', options.aesthetics.choice_colors); %
  545. g.axe_property('FontName', 'Arial', 'FontSize', 8);
  546. g.axe_property('XLim', [0 3], 'XTick', [0.75 2.25], 'XTickLabels', {'vmPFC','aIns'}); %
  547. g.set_names('y', 'Acceptance (%)', 'x', ' ');
  548. g.no_legend();
  549. g.update('x', cat_vect, 'y', [percent_accept_allcondis(1, :)'; percent_accept_allcondis(2, :)'; percent_accept_allcondis(3, :)'; percent_accept_allcondis(4, :)'], 'color', cat_vect);
  550. g.geom_jitter('alpha', 0.5);
  551. g.set_point_options('base_size', 3);
  552. %g.set_color_options('map', options.aesthetics.choice_colors - [0.15 0.15 0.15; 0 0.15 0.15; 0.15 0.15 0.15; 0.15 0.15 0.15]); %
  553. g.no_legend();
  554. g.draw();
  555. end
  556. [h,p_vmPFC,ci,statsvmPFC] = ttest(indiv_stats.vmPFC.UP.percentAccept,indiv_stats.vmPFC.DOWN.percentAccept)
  557. [h,p_aIns,ci,stats2] = ttest(indiv_stats.aIns.UP.percentAccept,indiv_stats.aIns.DOWN.percentAccept)
  558. [h,p_vmPFC_aIns,ci,stats2] = ttest2(indiv_stats.vmPFC.UP.percentAccept-indiv_stats.vmPFC.DOWN.percentAccept, indiv_stats.aIns.UP.percentAccept-indiv_stats.aIns.DOWN.percentAccept)
  559. % test without AFTl, NAIn and VINm
  560. %[h,p_vmPFC,ci,statsvmPFC] = ttest(indiv_stats.vmPFC.UP.percentAccept(1, [1,2,5,6]),indiv_stats.vmPFC.DOWN.percentAccept(1, [1,2,5,6]));
  561. % RT bar plot
  562. figfilename = strcat('RT_', roi);
  563. RT_allcondis = nan(4, max(length(indiv_stats.vmPFC.UP.RT), length(indiv_stats.aIns.UP.RT)));
  564. RT_allcondis(1, 1:length(indiv_stats.vmPFC.UP.RT)) = indiv_stats.vmPFC.UP.RT;
  565. RT_allcondis(2, 1:length(indiv_stats.vmPFC.DOWN.RT)) = indiv_stats.vmPFC.DOWN.RT;
  566. RT_allcondis(3, 1:length(indiv_stats.aIns.UP.RT)) = indiv_stats.aIns.UP.RT;
  567. RT_allcondis(4, 1:length(indiv_stats.aIns.DOWN.RT)) = indiv_stats.aIns.DOWN.RT;
  568. if options.plot_optional_figII
  569. figure('Position',[100 100 150 150]);
  570. cat_vect = [repmat(0.5, length(RT_allcondis), 1); repmat(1, length(RT_allcondis), 1); repmat(2, length(RT_allcondis), 1); repmat(2.5, length(RT_allcondis), 1)];
  571. g = gramm('x', cat_vect, 'y', [RT_allcondis(1, :)'; RT_allcondis(2, :)'; RT_allcondis(3, :)'; RT_allcondis(4, :)'], 'color', cat_vect);
  572. g.stat_summary('geom', {'bar', 'black_errorbar'},'width', 3);
  573. %g.set_color_options('map', options.aesthetics.choice_colors); %
  574. g.axe_property('FontName', 'Arial', 'FontSize', 8);
  575. g.axe_property('XLim', [0 3], 'XTick', [0.75 2.25], 'XTickLabels', {'vmPFC','aIns'}); %
  576. g.set_names('y', 'Acceptance (%)', 'x', ' ');
  577. g.no_legend();
  578. g.update('x', cat_vect, 'y', [RT_allcondis(1, :)'; RT_allcondis(2, :)'; RT_allcondis(3, :)'; RT_allcondis(4, :)'], 'color', cat_vect);
  579. g.geom_jitter('alpha', 0.5);
  580. g.set_point_options('base_size', 3);
  581. %g.set_color_options('map', options.aesthetics.choice_colors - [0.15 0.15 0.15; 0 0.15 0.15; 0.15 0.15 0.15; 0.15 0.15 0.15]); %
  582. g.no_legend();
  583. g.draw();
  584. % saveas(gcf, fullfile(PLOTS_PATH, roi,[figfilename '.png']));
  585. % saveas(gcf, fullfile(PLOTS_PATH, roi, figfilename), 'epsc');
  586. end
  587. % #BAR PLOT PER ROI %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  588. rois = {'aIns', 'vmPFC'};
  589. for iROI = 1:length(rois) % is aIns, 2 is vmPFC
  590. roi = rois{iROI};
  591. percent_accept_UP = indiv_stats.(roi).UP.percentAccept;
  592. percent_accept_DOWN = indiv_stats.(roi).DOWN.percentAccept;
  593. switch roi
  594. case 'vmPFC'
  595. cmap = [hex2rgb('#7dcb9c'); hex2rgb('#7dcb9c')];
  596. cmap2 = repmat(hex2rgb('#1d8352'), nSub, 1);
  597. T_data2 = T_data(T_data.ROI==2, :);
  598. case 'aIns'
  599. cmap = [hex2rgb('#f795a2'); hex2rgb('#f795a2')];
  600. cmap2 = repmat(hex2rgb('#e44369'), nSub, 1);
  601. T_data2 = T_data(T_data.ROI==1, :);
  602. end
  603. figfilename = strcat('UpvsDown_Acceptance_', roi);
  604. if true % Fig2.b 2.f.
  605. % acceptance bar plot
  606. figure('Position',[200 200 120 120]);
  607. cat_vect = [repmat(1, length(percent_accept_UP), 1); repmat(2, length(percent_accept_DOWN), 1)];
  608. cat_vect2 = repmat([1:length(percent_accept_UP)], 1, 2);
  609. g = gramm('x', cat_vect, 'y', [percent_accept_UP'; percent_accept_DOWN']); % , 'color', cat_vect
  610. g.stat_summary('geom', {'bar', 'black_errorbar'},'width', 0.5);
  611. %g.set_color_options('map', options.aesthetics.choice_colors); %
  612. g.axe_property('FontName', 'Arial', 'FontSize', 8);
  613. g.axe_property('XLim', [0.5 2.5], 'XTick', [1 2], 'XTickLabels', {'Up','Down'}); %
  614. g.set_names('y', 'Acceptance (%)', 'x', ' ');
  615. g.no_legend();
  616. g.set_color_options('map', cmap);
  617. g.update('x', cat_vect, 'y', [percent_accept_UP'; percent_accept_DOWN']); %, 'color', cat_vect
  618. g.geom_point('alpha', 0.5);
  619. g.set_point_options('base_size', 5);
  620. g.set_color_options('map', cmap2);
  621. g.draw();
  622. g.update('x', cat_vect, 'y', [percent_accept_UP'; percent_accept_DOWN'], 'color', cat_vect2);
  623. g.set_color_options('map', cmap2);
  624. g.geom_line()
  625. %g.set_color_options('map', options.aesthetics.choice_colors - [0.15 0.15 0.15; 0 0.15 0.15; 0.15 0.15 0.15; 0.15 0.15 0.15]); %
  626. g.no_legend();
  627. g.draw()
  628. % saveas(gcf, fullfile(roi,[figfilename '.png']));
  629. % saveas(gcf, fullfile(roi, figfilename), 'epsc');
  630. end
  631. end
  632. % #BAR PLOT OF vmPFC vs aINS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  633. percent_accept_upminusdown = nan(2, max(length(indiv_stats.vmPFC.UP.percentAccept), length(indiv_stats.aIns.UP.percentAccept)));
  634. percent_accept_upminusdown(1, 1:length(indiv_stats.vmPFC.UP.percentAccept)) = indiv_stats.vmPFC.UP.percentAccept-indiv_stats.vmPFC.DOWN.percentAccept;
  635. percent_accept_upminusdown(2, 1:length(indiv_stats.aIns.UP.percentAccept)) = indiv_stats.aIns.UP.percentAccept-indiv_stats.aIns.DOWN.percentAccept;
  636. if options.plot_optional_figII
  637. figure('Position',[200 200 160 170]);
  638. clear g
  639. figfilename = 'Up_minus_Down_Acceptance';
  640. cat_vect = [repmat(1, length(percent_accept_upminusdown), 1); repmat(2, length(percent_accept_upminusdown), 1)];
  641. g = gramm('x', cat_vect, 'y', [percent_accept_upminusdown(1, :)'; percent_accept_upminusdown(2, :)'], 'color', cat_vect);
  642. g.stat_boxplot('width', 1); %'geom', {'bar', 'black_errorbar'},'width', 1
  643. g.axe_property('FontName', 'Arial', 'FontSize', 8);
  644. g.axe_property('XLim', [0.5 2.5], 'XTick', [1 2], 'YLim', [min(percent_accept_upminusdown(:))-7 max(percent_accept_upminusdown(:))+7], 'XTickLabels', {'vmPFC','aIns'}); %
  645. g.set_names('y', 'Up-down acceptance (%)', 'x', ' ');
  646. cmap = [hex2rgb('#1d8352'); hex2rgb('#e44369')];
  647. g.set_color_options('map', cmap); %
  648. g.no_legend();
  649. g.update('x', cat_vect, 'y', [percent_accept_upminusdown(1, :)'; percent_accept_upminusdown(2, :)'], 'color', cat_vect);
  650. g.geom_jitter('alpha', 0.5);
  651. g.set_point_options('base_size', 5);
  652. %g.set_color_options('map', options.aesthetics.choice_colors - [0.15 0.15 0.15; 0 0.15 0.15; 0.15 0.15 0.15; 0.15 0.15 0.15]); %
  653. g.no_legend();
  654. g.geom_abline('intercept', 0, 'slope', 0);
  655. g.draw();
  656. % saveas(gcf, fullfile([figfilename '.png']));
  657. % g.export('file_name', figfilename, 'file_type', 'eps')
  658. end
  659. if options.plot_optional_figII
  660. % # RTs bar plot
  661. figure('Position',[100 100 70 110]);
  662. g = gramm('x', repelem(1, nSub), 'y', [RT_meanpersub]);
  663. g.stat_summary('geom', {'bar', 'black_errorbar'}, 'width', 1);
  664. g.set_color_options('map', [0.8 0.8 0.8]); %
  665. g.axe_property('FontName', 'Arial', 'FontSize', 8);
  666. g.axe_property('XLim', [0 2], 'XTick',[]); %
  667. g.set_names('y', 'Mean RT (s)', 'x', ' ');
  668. g.no_legend();
  669. g.update('x', repelem(1, nSub), 'y', [RT_meanpersub]);
  670. g.geom_jitter('alpha', 0.5);
  671. g.set_point_options('base_size', 4);
  672. g.set_color_options('map', [0.1 0.1 0.1]); %
  673. g.no_legend();
  674. g.draw();
  675. end
  676. mean_RT = mean(RT_meanpersub)
  677. S_RT = std(RT_meanpersub);
  678. SEM_RT = S_RT /sqrt(length(RT_meanpersub))
  679. end

a1_behav_archoices_bci.m, under CC-BY-4.0 · at the source

Overview

Authors: Clarissa Baratin1, Mathias Pessiglione2, Philippe Kahane1,3, Alexis Robin1,3, Lorella Minotti1,3, Guillaume Jean-Paul Claude Becq4, Julien Bastin1
  1. Univ. Grenoble Alpes, Inserm U1216, CHU Grenoble Alpes, Grenoble Institut Neurosciences, GIN, Grenoble, France
  2. Paris Brain Institute (ICM), Sorbonne Université, Inserm UMR1127, CNRS UMR 7225, Paris, France
  3. Neurology Department, CHU Grenoble Alpes, Grenoble, France
  4. Univ. Grenoble Alpes, CNRS, Grenoble INP, GIPSA-Lab, Grenoble, France
Journal: Nature communications, volume 17, issue 1, article 8325
Dates: received 15 December 2025; accepted 24 June 2026; published online 4 July 2026
Type: Research article · Language: English
License: CC BY-NC-ND
Identifiers: DOI 10.1038/s41467-026-75265-5 · PMID 42401540 · PMCID PMC13470483 · OpenAlex W7167357835
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: human (organism), cognitive (subfield)
Methods: Spectral & time-frequency, Statistics, Machine learning, Preprocessing, Evoked potentials, fMRI & imaging, Smoothing, state filtering, decompositions, Physiology & signal measures
Keywords: Cognitive neuroscience, Human behaviour
MeSH: Choice Behavior*, Decision Making*, Gamma Rhythm*, Insular Cortex*, Animals, Brain-Computer Interfaces, Humans, Magnetic Resonance Imaging, Male (* major topic)
Topic: Radiation Effects in Electronics (Electrical and Electronic Engineering, Engineering), according to OpenAlex
Funding: Agence Nationale de la Recherche (ANR-22-CE17-0057, ANR-15-IDEX-0002); Fondation pour la Recherche Médicale
Citations: not cited yet (Europe PMC); 55 references in the paper

Abstract

The abstract is not reproduced here: the paper's license (CC BY-NC-ND) does not allow it. Read it in the paper, at the publisher or on Europe PMC.

Repository

Its files are read in the Code ↔ Paper reader above, with 2 matches between paragraphs and lines of code.

Zenodo 20545301

License: CC-BY-4.0
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Size: 1 file
Software Heritage: not checked
Found in: “Code availability”
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Availability: 1 check, the latest on 27 September 2026: the link answers (HTTP 200)
  • 27 September 2026: the link answers (HTTP 200)
5 files
At the source:

Code availability statement

The paper has a code availability statement. Its license (CC BY-NC-ND) does not allow reproducing it here; in short, from what the harvester recognized in it:

  • it points to the authors' code: Zenodo 20545301

Read it in the paper: doi.org/10.1038/s41467-026-75265-5.

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;
  • 4 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.

Data availability statement

The paper has a data availability statement. Its license (CC BY-NC-ND) does not allow reproducing it here; in short, from what the harvester recognized in it:

  • no repository, dataset or request procedure was recognized in it

Read it in the paper: doi.org/10.1038/s41467-026-75265-5.

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 2, 28 September 2026

  • Funding: added Agence Nationale de la Recherche: ANR-22-CE17-0057, ANR-15-IDEX-0002; Fondation pour la Recherche Médicale

Version 1, 27 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 7 authors, 2 keywords, 9 MeSH terms, 52 references.

Cite

This paper

Baratin, C., Pessiglione, M., Kahane, P., Robin, A., Minotti, L., Becq, G. J.-P. C., & Bastin, J. (2026). Closed-loop readout of anterior insula high-gamma activity steers value-based decisions. Nature communications, 17(1), 8325. https://doi.org/10.1038/s41467-026-75265-5

BibTeX

@article{baratin2026closed,
author = {Baratin, Clarissa and Pessiglione, Mathias and Kahane, Philippe and Robin, Alexis and Minotti, Lorella and Becq, Guillaume Jean-Paul Claude and Bastin, Julien},
title = {{Closed-loop readout of anterior insula high-gamma activity steers value-based decisions}},
journal = {Nature communications},
year = {2026},
month = jul,
volume = {17},
number = {1},
pages = {8325},
publisher = {Nature Publishing Group},
issn = {2041-1723},
doi = {10.1038/s41467-026-75265-5},
url = {https://doi.org/10.1038/s41467-026-75265-5},
pmid = {42401540},
pmcid = {PMC13470483}
}

RIS

TY - JOUR
AU - Baratin, Clarissa
AU - Pessiglione, Mathias
AU - Kahane, Philippe
AU - Robin, Alexis
AU - Minotti, Lorella
AU - Becq, Guillaume Jean-Paul Claude
AU - Bastin, Julien
TI - Closed-loop readout of anterior insula high-gamma activity steers value-based decisions
T2 - Nature communications
J2 - Nat Commun
PY - 2026
DA - 2026/07/04
VL - 17
IS - 1
SP - 8325
SN - 2041-1723
PB - Nature Publishing Group
DO - 10.1038/s41467-026-75265-5
UR - https://doi.org/10.1038/s41467-026-75265-5
LA - en
ER -

CSL-JSON

{
"id": "10.1038/s41467-026-75265-5",
"type": "article-journal",
"title": "Closed-loop readout of anterior insula high-gamma activity steers value-based decisions",
"container-title": "Nature communications",
"author": [
{
"family": "Baratin",
"given": "Clarissa"
},
{
"family": "Pessiglione",
"given": "Mathias"
},
{
"family": "Kahane",
"given": "Philippe"
},
{
"family": "Robin",
"given": "Alexis"
},
{
"family": "Minotti",
"given": "Lorella"
},
{
"family": "Becq",
"given": "Guillaume Jean-Paul Claude"
},
{
"family": "Bastin",
"given": "Julien"
}
],
"container-title-short": "Nat Commun",
"volume": "17",
"issue": "1",
"page": "8325",
"DOI": "10.1038/s41467-026-75265-5",
"PMID": "42401540",
"PMCID": "PMC13470483",
"ISSN": "2041-1723",
"publisher": "Nature Publishing Group",
"URL": "https://doi.org/10.1038/s41467-026-75265-5",
"language": "en",
"issued": {
"date-parts": [
[
2026,
7,
4
]
]
}
}

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.1038/s41467-026-76593-2 [code]
Complementary and opponent value signals in the human brain support choosing the best and avoiding the worst.
Journal: Nature communications
In common: 18 references, 4 authors
[2] doi:10.1523/eneuro.0008-26.2026 [code]
Movement Disorder Patients with Depression Have Altered Corticostriatal Alpha-Beta Power Response to Reward and Loss.
Journal: eNeuro
In common: Statistics and Machine Learning Toolbox, 3 references
[3] doi:10.1038/s41467-026-73947-8 [code]
Frontal cortex organization supporting audiovisual processing during naturalistic viewing.
Journal: Nature communications
In common: cognitive, 3 references
[4] doi:10.1371/journal.pbio.3003818 [code]
Human neuronal firing varies with the frequency of local field potential oscillations.
Journal: PLoS biology
In common: Statistics and Machine Learning Toolbox, 3 references
[5] doi:10.1371/journal.pbio.3003767 [code]
Ultrasound neuromodulation reveals distinct roles of the dorsal anterior cingulate cortex and anterior insula in learning.
Journal: PLoS biology
In common: Statistics and Machine Learning Toolbox, cognitive, 2 references
[6] doi:10.1038/s41598-026-49900-6 [code]
Global neural oscillations underlie performance variability and attentional state fluctuations in humans.
Journal: Scientific reports
In common: Statistics and Machine Learning Toolbox, cognitive, 2 references
[7] doi:10.1038/s41467-026-74331-2 [code]
Trial-by-trial fMRI-neurofeedback dissociates fusiform and occipital contributions to face detection and recognition.
Journal: Nature communications
In common: Statistics and Machine Learning Toolbox, 2 references
[8] doi:10.1162/imag.a.1268 [code]
Real-time fMRI-triggered experience sampling: A proof-of-concept study.
Journal: Imaging neuroscience (Cambridge, Mass.)
In common: Statistics and Machine Learning Toolbox, 2 references
[9] doi:10.7554/elife.110685 [code]
Sensory adaptation and pupil-linked arousal support flexible evidence accumulation during perceptual decision making.
Journal: eLife
In common: Statistics and Machine Learning Toolbox, cognitive, 2 references
[10] doi:10.1371/journal.pcbi.1014673 [code]
Modeling the influences of non-local connectomic projections on geometrically constrained cortical dynamics.
Journal: PLoS computational biology
In common: Statistics and Machine Learning Toolbox, 2 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.