OSCR

Contributions of insula and superior temporal sulcus to interpersonal guilt and responsibility in social decisions.

Code ↔ Paper

27 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 27 matches · 2 of them tie a paragraph to a whole file without given lines: weak matches, whose lines are not tinted
  1. [1] § Results › Behaviour › Momentary happiness: links to reward ↔ Code/master_behavAnalysis_revised.m, lines 1015 to 1143 · score 0.87 · Responsibility Redux model, partner_pRPE, likelihood ratio, social_pRPE, Responsibility model fitted, sRPE · Report a mismatch
  2. [2] § Results › Behaviour › Choices: risk preferences ↔ Code/bin/fittingUtilityFunction/fitCARAmodelToRiskyChoices.m, lines 1 to 67 · score 0.81 · constant absolute risk, risk averse, loss trials, decision maker, expected utility, risk aversion · Report a mismatch
  3. [3] § Results › Behaviour › Choices: risk preferences ↔ Code/bin/fittingUtilityFunction/fitCARAmodelToRiskyChoices2conds.m, lines 1 to 67 · score 0.81 · constant absolute risk, risk averse, loss trials, decision maker, expected utility, risk aversion · Report a mismatch
  4. [4] § Results › BOLD signal › Functional connectivity ↔ Code/master_fMRI_showResults.m, lines 247 to 302 · score 0.80 · left IFG, right IFG, left STS, left insula, connectivity changes, PPI · Report a mismatch
  5. [5] § Results › Behaviour › Momentary happiness: links to reward ↔ Code/bin/compModels/fit_happy_model_responsibility_redux.m, lines 1 to 94 · score 0.80 · ResponsibilityRedux, likelihood ratio, social_pRPE, sRPE, model fitted, AIC · Report a mismatch
  6. [6] § Materials and methods › Momentary happiness › Computational models of happiness variations ↔ Code/master_behavAnalysis_revised.m, lines 1015 to 1143 · score 0.79 · Responsibility Redux model, partner_pRPE, social_pRPE, sRPE, computational models, variations · Report a mismatch
  7. [7] § Materials and methods › Statistical analysis › Decisions › Estimating risk attitude 2: CARA model ↔ Code/bin/fittingUtilityFunction/fitCARAmodelToRiskyChoices.m, lines 1 to 67 · score 0.75 · exponential utility function, Constant Absolute Risk, Expected utility, risk aversion, preferences, model · Report a mismatch
  8. [8] § Materials and methods › Statistical analysis › Decisions › Estimating risk attitude 2: CARA model ↔ Code/bin/fittingUtilityFunction/fitCARAmodelToRiskyChoices2conds.m, lines 1 to 67 · score 0.75 · exponential utility function, Constant Absolute Risk, Expected utility, risk aversion, preferences, model · Report a mismatch
  9. [9] § Materials and methods › fMRI data analysis › PPI analysis ↔ Code/fMRI/c_gPPI.m, lines 18 to 49 · score 0.74 · PPI models, STS cluster, insula cluster, ran, seed, Solo · Report a mismatch
  10. [10] § Materials and methods › Decision task ↔ Code/socialDecisionRespo_fMRI.m, lines 52 to 108 · score 0.73 · ISI, loss, interval, position, mixed, Social · Report a mismatch
  11. [11] § Results › BOLD signal › Comparison with multivariate neural guilt signature () ↔ Code/fMRI/f_apply_YuKoban_guilt_signature_map.m, lines 37 to 57 · score 0.73 · dot product, guilt responses, Yu, signature, Cliff, Delta · Report a mismatch
  12. [12] § Materials and methods › Statistical analysis › Decisions › Generalized linear mixed logistic regression ↔ Code/master_behavAnalysis.m, lines 577 to 651 · score 0.69 · random slopes, random intercepts, explanatory, Cond, minus, mixed · Report a mismatch
  13. [13] § Materials and methods › Statistical analysis › Decisions › Generalized linear mixed logistic regression ↔ Code/master_behavAnalysis_revised.m, lines 588 to 636 · score 0.69 · random slopes, random intercepts, explanatory, Cond, minus, mixed · Report a mismatch
  14. [14] § Materials and methods › Momentary happiness › Computational models of happiness variations ↔ Code/bin/compModels/fit_happy_model_responsibility_redux.m, lines 1 to 94 · score 0.68 · social_pRPE, Responsibility Redux, sRPE, variance, gamma, CR · Report a mismatch
  15. [15] § Materials and methods › Likelihood ratio test ↔ Code/bin/compModels/fit_happy_model_basic.m, lines 1 to 94 · score 0.67 · Chi square distribution, likelihood ratio, L0, L1, freedom, model · Report a mismatch
  16. [16] § Materials and methods › fMRI data analysis › Fixed-effects models ↔ Code/master_behavAnalysis_revised.m, lines 1176 to 1302 · score 0.66 · sRPE, best fitting, risky choice, lottery outcome, coefficients, chosen · Report a mismatch
  17. [17] § Materials and methods › Statistical analysis › Decisions › Estimating risk attitude 1: risk premium ↔ Code/master_behavAnalysis.m, lines 114 to 156 · score 0.59 · indicate risk aversion, risk seeking, indifferent, lottery, fitting, model · Report a mismatch
  18. [18] § Materials and methods › Statistical analysis › Decisions › Estimating risk attitude 1: risk premium ↔ Code/master_behavAnalysis_revised.m, lines 114 to 156 · score 0.59 · indicate risk aversion, risk seeking, indifferent, lottery, fitting, model · Report a mismatch
  19. [19] § Materials and methods › fMRI data analysis › PPI analysis ↔ Code/master_fMRI_showResults.m, lines 247 to 302 · score 0.58 · left STS, left insula, PPI, seed, interaction, cluster · Report a mismatch
  20. [20] § Materials and methods › Parameter recovery › LMM regressions of happiness variations ↔ Code/fMRI/bb_onsetMaker.m, the whole file · a weak match · score 0.54 · risky social, happiness ratings, event, chosen, dummy, linear · Report a mismatch
  21. [21] § Materials and methods › Momentary happiness › Computational models of happiness variations ↔ Code/bin/CharnessRabinModel.m, the whole file · a weak match · score 0.54 · disadvantageous inequality, variations, partner, happiness, models · Report a mismatch
  22. [22] § Results › Behaviour › Momentary happiness: links to reward ↔ Code/master_behavAnalysis.m, lines 69 to 112 · score 0.54 · Guilt envy, Responsibility Redux, computational models, Rutledge, inequality, modelled · Report a mismatch
  23. [23] § Results › Behaviour › Momentary happiness: links to reward ↔ Code/master_behavAnalysis_revised.m, lines 69 to 112 · score 0.54 · Guilt envy, Responsibility Redux, computational models, Rutledge, inequality, modelled · Report a mismatch
  24. [24] § Materials and methods › Momentary happiness ↔ Code/socialDecisionRespo_fMRI.m, lines 495 to 561 · score 0.53 · button press, happiness ratings, cursor · Report a mismatch
  25. [25] § Results › Behaviour › Momentary happiness: effects of agency, responsibility, and guilt ↔ Code/master_behavAnalysis_revised.m, lines 350 to 433 · score 0.52 · partner outcome, lottery choices, agency, CI, guilt, Solo · Report a mismatch
  26. [26] § Results › BOLD signal › Brain regions engaged during receipt of outcomes ↔ Atlases_and_parcellations/2019_Wager_pain_pathways/scripts/create_pain_pathways_brainnetwork.m, lines 71 to 134 · score 0.51 · fine grained, anterior insula, gyrus, cluster · Report a mismatch
  27. [27] § Results › BOLD signal › Brain regions engaged during receipt of outcomes ↔ Atlases_and_parcellations/2024_CANLab_atlas/create_pain_pathways2024_brainnetwork.m, lines 99 to 168 · score 0.51 · fine grained, anterior insula, gyrus, cluster · Report a mismatch

Paper

Loaded from Europe PMC by your browser; OSCR does not store it: doi.org · Europe PMC

The paper is loaded when this pane is shown.

The authors' code

MATLAB · 1,385 lines · 68 KB · MIT · 7 matches

  1. %% Script to load and fit behavioural data from the Responsibility project experiments
  2. %% General setup
  3. clear; close all; clc
  4. owd = pwd;
  5. colors = niceColorsDark(3); % the colors for the 3 experimental conditions
  6. fontSize = 20;
  7. set(0,'defaultAxesFontSize',fontSize)
  8. addpath('fittingUtilityFunction')
  9. %% get datafiles
  10. % By hand:
  11. % During fMRI data:
  12. mfilepath = [fileparts(mfilename('fullpath')) filesep];
  13. addpath(genpath(mfilepath))
  14. % baseDir = '/Users/johannesschultz/sciebo/CURRENT WORK/Responsibility/';
  15. baseDir = [fileparts(fileparts(mfilepath)) filesep]; % should go 1 level higher than Code
  16. %% select which study(ies) to show
  17. study = {'Behav','fMRI','both (-> paper)'};
  18. % try selection = bttnChoiceDialog(study, 'Which dataset?', 3,'',[1 2 3]);
  19. % study = study{selection};
  20. % end
  21. study = 'Behav';
  22. study = 'fMRI';
  23. study = 'both (-> paper)';
  24. switch study
  25. case 'Behav'
  26. paperFigure = 0;
  27. datasets{1} = 'Behav';
  28. pathnames{1} = [baseDir 'BehaviouralData/BehaviourOnly']; % Behav only data
  29. case 'fMRI'
  30. paperFigure = 0;
  31. datasets{1} = 'fMRI';
  32. pathnames{1} = [baseDir 'BehaviouralData/fMRIstudy']; % fMRI expt data
  33. case 'both (-> paper)'
  34. paperFigure = 1;
  35. datasets{1} = 'Behav';
  36. datasets{2} = 'fMRI';
  37. pathnames{1} = [baseDir 'BehaviouralData/BehaviourOnly']; % Behav only data
  38. pathnames{2} = [baseDir 'BehaviouralData/fMRIstudy']; % fMRI expt data
  39. end
  40. %% Definition of condition names
  41. % conditionNames = {'You decide for both','Partner decides for both','You decide for yourself'};
  42. conditionNames = {'Social','Partner','Solo'};
  43. hap_typeNames_soc = {'high | high','high | low','low | high','low | low'}; % first participant, then partner
  44. hap_typeNames_nonsoc = {'high','low'};
  45. %% display options
  46. happyFigClassicOrDotPlotFlag = 2; % 0 -> no fig; 1 -> meansembar; 2 -> dotPlot. Choose 1 if want sequentialFiguresForTalk to be 1
  47. sequentialFiguresForTalk = 0;
  48. useDiffHappinessForSimplePlot = 1; % uses changes in subsequent happiness ratings for the simple behavioural happiness plot
  49. if paperFigure
  50. studyOffsets = [0 .45 0 0;0 0 0 0];
  51. paperFig1 = figure('name','Figure 2 - Choices','position',[5 5 1600 840]);
  52. decPanelPos = [.06 .1 .40 .3];
  53. riskPremPanelPos = [.55 .1 .16 .3];
  54. rhoPanelPos = [.79 .1 .16 .3];
  55. paperFig2 = figure('name','Figure 3 - Happiness','position',[5 5 1600 840]);
  56. happyRewardPanelPos1 = [.06 .13 .14 .26];
  57. happyRewardPanelPos2 = [.28 .13 .14 .26];
  58. happyPredPanelPos = [.50 .13 .14 .26];
  59. happyLotteryPanelPos = [.72 .13 .22 .26];
  60. end
  61. %% Happiness data analysis settings
  62. % Zscore the happiness results separately for each run
  63. zscoreSepEachRun = 'Yes';
  64. % % For the non-computational analysis, use only the trials directly before the happiness ratings?
  65. useAllTrialsForNonComp = 'no';
  66. % Computational modeling of happiness: do it or not?
  67. compModelling = 1;
  68. showIndivmodelNameFitFigs = 0;
  69. useTauForFMRIreg = 1;
  70. % Settings for computational modeling a la Rutledge
  71. % Use which modelName?
  72. if compModelling
  73. addpath('TDmodels')
  74. compModelName = {'None','Compare','ParamRecovery','Basic','InequalSimple','GuiltEnvy','otherRPEactPass','Responsibility','ResponsibilityRedux'};
  75. try selection = bttnChoiceDialog(compModelName,'',1,'Use which model name for computational analysis?',[3 3]);
  76. compModelName = compModelName{selection};
  77. end
  78. if strcmpi(compModelName,'None'), compModelling = 0; end
  79. else; compModelName = 'None';
  80. end
  81. whichTrials = 'all';
  82. % Create fMRI regressors?
  83. compToDoList = []; % nothing per default
  84. createfMRIreg = 'No'; % not per default
  85. if compModelling && ~strcmpi(compModelName,'Compare') && ~strcmpi(compModelName,'ParamRecovery') && ~strcmpi(compModelName,'None')
  86. createfMRIreg = {'Yes','No'};
  87. try selection = bttnChoiceDialog(createfMRIreg,'',1,'Create fMRI regressors?',[1 2]);
  88. createfMRIreg = createfMRIreg{selection};
  89. end
  90. end
  91. % Determine comp modelling to dos
  92. if compModelling, compToDoList = 1; end % default for comp modelling
  93. if compModelling && strcmpi(compModelName,'ParamRecovery'), compToDoList = 0; end % no real fitting needed, but loading of fitted data and simulations
  94. if strcmpi(createfMRIreg,'Yes')
  95. compToDoList = [1 2]; % modelling AND make fMRI regressors
  96. spm12 % put spm functions in path
  97. initialISIandSetupValues = dlmread([mfilepath 'bin/ResponsibilityExp_startTime.txt']);
  98. end
  99. %% Decision data analysis settings
  100. % Task: choice between safe option and lottery with 50% probability of high
  101. % vs. low outcome, in 2 contexts: decide for self only, or for self and
  102. % other.
  103. % Aim of analysis: calculate the certainty equivalents (CEs) of the
  104. % lotteries in the 2 choice conditions. CEs are defined as the amount of
  105. % reward for which the participant was choice-indifferent with regards to
  106. % said lotteries; the CE therefore indicates the subjective value of the
  107. % lottery in the currency of the safe reward. Lottery CEs larger than said
  108. % lotteries' objective expected value (EV) reflect risk-seeking behavior;
  109. % CEs smaller than the lotteries' EV indicate risk aversion.
  110. %
  111. % Then, estimate the contribution of utility to the subjective
  112. % values in both choice conditions.
  113. % analyseDecisions = {'Yes','No'};
  114. % try selection = bttnChoiceDialog(analyseDecisions,'',1,'Analyse decisions?',[1 2]);
  115. % analyseDecisions = analyseDecisions{selection};
  116. % end
  117. analyseDecisions = 'Yes'; % general problem: I have few trials and people are not always consistent. See table decTab for a subject's decisions as function of values of risky and safe options
  118. flag.fitBinnedEVdiffs = 1; % the first type of decision analysis I did, abandoned for better alternatives
  119. flag.fitBinnedSVdiffs = 1; % same, but based on subjective value. Only works if I have CARA rhos for each trialtype, so need flag.findCARArhoInSearchSpace=1
  120. flag.fitProbitFunction = 1; % fits the choices fine as function of EVrisky-Vsafe, but (1) is this a valid independent value? 2) I can't directly interpret the estimated parameters
  121. flag.findCARArhoInSearchSpace = 1; % this is the best so far: finds the risk aversion parameter that best explains the choices.
  122. rhoToTest = -.1:0.001:.1; % the values of rho to test
  123. flag.checkRiskAversionConsist = 1; % Only works if fitProbitFunctionFlag and findCARArhoInSearchSpaceFlag are both = 1
  124. binEdges = -50:20:50;
  125. choiceLMMs = {}; % we will collect choice probit linear mixed models in here
  126. trialTypeColors = niceColors70s(3);
  127. % Exponential utility function for the CARA model
  128. % NOTE: rho is a constant that represents the degree of risk preference
  129. % (rho>0 for risk aversion, rho=0 for risk-neutrality, and rho<0 for
  130. % risk-seeking). c is a commodity, i.e. something the decision-maker likes
  131. u_CARA = @(c, rho) (rho ~= 0) .* (1 - exp(-rho .* c)) ./ ( rho + (rho == 0) .* 0.000001) + ...
  132. (rho == 0) .* c;
  133. % ---- Expected utility function, which is the utility times the probability
  134. % c1 and c2 are the high and low amounts of the risky option
  135. EU_CARA = @(c1, c2, p1, rho) p1 .* u_CARA(c1, rho) + (1 - p1) .* u_CARA(c2, rho);
  136. %% ------------------------------------------------------------------------
  137. %
  138. % END SETTINGS, NOW GET DATA
  139. %
  140. % -------------------------------------------------------------------------
  141. % which dataset to use has been defined above
  142. for currentStudy = 1:length(datasets)
  143. pathname = pathnames{currentStudy};
  144. dataset = datasets{currentStudy};
  145. studyName = sprintf('Study %d', currentStudy);
  146. if strcmpi(study,'both (-> paper)') & paperFigure
  147. studyOffset = studyOffsets(currentStudy,:);
  148. end
  149. fprintf(1,' =========== Dataset %s ============ \n',dataset)
  150. clear R RR subjNumbTemp initialISIandSetup filesCell
  151. files = dir([pathname '/*.mat']); filesCell = {};
  152. for f = 1:length(files); filesCell{f} = files(f).name; end; files = filesCell;
  153. % if ~iscell(files); ff{1} = files; files = ff; clear ff; end % needed for Windows I think
  154. % sort or not?
  155. if length(files) > 1
  156. % sortOrNot = {'sort','don''t sort'};
  157. % try selection = bttnChoiceDialog(sortOrNot, 'Sort according to subject number or not?', '','',[1 2]);
  158. % sortOrNot = sortOrNot{selection};
  159. % end
  160. sortOrNot = 'sort';
  161. switch sortOrNot
  162. case 'sort'
  163. files = sortrows(char(files));
  164. case 'don''t sort'
  165. files = char(files);
  166. end
  167. else
  168. files = char(files);
  169. end
  170. % files = files(1:10,:);
  171. %% load data
  172. for f = 1:size(files,1)
  173. Raw = load([pathname filesep deblank(files(f,:))]);
  174. Raw.results(1).subjName = deblank(files(f,:));
  175. Raw.results(1).Ntrials = length(Raw.results);
  176. ii = findstr(Raw.results(1).subjName,'_sub');
  177. temp = Raw.results(1).subjName(ii+5:ii+7);
  178. if strcmpi(temp(1),'M') || strcmpi(temp(1),'W') % then it's from Julia's experiment
  179. temp2 = str2num(temp(2:end));
  180. if strcmpi(temp(1),'M')
  181. temp2 = 100 + temp2;
  182. elseif strcmpi(temp(1),'W')
  183. temp2 = 200 + temp2;
  184. end
  185. temp = temp2;
  186. end % then it's not Julia's experiment, we should have the number
  187. if isempty(temp)
  188. temp = Raw.results(1).subjName(ii(end-2)+1:ii(end-1)-1);
  189. end
  190. if ischar(temp); temp=str2num(temp); end
  191. for str_loop = 1:length(Raw.results)
  192. gl=[Raw.results.amountThisTrialSubject];
  193. Raw.results(str_loop).Agl_Abs=sum(gl(1:str_loop-1));
  194. riskchoices=Raw.results(str_loop).riskyOption;
  195. riskEV=(riskchoices*0.5);
  196. choicesEV=[riskEV Raw.results(str_loop).safeOption];
  197. minEV=min(choicesEV);
  198. Raw.results(str_loop).MinEV=minEV;
  199. if Raw.results(str_loop).play==1
  200. choiceEV=sum(riskchoices*0.5);
  201. Raw.results(str_loop).ChoiceEV=choiceEV;
  202. Raw.results(str_loop).Ch_diff=choiceEV-minEV;
  203. elseif Raw.results(str_loop).play==0
  204. choiceEV=Raw.results(str_loop).safeOption;
  205. Raw.results(str_loop).ChoiceEV=choiceEV;
  206. Raw.results(str_loop).Ch_diff=choiceEV-minEV;
  207. end
  208. Raw.results(str_loop).PE=(gl(str_loop)-choiceEV);
  209. end
  210. subjNumbers(f) = temp;
  211. R{f} = Raw.results;
  212. if strcmpi(zscoreSepEachRun,'Yes')
  213. % zscore happiness (separately for each run)
  214. happ = [R{f}.happiness];
  215. idx = find(~isnan(happ));
  216. happ = zscore(happ(idx));
  217. for i = 1:length(idx)
  218. R{f}(idx(i)).happiness = happ(i);
  219. end
  220. end
  221. end % files
  222. % combine results structures?
  223. clear initialISIandSetup
  224. if size(files,1) > 1
  225. combineOrNot = 'combine';
  226. switch combineOrNot
  227. case 'combine' % then decide how many files to group
  228. if strcmpi(dataset,'Behav'), N = 3; else; N = 2; end
  229. for g = 1:size(files,1) / N % number of groups
  230. idx = [1:N] + (g-1)*N;
  231. RR{g} = horzcat(R{idx});
  232. subjNumbTemp(g) = subjNumbers(idx(1));
  233. % if need to create fMRI regressors, load the initial ISI and setup time
  234. if strcmpi(createfMRIreg,'Yes')
  235. idx = find(initialISIandSetupValues(:,1,1) == subjNumbTemp(g));
  236. if isempty(idx)
  237. warning(sprintf('no ISI values found for subject %d',subjNumbTemp(g)));
  238. initialISIandSetup(g,:) = NaN;
  239. else
  240. initialISIandSetup(g,:) = initialISIandSetupValues(idx,2:end); % go to the correct run and pick its number
  241. end
  242. end
  243. end
  244. R = RR;
  245. subjNumbers = subjNumbTemp;
  246. case 'don''t combine' % nothing to do
  247. end
  248. else; error('No data files found')
  249. end
  250. %% If Study 2, I can choose to analyse data from all the people with fMRI data (44 subjects), or all the people with good fMRI data (40 subjects)
  251. % We scanned 44 people, and excluded 4 that moved too much. I will report
  252. % the behavioural data from 44 people, and the fMRI data from 40 people.
  253. if strcmpi(dataset,'fMRI')
  254. personsWithFMRIdata = [ 301 302 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 347 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349];
  255. % personsWithGoodfMRIdata = [ 301 302 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 347 334 335 336 337 338 339 340 ];
  256. subjNumbersOrig = subjNumbers;
  257. [subjNumbers,idx] = intersect(subjNumbers,personsWithFMRIdata);
  258. R = R(idx);
  259. end
  260. %% display number of subjects included:
  261. fprintf(1,' --- N subjects in this dataset: %d --- \n',length(subjNumbers))
  262. %% ------------------------------------------------------------------------
  263. %
  264. % GOT DATA, NOW COLLECT AND DISPLAY HAPPINESS DATA - ANALYSIS l.1165+
  265. %
  266. % -------------------------------------------------------------------------
  267. %% Get happiness ratings for simple analysis - LMM analysis further below
  268. clear happiness* hap_idx* decisions decisionsCounts
  269. for i = 1:length(R) % for each subject
  270. happinessTemp = [R{i}(:).happiness];
  271. if strcmpi(zscoreSepEachRun,'No')
  272. idx = find(~isnan(happinessTemp));
  273. happ = zscore(happinessTemp(idx));
  274. happinessTemp(idx) = happ;
  275. end
  276. % analysis of the behavioural data
  277. % get the happiness values for the different outcomes
  278. hap_whoWon_soc = [1 1;1 0;0 1;0 0]; % first subject, then partner
  279. hap_whoWon_nonsoc = [1;0]; % only subject
  280. subjectWon = [R{i}(:).subjectWon];
  281. partnerWon = [R{i}(:).partnerWon];
  282. conditions = [R{i}(:).condition];
  283. happiness = [R{i}(:).happiness];
  284. dhappiness = NaN(size(happiness)); dhappiness(~isnan(happiness)) = [0 diff(happiness(2:2:end))];
  285. % Use difference in happiness for analysis
  286. if useDiffHappinessForSimplePlot
  287. happiness = dhappiness;
  288. end
  289. hap_idx = {};
  290. for ii = 1:length(hap_typeNames_soc) % for all 4 outcomes
  291. for cc = 1:2 % social and partner conditions
  292. hap_idx{ii,cc} = find(subjectWon == hap_whoWon_soc(ii,1) & partnerWon == hap_whoWon_soc(ii,2) & conditions == cc);
  293. if strcmpi(useAllTrialsForNonComp,'yes')
  294. try happiness_soc(i,ii,cc) = nanmean([happiness(hap_idx{ii,cc}) happiness(hap_idx{ii,cc}-1)]); catch happiness_soc(i,ii,cc) = NaN; end
  295. else
  296. try happiness_soc(i,ii,cc) = nanmean([happiness(hap_idx{ii,cc})]); catch happiness_soc(i,ii,cc) = NaN; end
  297. end
  298. end
  299. end
  300. for ii = 1:length(hap_typeNames_nonsoc)
  301. hap_idx{ii,1} = find(subjectWon == hap_whoWon_nonsoc(ii) & conditions==3);
  302. if strcmpi(useAllTrialsForNonComp,'yes')
  303. try happiness_nonsoc(i,ii,1) = nanmean([happiness(hap_idx{ii,1}) happiness(hap_idx{ii,1}-1)]); catch happiness_nonsoc(i,ii,1) = NaN; end
  304. else
  305. try happiness_nonsoc(i,ii,1) = nanmean([happiness(hap_idx{ii,1})]); catch happiness_nonsoc(i,ii,1) = NaN; end
  306. end
  307. end
  308. end % for each subject
  309. %% Report happiness ratings
  310. if sequentialFiguresForTalk; figsToDo = 1:6; else; figsToDo = 6; end
  311. for ff = figsToDo % for the different stages of the figure
  312. happiness = NaN(length(R),4,3); % dimensions: subjects; outcome [high|high, high|low, low|high, low|low]; condition [solo, social, partner]
  313. happinessNonsoc = NaN(length(R),4,3); % same size, just for the controls
  314. switch ff
  315. case 1 % first stage: only background
  316. case 2 % second stage: only non-soc
  317. happinessNonsoc(:,2:3,1) = happiness_nonsoc;
  318. case 3 % only add win-win
  319. happinessNonsoc(:,2:3,1) = happiness_nonsoc;
  320. happiness(:,1,2:3) = happiness_soc(:,1,:);
  321. case 4 % add win-lose
  322. happinessNonsoc(:,2:3,1) = happiness_nonsoc;
  323. happiness(:,1:2,2:3) = happiness_soc(:,1:2,:);
  324. case 5 % add lose-win
  325. happinessNonsoc(:,2:3,1) = happiness_nonsoc;
  326. happiness(:,1:3,2:3) = happiness_soc(:,1:3,:);
  327. case 6 % add the remainder
  328. happinessNonsoc(:,2:3,1) = happiness_nonsoc;
  329. happiness(:,:,2:3) = happiness_soc;
  330. end
  331. if happyFigClassicOrDotPlotFlag == 1
  332. figure('name','Happiness','position',[324 378 746 420]);
  333. if i>1 % more than 1 subject
  334. [ll1] = meansembar(1:3,happiness,1,niceColorsWarm(4),14,.2,'CI'); drawnow
  335. hold on
  336. [ll2] = meansembar(1:3,happinessNonsoc,1,[0 0 0;1 1 1;.5 .5 .5;0 0 0],14,.2,'CI'); drawnow
  337. else
  338. bar(squeeze(happiness)'); drawnow
  339. end
  340. if ~sequentialFiguresForTalk; legend([ll1 ll2(2:3)],[hap_typeNames_soc hap_typeNames_nonsoc],'location','eastoutside'); end
  341. ylabel('Happiness (z-scored)')
  342. set(gca,'position',[0.1300 0.2167 0.6998 0.7083],'ylim',[-1 1],'xlim',[.5 3.5],'xtick',1:3,'xticklabel',conditionNames([3 1 2]))
  343. grid on; box off; drawnow
  344. end
  345. end
  346. % For each subject, measure the impact of agency on happiness after negative outcomes for the partner
  347. responsibilityEffect = nanmean(squeeze(happiness(:,[2 4],2)-happiness(:,[2 4],3)),2)
  348. guiltEffect = responsibilityEffect; subjNumb = subjNumbers'; Tg = table(subjNumb,guiltEffect);
  349. writetable(Tg,[mfilepath 'csv/' dataset ' - BehavGuiltEffect.csv']);
  350. % Print happiness values to paper figure
  351. if happyFigClassicOrDotPlotFlag == 2
  352. if paperFigure
  353. figure(paperFig2)
  354. ah1 = axes('position',happyLotteryPanelPos+studyOffset);
  355. else
  356. figure('name',[dataset ' Happiness ratings dotPlots'],'position',[322 427 552 295]); ah1 = gca;
  357. end
  358. % Show happiness figure with dotplots
  359. % as soon as partner loses, participants feel better if partner took the decision
  360. axes(ah1)
  361. hh = []; S = []; happiness2 = [];
  362. happiness2(:,:,1:4) = permute(happiness(:,[1 3 2 4],2:3),[1 3 2]);
  363. S.colors = niceColorsWarm2(3); S.colors = S.colors(2:3,:);
  364. S.errorType = 'CI';
  365. S.markersize = 4;
  366. S.y = happiness2;
  367. hh = dotPlot(S);
  368. set(gca,'ylim',[-3.5 3.5],'ytick',-3:1:3,'xlim',[.2 8.8],'xtick',[1.5:2:8],'xticklabel',{'High\newlineHigh','Low\newlineHigh','High\newlineLow','Low\newlineLow',})
  369. box on
  370. hold on
  371. % add stars for "guilt effect": contrasting low partner outcomes in Social and Partner
  372. plot([5 6],[-3 -3],'k','linewidth',2)
  373. plot([7 8],[-3 -3],'k','linewidth',2)
  374. if strcmpi(dataset,'Behav') % p values are < 0.001 and = 0.002
  375. t_hdle=text(5.5,-2.8,'***'); t_hdle.HorizontalAlignment='center'; t_hdle.FontSize=20;
  376. t_hdle=text(7.5,-2.8,'**'); t_hdle.HorizontalAlignment='center'; t_hdle.FontSize=20;
  377. elseif strcmpi(dataset,'fMRI') % p values are = 0.01 and < 0.001
  378. t_hdle=text(5.5,-2.8,'**'); t_hdle.HorizontalAlignment='center'; t_hdle.FontSize=20;
  379. t_hdle=text(7.5,-2.8,'***'); t_hdle.HorizontalAlignment='center'; t_hdle.FontSize=20;
  380. end
  381. legend([hh(1:2).mu],{'Social','Partner'});
  382. ylabel('\Delta Happiness [std]')
  383. xlabel('Outcome participant (top) and partner (bottom)')
  384. title([studyName ': Happiness after lottery choices'])
  385. end
  386. %% ------------------------------------------------------------------------
  387. %
  388. % NOW COLLECT, DISPLAY AND ANALYSE DECISIONS
  389. %
  390. % -------------------------------------------------------------------------
  391. %% Analyse decisions, but only for conditions 1 & 3, as an algorithm took decisions in condition 2
  392. if strcmpi(analyseDecisions,'Yes'); progressbar(0,0,'Decisions')
  393. EVdiff_str = {'EV_r_i_s_k_y - V_s_a_f_e'};
  394. Ntodo = length(R);
  395. for i = 1:Ntodo % for each subject
  396. conditions = [R{i}(:).condition];
  397. trialTypes = {'gain trials','mixed trials','loss trials'};
  398. for c = [1 3] % don't analyse computer decisions
  399. % ------ 0) Calculate basic variables ------
  400. idx_cond = find(conditions == c);
  401. Vsafe = [R{i}(idx_cond).safeOption]';
  402. temp = reshape([R{i}(idx_cond).riskyOption],2,[]);
  403. riskyHigh = temp(1,:)'; riskyLow = temp(2,:)';
  404. EVrisky = (riskyHigh + riskyLow) / 2;
  405. varRisky = riskyHigh - riskyLow;
  406. EVriskyMinusVsafe = EVrisky-Vsafe;
  407. chooseRisky = [R{i}(idx_cond).play]';
  408. choseSafe = 1-chooseRisky;
  409. % we sort the trials into gain, mixed, and loss trials, because we assume different risk preferences for them
  410. idx_gain = find(riskyLow >= 0 & Vsafe >= 0);
  411. idx_mixed = find(Vsafe == 0);
  412. idx_loss = find(riskyHigh <= 0 & Vsafe <= 0);
  413. trialType = []; trialType(idx_gain) = 1; trialType(idx_mixed) = 2; trialType(idx_loss) = 3; trialType = trialType';
  414. trialType_indices = {idx_gain,idx_mixed,idx_loss};
  415. % Make a table with the variables we need
  416. Tdec = table(trialType, riskyHigh, riskyLow, EVrisky, varRisky, Vsafe, EVriskyMinusVsafe, chooseRisky, choseSafe);
  417. Tdec_allS{i,c} = Tdec; % gather all the decision data tables
  418. % ------ 1) Fit decisions as function of SVrisky-Vsafe with cumulative Gaussian ------
  419. if showIndivmodelNameFitFigs
  420. figure('name',sprintf('Subject %d',subjNumbers(i)));
  421. end
  422. if flag.fitBinnedEVdiffs
  423. [~,binEdges,ee] = histcounts(EVriskyMinusVsafe,binEdges);
  424. for iii = 1:length(binEdges)-1
  425. decisions(i,iii,c) = nanmean(chooseRisky(ee==iii));
  426. decisionsCounts(i,iii,c) = length(chooseRisky(ee==iii));
  427. end
  428. binCenters = (binEdges(1:end-1)+binEdges(2:end))/2;
  429. if showIndivmodelNameFitFigs
  430. if length(vars)>1; subplot(2,2,v); end
  431. hold on
  432. fitPsychFunction_js(binCenters/10,decisions(i,:,c),'plotFlag',gca,'functType',functType,'lowerBounds',lowerBounds,'upperBounds',upperBounds,'showText',0,'plotDottedLines','none','color',colors(c,:),'linewidth',2);
  433. title(EVdiff_str)
  434. % ylabel('P(risky), \bar{x}\pm SEM','interpreter','tex')
  435. ylabel('P(risky) [M+-SEM]')
  436. grid on
  437. end
  438. end
  439. % ------ 2) Fit CARA model ------
  440. % now, new approach to model the choices people made.
  441. % We're using the constant absolute risk aversion (CARA) model to
  442. % obtain certainty equivalents for the risky options.
  443. if flag.findCARArhoInSearchSpace
  444. plotFlag = 0;
  445. for t = 1:length(trialTypes)
  446. idx = trialType_indices{t};
  447. CARA_rho(i,t,c) = findCARArhoInSearchSpace(riskyHigh(idx),riskyLow(idx),Vsafe(idx),chooseRisky(idx),rhoToTest,plotFlag);
  448. end
  449. CARA_rho_searchSpace(i,c) = findCARArhoInSearchSpace(riskyHigh,riskyLow,Vsafe,chooseRisky,rhoToTest,plotFlag);
  450. end
  451. % ------ 3) Fit probit function to model choices as function of difference in expected values between safe and risky:
  452. if flag.fitProbitFunction
  453. xForFit = -80:80; % delta EV (EVrisky - Vsafe) to use for display and calculation of risk premium
  454. yfit = {};
  455. [B,DEV,STATStemp] = glmfit(Tdec.EVriskyMinusVsafe,Tdec.chooseRisky,'binomial','link','probit');
  456. % Deviance test to see if this model fits better than one with just a constant term (see see https://ch.mathworks.com/help/stats/glmfit.html):
  457. [~,dev_noconstant] = glmfit(ones(size(Tdec.EVriskyMinusVsafe)),Tdec.chooseRisky,'binomial','link','probit','Constant','off');
  458. D = dev_noconstant - DEV; D = dev_noconstant - DEV; % D has a chi-square distribution with degrees of freedom equal to the difference in the number of estimated parameters in the model corresponding to DEV and the number of estimated parameters in the constant model.
  459. STATStemp.pModel = 1 - chi2cdf(D,length(B)-1); % Find the p-value for a deviance test.
  460. STATS_probitFitAllT(i,c) = STATStemp;
  461. yfit{1} = glmval(B,xForFit, 'probit');
  462. % Find 0-crossing point, which is a measure of the risk premium:
  463. [~,iii] = min((yfit{1}-.5).^2);
  464. riskPremiumProbitFit(i,c) = xForFit(iii);
  465. end
  466. drawnow
  467. % ------ 5) Calculate the SV of the risky option for each trial based
  468. % on CARA_rho, to see if choices are related to that now. Relate SV to happiness?
  469. if flag.findCARArhoInSearchSpace
  470. SVrisky = [];
  471. for t = 1:length(trialTypes)
  472. idx = Tdec.trialType == t;
  473. SVrisky(idx) = EU_CARA(Tdec.riskyHigh(idx),Tdec.riskyLow(idx),0.5,CARA_rho(i,t,c)); % subjective value of risky option under CARA given estimated rho
  474. end; SVrisky = SVrisky';
  475. Tdec.SVrisky = SVrisky;
  476. Tdec_allS{i,c}.SVrisky = SVrisky;
  477. SVdiff = Tdec.SVrisky-Tdec.Vsafe;
  478. Tdec.SVdiff = SVdiff;
  479. Tdec_allS{i,c}.SVdiff = SVdiff;
  480. end % flag.findCARArhoInSearchSpace
  481. % ------ 6) Fit decisions as function of SVrisky-SVsafe with cumulative Gaussian ------
  482. if flag.fitBinnedSVdiffs && ( flag.findCARArhoInSearchSpace )
  483. [~,binCenters,ee] = histcounts(SVdiff,binEdges);
  484. for iii = 1:length(binEdges)-1
  485. decisions(i,iii,c) = nanmean(chooseRisky(ee==iii));
  486. end
  487. binCenters = (binCenters(1:end-1)+binCenters(2:end))/2;
  488. end % flag.fitBinnedSVdiffs
  489. end % each experimental condition
  490. if showIndivmodelNameFitFigs; legend(conditionNames); end
  491. progressbar(i/Ntodo,0,'Decisions')
  492. end % each subject
  493. end % analyseDecisions
  494. %% Do participants choose on average the option with the higher EV?
  495. propRiskyChoicesIfEVdiffPos = [];
  496. for i = 1:Ntodo
  497. % first, define GLM design matrix
  498. X = [...
  499. Tdec_allS{i,1}.EVriskyMinusVsafe;...
  500. Tdec_allS{i,3}.EVriskyMinusVsafe...
  501. ];
  502. y = [Tdec_allS{i,1}.chooseRisky; Tdec_allS{i,3}.chooseRisky]; % risky choices
  503. propRiskyChoicesIfEVdiffPos(i) = mean([ y(X(:,1)>0); 1-y(X(:,1)<0) ]);
  504. end
  505. str = ttest_nice(propRiskyChoicesIfEVdiffPos-0.5);
  506. fprintf('Choices of option with higher EV: mean = %.1f, SD = %.1f, %s\n',mean(propRiskyChoicesIfEVdiffPos)*100,std(propRiskyChoicesIfEVdiffPos)*100,str)
  507. %% Check variations of CARA rho as a function of trialtype and expt. condition
  508. if flag.findCARArhoInSearchSpace
  509. disp('2-way ANOVA on CARA rho:')
  510. anova2_repmeas_autodesign(CARA_rho(:,:,[1 3]));
  511. disp('T-test on CARA rho obtained over all trials through search in space, comparing the 2 conditions:')
  512. ttest_nice(CARA_rho_searchSpace(:,1),CARA_rho_searchSpace(:,3));
  513. end
  514. %% Compare rho for self-for-both vs rho for self only
  515. figure('name',[dataset ' \rho across conditions (left=avg over trialtypes)'],'position',[221 240 815 345])
  516. rho = squeeze(mean(CARA_rho,2));
  517. subplot(1,2,1);
  518. regress_display(rho(:,1),rho(:,3),'regressType','robust ','inputNames',{'rho social','rho solo'},'axesHandle',gca);
  519. subplot(1,2,2);
  520. regress_display(makerow(CARA_rho(:,:,1)),makerow(CARA_rho(:,:,3)),'regressType','robust','inputNames',{'rho social','rho solo'},'axesHandle',gca);
  521. %% Fit generalized linear mixed-effects model to risky choices
  522. % Explanations here:
  523. % https://ch.mathworks.com/help/stats/generalized-linear-mixed-effects-models.html
  524. % https://ch.mathworks.com/help/stats/fit-a-generalized-linear-mixed-effects-model.html
  525. % 1) Make big table with data from all subjects
  526. Tdec = [];
  527. for i = 1:Ntodo
  528. temp1 = Tdec_allS{i,1}; % the self-for-both condition data
  529. temp1.subject = i * ones(size(temp1.chooseRisky));
  530. temp1.condition = ones(size(temp1.chooseRisky));
  531. temp2 = Tdec_allS{i,3}; % the self-only condition data
  532. temp2.subject = i * ones(size(temp2.chooseRisky));
  533. temp2.condition = 2 * ones(size(temp2.chooseRisky));
  534. Tdec = [Tdec; temp1; temp2];
  535. end
  536. % Mean-correct all terms first, to help interpret the coefficients.
  537. Tdec.condition = Tdec.condition-1;
  538. Tdec.EVdiffMC = ( Tdec.EVriskyMinusVsafe-mean(Tdec.EVriskyMinusVsafe) ); % !! do NOT change Euro cent into Euros
  539. Tdec.condMC = Tdec.condition-mean(Tdec.condition);
  540. Tdec.EVcond_int_MC = Tdec.condMC .* Tdec.EVdiffMC - mean(Tdec.condMC .* Tdec.EVdiffMC);
  541. % Write table out to verify model in R
  542. writetable(Tdec,[mfilepath 'csv/' dataset ' - Choices_singleTrialData.csv']);
  543. % 2) Make a simple linear mixed model with EVriskyMinusVsafe, condition and
  544. % their interaction as independent variables, subject as random term
  545. % factor, with random intercept.
  546. % NOTE June 2023: models with random slopes fit even better!
  547. % model = 'chooseRisky ~ 1 + EVdiffMC + condMC + EVcond_int_MC + (1 | subject)';
  548. % modelRS1 = 'chooseRisky ~ 1 + EVdiffMC + condMC + EVcond_int_MC + (1 + EVdiffMC | subject)';
  549. % modelRS2 = 'chooseRisky ~ 1 + EVdiffMC + condMC + EVcond_int_MC + (1 + EVdiffMC + condMC | subject)';
  550. model = 'chooseRisky ~ 1 + EVdiffMC * condMC + (1 + EVdiffMC + condMC | subject)';
  551. % 3) Fit a probit model
  552. disp('Fitting probit and linear probability models to Choice data...')
  553. glme = fitglme(Tdec,...
  554. model,...
  555. 'Distribution','Binomial','Link','probit','FitMethod','Laplace',...
  556. 'DummyVarCoding','effects');
  557. % 4) Fit a linear probability model, so that the coefficients can be better
  558. % interpreted
  559. lm = fitglme(Tdec,...
  560. model);
  561. % collect glme and lm for econ-style table
  562. choiceLMMs{currentStudy,1} = glme;
  563. choiceLMMs{currentStudy,2} = lm;
  564. %% 5) Make a figure with fitted data for the probit model
  565. %
  566. % MUPRED = PREDICT(GLME) computes a vector MUPRED of predictions of the
  567. % conditional mean of the response given the random effects at the
  568. % original predictors used to create GLME. MUPRED includes contributions
  569. % from both estimated fixed effects and approximate empirical Bayes
  570. % predictors (EBPs) of the random effects.
  571. %
  572. % MUPRED = PREDICT(GLME,T) uses predictor variables from the table T to
  573. % predict the conditional mean of the response. T must contain all of the
  574. % predictor variables used to create GLME.
  575. %
  576. % [MUPRED,MUCI] = PREDICT(...) also returns the two-column matrix MUCI
  577. % containing 95% pointwise confidence intervals for the predicted values.
  578. % The lower limits of the bounds are in column 1, and the upper limits
  579. % are in column 2.
  580. % Compute histograms of decisions at each EVdiff bin, for solo and social conditions
  581. clear hdle
  582. if paperFigure
  583. figure(paperFig1), axes('position',decPanelPos+studyOffset)
  584. % [hh,hhhh] = meansemplotWithDots(binCenters/100,decisions(:,:,[1 3])); hh(1).Visible = 'off'; hh(2).Visible = 'off'; hold on
  585. % colors = [0 0 .5; 0 0 0; .5 0 0]; % dark blue for solo and dark red for social
  586. colors = [.6 .6 1; 0 0 0; 1 .6 .6]; % dark blue for solo and dark red for social
  587. markers = '^ov'; % upper triangle for solo and lower triangle for social
  588. for c = [1 3]; for i=1:length(binCenters), [n,v]=hist(decisions(:,i,c)); keep=find(n);
  589. scatter(binCenters(i)*ones(length(keep),1),v(keep),n(keep)*10,colors(c,:),'filled',markers(c));
  590. hold on, end, end
  591. else
  592. figure('Name',[dataset ' GLME fit'],'position',[ 360 427 346 271]);
  593. end
  594. % Print probit-model fits to figure
  595. % Nsubj = length(subjNumbers);
  596. Nd = 100; % N datapoints to model
  597. EVdiffMC = linspace(-50,50,Nd)';
  598. subject = zeros(Nd,1);
  599. colors = [0 0 1;1 0 0];
  600. for c = 1:2 % both conditions
  601. condMC = -1*(c-1.5) * ones(Nd,1);
  602. Tnew = table(EVdiffMC,condMC,subject);
  603. x = EVdiffMC;
  604. [mupred,muci] = predict(glme,Tnew); hold on
  605. hdle(c,:) = errorarea(x,mupred,muci,colors(c,:));
  606. end
  607. xlabel([EVdiff_str{1} '[Euro cents]'])
  608. ylabel('{\it p} (risky)')
  609. set(gca,'xlim',[-50 50])
  610. title([studyName ': Choices'])
  611. legend(hdle(:,1),conditionNames([3 1]),'location','NorthWest');
  612. %% If I assessed risk aversion using both CARA and the 0-crossing of the fitted probit function, I can check whether the derived measures are related:
  613. if flag.checkRiskAversionConsist && flag.fitProbitFunction && flag.findCARArhoInSearchSpace
  614. % check correlation between horizontal deviation in the probit fit
  615. % and rho
  616. % riskPremiumProbitFit(abs(riskPremiumProbitFit)>50)=NaN;
  617. riskPrem = riskPremiumProbitFit / 100; % !! Transform Euro cent into Euro
  618. inputNames = {'\rho','Risk premium'};
  619. % regress_display(CARA_rho(:),riskPremiumProbitFit_clean(:))
  620. figure('name',[dataset ' Consistency risk aversion measurements'],'position',[221 240 815 345])
  621. cc = [1 3]; % conditions to report on
  622. for c = 1:length(cc)
  623. subplot(1,2,c);
  624. riskPrem_temp = riskPrem(:,cc(c));
  625. rho_temp = mean(CARA_rho(:,:,cc(c)),2);
  626. regress_display(rho_temp,riskPrem_temp,...
  627. 'axesHandle',gca,'inputNames',inputNames,'titlePrefix',conditionNames{cc(c)},'regressType','robust'); grid on
  628. end
  629. % Compare risk preference measure rho for Solo and Social:
  630. if paperFigure
  631. figure(paperFig1)
  632. else,
  633. figure('name',[dataset ' Risk preference across conditions'],'position',[360 399 546 299]);
  634. end
  635. facecolor = [.5 .5 .5]; withmdn = 0; style = 2;
  636. % Print estimated risk premium values to paper figure
  637. if paperFigure, figure(paperFig1), axes('position',riskPremPanelPos+studyOffset), else, subplot(1,2,2); end
  638. riskPrem_temp = riskPrem; riskPrem_temp(abs(riskPrem_temp)>.7) = 0;
  639. % hh = distributionPlot(riskPrem_temp(:,[3 1]),'color',[.8 .8 .8],'showMM',4); hold on;
  640. % hh{2}(1).LineWidth=2; hh{2}(2).LineWidth=2; hh{2}(1).Marker='.';
  641. violin(1,riskPrem_temp(:,3),'facecolor',facecolor,'withmdn',withmdn,'style',style,'scaling',1); hold on
  642. violin(2,riskPrem_temp(:,1),'facecolor',facecolor,'withmdn',withmdn,'style',style,'scaling',1); hold on
  643. % hh{2}(1).Marker='o'; hh{2}(1).MarkerFaceColor=[1 0 0];
  644. % hh{2}(2).Marker='^'; hh{2}(2).MarkerFaceColor=[0 1 0];
  645. plot(riskPrem_temp(:,[3 1])','k'); set(gca,'xtick',[1 2],'xticklabel',conditionNames([3 1]),'xlim',[.5 2.5]);
  646. m = mean(riskPrem_temp(:,[3 1]));
  647. CI = ci_t(riskPrem_temp(:,[3 1]),95); % find 95% confidence intervals for the mean, assuming normally-distributed data
  648. errL = m - CI(1,:);
  649. errH = CI(2,:) - m;
  650. % previously: err = std(riskPrem_temp(:,[3 1]))/sqrt(size(riskPrem_temp,1))
  651. errorbar([1 2],m,errL,errH,'.-r','linewidth',2);
  652. title([studyName ': Risk premium'])%,'position',[1 0.0027473])
  653. ylabel([EVdiff_str{1} ' [Euro]'])
  654. ttest_nice(riskPrem_temp(:,1),riskPrem_temp(:,3),'paired',1);
  655. % Print estimated risk aversion parameter rho values to paper figure
  656. if paperFigure, figure(paperFig1), axes('position',rhoPanelPos+studyOffset), else,
  657. subplot(1,2,1);
  658. end
  659. violin(1,rho(:,3),'facecolor',facecolor,'withmdn',withmdn,'style',style,'scaling',1); hold on
  660. violin(2,rho(:,1),'facecolor',facecolor,'withmdn',withmdn,'style',style,'scaling',1); hold on
  661. plot(rho(:,[3 1])','k'); set(gca,'xtick',[1 2],'xticklabel',conditionNames([3 1]),'xlim',[.5 2.5])
  662. m = mean(rho(:,[3 1]));
  663. CI = ci_t(rho(:,[3 1]),95); % find 95% confidence intervals for the mean, assuming normally-distributed data
  664. errL = m - CI(1,:);
  665. errH = CI(2,:) - m;
  666. % previously: errorbar([1 2],mean(rho(:,[3 1])),std(rho(:,[3 1]))/sqrt(size(rho,1)),'.-r','linewidth',2);
  667. errorbar([1 2],m,errL,errH,'.-r','linewidth',2);
  668. title([studyName ': \rho'],'fontsize',24)
  669. ylabel('risk seeking \leftrightarrow risk averse')
  670. ttest_nice(rho(:,1),rho(:,3),'paired',1);
  671. end
  672. %% ------------------------------------------------------------------------
  673. %
  674. % ANALYSED DECISIONS, NOW COMPUTATIONAL MODELING OF HAPPINESS
  675. %
  676. % -------------------------------------------------------------------------
  677. %% Rutledge-like computational analysis
  678. for i = 1:length(R) % for each subject
  679. % first, prepare the variables for the computational analysis
  680. choseSafe = [R{i}(:).play];
  681. % choseGamble = 1-choseSafe;
  682. try, nonsocialTrial = ([R{i}(:).condition] == 3);
  683. catch; nonsocialTrial = ~isnan([R{i}(:).amountThisTrialPartner]); end
  684. try, socialActive = ([R{i}(:).condition] == 1);
  685. catch; socialActive = [R{i}.condition]; end
  686. try, socialPassive = ([R{i}(:).condition] == 2); end
  687. amountReceivedBySubject = [R{i}.amountThisTrialSubject];
  688. CR = amountReceivedBySubject.*choseSafe;
  689. EV = mean(reshape([R{i}(:).riskyOption],2,[])) .* (1-choseSafe);
  690. RPE = EV-amountReceivedBySubject.*(1-choseSafe);
  691. happinessTemp = [R{i}(:).happiness];
  692. if strcmpi(zscoreSepEachRun,'No')
  693. idx = find(~isnan(happinessTemp));
  694. happ = zscore(happinessTemp(idx));
  695. happinessTemp(idx) = happ;
  696. end
  697. matrix = zeros(length(R{i}),20);
  698. matrix(:,1) = [R{i}(:).condition];
  699. matrix(:,3) = [R{i}(:).safeOption];
  700. matrix(:,4:5) = reshape([R{i}(:).riskyOption],2,[])';
  701. matrix(:,7) = [R{i}(:).play];
  702. matrix(:,8) = [R{i}(:).amountThisTrialSubject];
  703. matrix(:,10) = happinessTemp;
  704. matrix(:,13) = isnan([R{i}(:).amountThisTrialPartner])+1;
  705. matrix(:,16) = [R{i}(:).amountThisTrialPartner];
  706. matrix(:,17) = [R{i}(:).Agl_Abs];
  707. matrix(:,18)= [R{i}(:).MinEV];
  708. matrix(:,19)= [R{i}(:).ChoiceEV];
  709. matrix(:,20)= [R{i}(:).Ch_diff];
  710. matrix(:,21) = [R{i}(:).PE];
  711. switch whichTrials
  712. case 'all'
  713. idx = 1:size(matrix,1);
  714. case 'social'
  715. idx = find(~nonsocialTrial);
  716. case 'non-social'
  717. idx = find(nonsocialTrial);
  718. case 'social-active'
  719. idx = find(socialActive);
  720. case 'social-passive'
  721. idx = find(socialPassive);
  722. case 'social-passive and non-social'
  723. idx = [find(socialPassive) find(nonsocialTrial)];
  724. case 'social-active and non-social'
  725. idx = [find(socialActive) find(nonsocialTrial)];
  726. end
  727. matrix = matrix(idx,:);
  728. alldata(i).socdata{1} = matrix;
  729. % alldata(i).Ntrials = [R{i}.Ntrials];
  730. end % subject
  731. %% Run Rutledge-like computational analysis
  732. clear compResults mtxs ff
  733. for whatToDo = compToDoList % 1 = fit the data, 2 = create fMRI regressors; 0 = parameter recovery; done after having fitted real data.
  734. disp('Fitting computational models for participant number: ')
  735. % first, fit behavioural data, then create fMRI regressors if desired
  736. for n=1:length(alldata), % n subjects
  737. fprintf(1,'%d,',n);
  738. for m=1:length(alldata(n).socdata), % m runs?
  739. % temp is the data, rows are trials, columns are variables:
  740. % 3: safe values
  741. % 4 to 5: risky values
  742. % 7: 1 if gambled, 0 if chose safe option
  743. % 8: reward obtained by self
  744. % 10: happiness score
  745. % 13: 1 if participant chose, 2 if other person chose
  746. % 16: other person reward
  747. % 17: Agl_Abs
  748. % 18: MinEV
  749. % 19: ChoiceEV
  750. % 20: Ch_diff
  751. % 21: PE
  752. eval(sprintf('temp = alldata(%d).socdata{%d};',n,m)); temp(1,10:12)=nan; %collect matrices and toss first rating
  753. t2 = temp(:,10); rawhappy = t2(~isnan(t2)); happyind = find(~isnan(t2)); temp(isnan(temp(:,16)),16)=0; %other reward=0 when solo trial
  754. nrate=length(rawhappy); ntrial=size(temp,1); x=zeros(nrate,ntrial);
  755. evmtx=x; certainmtx=x; rpemtx=x; rewardmtx=x; othercertainmtx=x; otherrewardmtx=x; otherrpemtx=x; ipemtx=x; envymtx=x; guiltmtx=x; notenvymtx=x; notguiltmtx=x; youchosemtx=x; theychosemtx=x;
  756. Agl_Absmtx=x; MinEVmtx=x; ChoiceEVmtx=x; Ch_diffmtx=x; PEmtx=x;
  757. switch whatToDo
  758. case 0 % parameter recovery; same trials as for fitting
  759. trialsToFit = happyind;
  760. case 1 % fit the data
  761. trialsToFit = happyind;
  762. case 2 % create fMRI regressors
  763. trialsToFit = 1:ntrial;
  764. end
  765. for q = 1:length(trialsToFit)
  766. temp2 = temp(1:trialsToFit(q),:); %clip out all trials up to rating
  767. tempev = mean(temp2(:,4:5),2) .* double(temp2(:,7)==1); %0 if no gamble or error, ev if gambled
  768. temprpe = temp2(:,8) .* double(temp2(:,7)==1) - tempev; %0 if no gamble or error, rpe if gambled
  769. tempreward = temp2(:,8) .* double(temp2(:,7)==1); % gamble rewards (0 if chose certain)
  770. tempcertain = temp2(:,3) .* double(temp2(:,7)==0); % 0 if gambled, otherwise certain amount
  771. tempothercertain = temp2(:,16) .* double(temp2(:,7)==0) .* double(temp2(:,13)==2); % other reward if no gamble
  772. tempotherreward = temp2(:,16) .* double(temp2(:,7)==1) .* double(temp2(:,13)==2); % other reward if gamble
  773. tempotherrpe = temp2(:,16) .* double(temp2(:,7)==1) - tempev; % rpe for other
  774. tempipe = (sign(temprpe)) .* double(temp2(:,1)<3) .* (tempotherreward-tempev); %sign or your rpe x sign of theirs
  775. tempenvy = (sign(temprpe)<0) .* double(temp2(:,1)<3) .* (tempotherreward-tempreward); %you lost and they got this much more than you
  776. tempguilt = (sign(temprpe)>0) .* double(temp2(:,1)<3) .* (tempreward-tempotherreward); %you won and you got this much more than them
  777. tempnotenvy = (sign(temprpe)<0) .* double(temp2(:,1)<3) .* double(~(tempotherreward-tempreward)); %you lost and they also lost dummy
  778. tempnotguilt = (sign(temprpe)>0) .* double(temp2(:,1)<3) .* double(~(tempreward-tempotherreward)); %you won and they also won dummy
  779. tempyouchose = double(temp2(:,13)==1);
  780. temptheychose = double(temp2(:,13)==2);
  781. evmtx(q,1:length(tempev)) = fliplr(transpose(tempev)) / 100; %convert to ?
  782. certainmtx(q,1:length(tempcertain)) = fliplr(transpose(tempcertain)) / 100;
  783. rpemtx(q,1:length(temprpe)) = fliplr(transpose(temprpe)) / 100;
  784. rewardmtx(q,1:length(tempreward)) = fliplr(transpose(tempreward)) / 100;
  785. ipemtx(q,1:length(tempipe)) = fliplr(transpose(tempipe)) / 100;
  786. othercertainmtx(q,1:length(tempothercertain)) = fliplr(transpose(tempothercertain)) / 100;
  787. otherrewardmtx(q,1:length(tempotherreward)) = fliplr(transpose(tempotherreward)) / 100;
  788. otherrpemtx(q,1:length(temprpe)) = fliplr(transpose(tempotherrpe)) / 100;
  789. envymtx(q,1:length(tempenvy)) = fliplr(transpose(tempenvy)) / 100;
  790. guiltmtx(q,1:length(tempguilt)) = fliplr(transpose(tempguilt)) / 100;
  791. notenvymtx(q,1:length(tempnotenvy)) = fliplr(transpose(tempnotenvy)); %dummy
  792. notguiltmtx(q,1:length(tempnotguilt)) = fliplr(transpose(tempnotguilt)); %dummy
  793. youchosemtx(q,1:length(tempyouchose)) = fliplr(transpose(tempyouchose)); %1 if you chose
  794. theychosemtx(q,1:length(temptheychose)) = fliplr(transpose(temptheychose)); %1 if they chose
  795. Agl_Abs=double(temp2(:,17));
  796. MinEV=double(temp2(:,18));
  797. ChoiceEV=double(temp2(:,19));
  798. Ch_diff=double(temp2(:,20));
  799. PE=double(temp2(:,21));
  800. Agl_Absmtx(q,1:length(Agl_Abs)) = fliplr(transpose(Agl_Abs)) / 100; %convert to ?
  801. MinEVmtx(q,1:length(MinEV)) = fliplr(transpose(MinEV)) / 100; %convert to ?
  802. ChoiceEVmtx(q,1:length(ChoiceEV)) = fliplr(transpose(ChoiceEV)) / 100; %convert to ?
  803. Ch_diffmtx(q,1:length(Ch_diff)) = fliplr(transpose(Ch_diff)) / 100; %convert to ?
  804. PEmtx(q,1:length(PE)) = fliplr(transpose(PE)) / 100; %convert to ?
  805. end;
  806. clear mtx; mtx.certainmtx=single(certainmtx); mtx.evmtx=single(evmtx); mtx.rpemtx=single(rpemtx); mtx.rewardmtx=single(rewardmtx);
  807. mtx.ipemtx=single(ipemtx); mtx.othercertainmtx=single(othercertainmtx); mtx.otherrewardmtx=single(otherrewardmtx); mtx.otherrpemtx=single(otherrpemtx);
  808. mtx.envymtx=single(envymtx); mtx.guiltmtx=single(guiltmtx); mtx.youchosemtx=single(youchosemtx); mtx.theychosemtx=single(theychosemtx);
  809. mtx.notenvymtx=single(notenvymtx); mtx.notguiltmtx=single(notguiltmtx);
  810. mtx.Agl_Abs=single(Agl_Absmtx); mtx.MinEV=single(MinEVmtx); mtx.PE=single(PEmtx);
  811. mtx.ChoiceEV=single(ChoiceEVmtx); mtx.Ch_diff=single(Ch_diffmtx);
  812. mtx.conds=temp(1:trialsToFit(end),1);
  813. eval(sprintf('alldata(%d).mtx{%d}=mtx;',n,m));
  814. eval(sprintf('alldata(%d).rawhappy{%d}=rawhappy;',n,m));
  815. eval(sprintf('temp = alldata(%d).socdata{%d};',n,m)); temp(1,10:12)=nan; %toss first rating
  816. t2 = temp(:,10); zhappy = t2(~isnan(t2));
  817. eval(sprintf('alldata(%d).zhappy{%d}=zhappy;',n,m))
  818. % do computational modelling
  819. if whatToDo == 1 %2 & strcmpi(createfMRIreg,'Yes')
  820. if strcmpi(compModelName,'ActPass')
  821. compResults(n,1) = fit_happy_model_inequalityActPass(mtx,zhappy,NaN);
  822. elseif strcmpi(compModelName,'otherRPEactPass')
  823. compResults(n,1) = fit_happy_model_otherRPEactPass(mtx,zhappy,NaN);
  824. elseif strcmpi(compModelName,'GuiltEnvy')
  825. compResults(n,1) = fit_happy_model_guiltenvy(mtx,zhappy,NaN);
  826. elseif strcmpi(compModelName,'InequalSimple')
  827. compResults(n,1) = fit_happy_model_inequalitySimple(mtx,zhappy,NaN);
  828. elseif strcmpi(compModelName,'Basic')
  829. compResults(n,1) = fit_happy_model_basic(mtx,zhappy,NaN);
  830. elseif strcmpi(compModelName,'Responsibility')
  831. compResults(n,1) = fit_happy_model_responsibility(mtx,zhappy,NaN);
  832. elseif strcmpi(compModelName,'ResponsibilityRedux')
  833. compResults(n,1) = fit_happy_model_responsibility_redux(mtx,zhappy,NaN);
  834. elseif strcmpi(compModelName,'GuiltEnvy+UtilityFunction')
  835. compResults(n,1) = fit_happy_model_guiltenvy_utl(mtx,zhappy,NaN);
  836. elseif strcmpi(compModelName,'Compare')
  837. compResults(n,1) = fit_happy_model_basic(mtx,zhappy,NaN);
  838. compResults(n,2) = fit_happy_model_inequalitySimple(mtx,zhappy,NaN);
  839. compResults(n,3) = fit_happy_model_guiltenvy(mtx,zhappy,NaN);
  840. compResults(n,4) = fit_happy_model_responsibility(mtx,zhappy,NaN);
  841. compResults(n,5) = fit_happy_model_responsibility_redux(mtx,zhappy,NaN);
  842. end
  843. if showIndivmodelNameFitFigs
  844. for m = 1:size(compResults,2)
  845. figure;
  846. subplot(2,1,1)
  847. plot(zhappy,'b');
  848. hold on; plot(compResults(n,m).happypred,'r')
  849. dataNames = {'happiness','predicted happiness'};
  850. legend(dataNames);
  851. title([R{n}(1).subjName ' ' whichTrials], 'interpreter','none')
  852. ylabel(sprintf('R2 = %.2f',compResults(n,m).r2));
  853. subplot(2,1,2)
  854. bar(compResults(n,m).b)
  855. xlabel_oblique(compResults(n,m).paramNames)
  856. title([compResults(n,m).compModelName ' - parameters'], 'interpreter','none')
  857. drawnow
  858. end
  859. end
  860. % regress_display(zhappy,results(n).happypred,'inputNames',dataNames)
  861. end % whatToDo == 1
  862. % use tau to create fMRI regressors if desired
  863. if whatToDo == 2 && strcmpi(createfMRIreg,'Yes')
  864. idx = strmatch('decay',compResults(n,1).paramNames); % look for the decay parameter
  865. tau = compResults(n,1).b(idx); %decay constant
  866. if useTauForFMRIreg
  867. [fMRIregressors,fMRIregressor_names] = create_fMRIregressors_otherRPEactPass(tau,mtx,R{n},initialISIandSetup(n,:)); % use results of the fit to create fMRI regressors
  868. % [fMRIregressors,fMRIregressor_names] = create_fMRIregressors(tau,mtx,R{n},initialISIandSetup(n,:)); % use results of the fit to create fMRI regressors
  869. else
  870. [fMRIregressors,fMRIregressor_names] = create_fMRIregressors(0,mtx,R{n},initialISIandSetup(n,:)); % use results of the fit to create fMRI regressors
  871. end
  872. q=R{n}(1).subjName; us = findstr(q,'_');
  873. subjNo = q(us(5)+1:us(6)-1);
  874. if double(subjNo(1)) > 57
  875. subjNo = q(us(4)+1:us(5)-1);
  876. end
  877. for ses = 1:length(fMRIregressors)
  878. dlmwrite(['fMRIregressors_' subjNo '_' num2str(ses) '.txt'],fMRIregressors{ses})
  879. figure; imagesc(fMRIregressors{ses});
  880. set(gca,'xtick',[1:size(fMRIregressors{ses},2)]+.4)
  881. xlabel_oblique(fMRIregressor_names(1:size(fMRIregressors{ses},2)),15,12,1);
  882. set(gca,'position',[0.1300 0.1800 0.7750 0.7450])
  883. ylabel('Trial from start of run1')
  884. title(['fMRIregressors for subject ' subjNo ', run ' num2str(ses)])
  885. end % fMRI ses
  886. end % fMRI regressors
  887. end % runs
  888. mtxs{n} = mtx;
  889. zhappyAll(n).zhappy = zhappy;
  890. subjectNos(n).subjectNo = n*ones(length(zhappy),1);
  891. end % subjects
  892. end % whatToDo
  893. fprintf(1,'done\n');
  894. % Make table with computational results, write it out
  895. if compModelling && whatToDo ~= 0 % so no parameter recovery
  896. for m = 1:size(compResults,2)
  897. predictedHappiness = vertcat(compResults(:,m).happypred);
  898. realHappiness = vertcat(zhappyAll(:).zhappy);
  899. subjectNo = vertcat(subjectNos(:).subjectNo);
  900. ThapComp = table(realHappiness,predictedHappiness,subjectNo);
  901. writetable(ThapComp,[mfilepath 'csv/' dataset ' - Happiness and happiness predicted by ' compResults(1,m).modelName '.csv'])
  902. end
  903. end
  904. if ~compModelling || whatToDo == 0 % then read already computed predicted happiness values
  905. ThapComp = readtable([mfilepath 'csv/' dataset ' - Happiness and happiness predicted by ResponsibilityRedux.csv']);
  906. end
  907. % Show fit quality of model
  908. if strcmpi(study,'both (-> paper)')
  909. figure(paperFig2)
  910. axes('position',happyPredPanelPos+studyOffset);
  911. else
  912. figure
  913. end
  914. regress_display(ThapComp.realHappiness,ThapComp.predictedHappiness,'axesHandle',gca,'inputNames',{'Reported \Delta happiness [std]','Pred. \Delta happiness [std]'},'regressType','robust')
  915. title([studyName ': Fit of comp. model'])
  916. %% Show results of computational modelling
  917. try disp('Individual fits of the models tested (R2):')
  918. disp(reshape([compResults.r2],n,[])); end
  919. if exist('compResults','var')
  920. % combine the results in a matrix
  921. clear resMtx
  922. f1 = figure('name','RL model parameters','position',[440 139 560 659]);
  923. for m = 1:size(compResults,2)
  924. for n = 1:size(compResults,1)
  925. resMtx{m}(n,:) = [subjNumbers(n) compResults(n,m).r2 compResults(n,m).r2adj compResults(n,m).aic compResults(n,m).bic compResults(n,m).b]; % with aic and bic
  926. end
  927. resMtxVarnames{m} = [{'Subject number', 'R2', 'R2adj', 'aic', 'bic'}, compResults(n,m).paramNames];
  928. % display
  929. if length(alldata) > 1
  930. % group results
  931. figure(f1); subplot(size(compResults,2),1,m)
  932. showWhat = [6:size(resMtx{m},2)];
  933. plot([.5 length(showWhat)+.5],[0 0],'k')
  934. try violinDots(resMtx{m}(:,showWhat));
  935. catch, meansemplot(resMtx{m}(:,showWhat));
  936. end
  937. try xlabel_oblique(resMtxVarnames{m}(showWhat)); end
  938. title(compResults(1,m).modelName)
  939. % individual variation
  940. figure('name',['Individual variation of parameters for compModelName ' compResults(1,m).modelName]);
  941. try
  942. subplot(4,1,1)
  943. bar(resMtx{m}(:,2)); title('R2')
  944. subplot(4,1,2)
  945. bar(responsibilityEffect); title('Responsibility effect: Effect of self - other''s decision on happiness in other loss trials')
  946. subplot(4,1,3)
  947. bar(resMtx{m}(:,end-1)); title(compResults(n,m).paramNames(end-1))
  948. subplot(4,1,4)
  949. bar(resMtx{m}(:,end)); title(compResults(n,m).paramNames(end))
  950. catch
  951. subplot(4,1,1)
  952. plot(resMtx{m}(:,2)); title('R2')
  953. subplot(4,1,2)
  954. plot(responsibilityEffect); title('Responsibility effect: Effect of self - other''s decision on happiness in other loss trials')
  955. subplot(4,1,3)
  956. plot(resMtx{m}(:,end-1)); title(compResults(n,m).paramNames(end-1))
  957. subplot(4,1,4)
  958. plot(resMtx{m}(:,end)); title(compResults(n,m).paramNames(end))
  959. end
  960. % write out data to analyse in SPSS or such
  961. dlmwrite(['ComputFitData_' compResults(n,m).modelName '.csv'],resMtx{m})
  962. end
  963. disp('Mean and median R2:')
  964. disp([mean(resMtx{m}(:,2)) median(resMtx{m}(:,2))])
  965. end
  966. else; disp('No computational modelling done')
  967. end
  968. if strcmpi(compModelName,'compare') % then make a table showing the comparison results and do some stats on the parameters
  969. modelNames = {compResults(1,:).modelName};
  970. Nmodels = length(modelNames);
  971. figure('name','RL model comparison','position',[954 480 446 325])
  972. for m = 1:Nmodels
  973. aic(m) = sum(resMtx{m}(:,3));
  974. bic(m) = sum(resMtx{m}(:,4));
  975. end
  976. subplot(2,1,1); bar(bic); title('BIC'); set(gca,'xtick',1:Nmodels)
  977. subplot(2,1,2); bar(aic); title('AIC'); set(gca,'xtick',1:Nmodels,'xticklabel',modelNames)
  978. % do statistics on the model parameters:
  979. disp('Testing if the model parameters CR, EV, RPE and decay are above 0, and if EV < RPE:')
  980. for m = 1:Nmodels; disp(modelNames{m});
  981. for tt = 5:8; ttest_nice(resMtx{m}(:,tt)); end;
  982. ttest_nice(resMtx{m}(:,6),resMtx{m}(:,7));
  983. end
  984. % save the calculated model parameters for each model, and do stats on the Responsibilty model parameters:
  985. for m = 1:Nmodels
  986. params = vertcat(compResults(:,m).b);
  987. paramNames = compResults(1,m).paramNames;
  988. ParamFitTable = array2table(params,'VariableNames',paramNames);
  989. writetable(ParamFitTable,[mfilepath 'csv/' dataset ' - ' modelNames{m} ' - fittedParameters.csv']);
  990. % stats on the Responsibiltiy model parameters:
  991. if m == 4 % the Responsibility model
  992. disp('Comparing the model parameters sRPE > social_pRPE:')
  993. str = signrank_nice(ParamFitTable.sRPE, ParamFitTable.social_pRPE); disp(str)
  994. disp('Comparing the model parameters social_pRPE > 0:')
  995. str = signrank_nice(ParamFitTable.social_pRPE); disp(str)
  996. disp('Comparing the model parameters social_pRPE > partner_pRPE:')
  997. str = signrank_nice(ParamFitTable.social_pRPE, ParamFitTable.partner_pRPE); disp(str)
  998. elseif m == 5 % the ResponsibilityRedux model
  999. disp('Comparing the model parameters sRPE > social_pRPE:')
  1000. str = signrank_nice(ParamFitTable.sRPE, ParamFitTable.social_pRPE); disp(str)
  1001. disp('Comparing the model parameters social_pRPE > 0:')
  1002. str = signrank_nice(ParamFitTable.social_pRPE); disp(str)
  1003. end
  1004. end
  1005. % make paper table
  1006. varIdxToReport = [2 3 5 4]; % R2, adjR2, BIC, AIC
  1007. for m = 1:length(modelNames)
  1008. dataForTable(m,:) = [mean(resMtx{m}(:,2)) mean(resMtx{m}(:,3)) round(sum(resMtx{m}(:,5))) round(sum(resMtx{m}(:,4)))];
  1009. end
  1010. Tcomp = array2table(dataForTable,'VariableNames', resMtxVarnames{1}(varIdxToReport));
  1011. Tcomp.modelName = modelNames';
  1012. writetable(Tcomp,[mfilepath 'csv/' dataset ' - computational models of happiness.xlsx']);
  1013. % do some stats to compare the model fits
  1014. disp('Results of likelihood ratio test comparing the different models:')
  1015. % run likelihood ratio tests (LR = -2 * ln(L0/L1) = -2 * (logL1 - logL0)), follows Chi-squared distribution, with DF = diff in N params:
  1016. % See for example here: https://www.geeksforgeeks.org/r-language/likelihood-ratio-test/
  1017. comparisons = [[1 4];[2 4];[3 4];[5 4]]; % the numbers of the models to be compared: compare Responsibility (model 4) to all others
  1018. for pair = 1:size(comparisons,1)
  1019. m0 = comparisons(pair,1); m1 = comparisons(pair,2); % m0 is the simpler, m1 the more complex model
  1020. % LR = -2 * ([compResults(:,m0).logL] - [compResults(:,m1).logL]); % for each participant separately
  1021. LR = -2 * (sum([compResults(:,m0).logL]) - sum([compResults(:,m1).logL])); % summing over participants
  1022. df = length(compResults(1,m1).b) - length(compResults(1,m0).b);
  1023. pval = chi2test(LR,df); % LRs follow a Chi-square distribution
  1024. fprintf('Is model "%s" better than model "%s"? LikelihoodRatioTest = %.2f, p = %f\n', modelNames{m1}, modelNames{m0}, LR, pval)
  1025. end
  1026. end % compare models
  1027. if strcmpi(compModelName,'ParamRecovery')
  1028. %% Run parameter recovery analysis, only for ResponsibilityRedux model. Need to load real parameters and compute mtx matrices (done above).
  1029. % First, load the real fitted parameters
  1030. paramDir = 'csv/';
  1031. params = readtable([paramDir dataset ' - ResponsibilityRedux - fittedParameters.csv']);
  1032. % Next, for each subject of each study, simulate data based on real
  1033. % parameters, fit those data, and check what parameters come out. Vary the
  1034. % noise (units: SD of happiness). Display results.
  1035. noiseLevel = 1; Nrep = 10; displayFlag = 0;
  1036. if ~(length(mtxs) == size(params,1)); error('Data and parameter matrices have different sizes - check which study we''re processing here'); end
  1037. progress_report(0,'Parameter recovery')
  1038. recov_params_all = [];
  1039. for sub = 1:length(mtxs)
  1040. progress_report(sub/length(mtxs),'Parameter recovery')
  1041. mtx = mtxs{sub};
  1042. paramsThisSub = table2array(params(sub,:));
  1043. recov_params = parameterRecovery_happy_model_responsibility_redux(mtx,paramsThisSub,noiseLevel,Nrep,displayFlag);
  1044. recov_params_all(:,:,sub) = recov_params; % dimensions: Nrep, paramNo, subNo.
  1045. end % for each subject
  1046. save(['bin/compModels/Recovered model parameters for ' dataset ' study ' num2str(Nrep) 'iter.mat'],'recov_params_all','params')
  1047. % Now, display
  1048. figure('Name',['Model parameter recovery for ' dataset ' study']);
  1049. for p = 1:size(params,2)
  1050. subplot(2,3,p);
  1051. % plot(table2array(params(:,p)),squeeze(mean(recov_params_all(:,p,:))),'.') % x axis: real parameters across subjects, y axis: recovered parameters
  1052. plot(repmat(table2array(params(:,p)),1,Nrep)',squeeze(recov_params_all(:,p,:)),'.') % x axis: real parameters across subjects, y axis: recovered parameters
  1053. title(params.Properties.VariableNames{p},'interpreter','none')
  1054. end
  1055. end % parameter recovery
  1056. %% ------------------------------------------------------------------------
  1057. %
  1058. % NOW LINEAR MIXED MODEL ANALYSIS OF HAPPINESS DATA
  1059. %
  1060. % -------------------------------------------------------------------------
  1061. data = [];
  1062. for i = 1:length(R) % for each subject
  1063. for j = 1:length(R{i}) % for each trial
  1064. dat = [...
  1065. R{i}(j).happiness...
  1066. R{i}(j).condition...
  1067. R{i}(j).safeOption/100 ...
  1068. R{i}(j).riskyOption/100 ...
  1069. R{i}(j).play...
  1070. R{i}(j).subjectWon...
  1071. R{i}(j).partnerWon...
  1072. R{i}(j).amountThisTrialSubject/100 ...
  1073. R{i}(j).amountThisTrialPartner/100 ...
  1074. i...
  1075. ];
  1076. data = [data; dat];
  1077. end
  1078. end
  1079. Thap = array2table(data,'VariableNames',{'happiness' 'cond' 'Vsafe' 'riskyHi' 'riskyLo' 'choseRisky' 'subjectWon' 'partnerWon' 'rewardSubj' 'rewardPart' 'subject'});
  1080. Thap.EV = ( ( Thap.riskyHi + Thap.riskyLo ) / 2 ) .* Thap.choseRisky + ( Thap.Vsafe .* ( 1 - Thap.choseRisky) );
  1081. ineq = NaN(size(data,1),1); ineq(Thap.rewardSubj ~= Thap.rewardPart) = 1; ineq(Thap.rewardSubj == Thap.rewardPart) = 0; ineq(isnan(Thap.rewardPart)) = NaN; % social trials in which participants got different outcomes vs same outcomes
  1082. ineqAdv = NaN(size(data,1),1); ineqAdv(Thap.subjectWon==1 & Thap.partnerWon==0) = 1; ineqAdv(Thap.subjectWon==1 & Thap.partnerWon==1) = 0; % trials in which participant only won vs. both won
  1083. ineqDisadv = NaN(size(data,1),1); ineqDisadv(Thap.subjectWon==0 & Thap.partnerWon==1) = 1; ineqDisadv(Thap.subjectWon==1 & Thap.partnerWon==1) = 0; % trials in which partner only won vs. both won
  1084. Thap.ineq = ineq;
  1085. Thap.ineqAdv = ineqAdv;
  1086. Thap.ineqDisadv = ineqDisadv;
  1087. Thap.sRPE = Thap.rewardSubj - Thap.EV;
  1088. Thap.pRPE = Thap.rewardPart - Thap.EV;
  1089. Thap.subjDecided = Thap.cond ~= 2;
  1090. Thap.socialTrial = Thap.cond < 3;
  1091. % Write table out to verify model in R - remove trials with happiness =
  1092. % NaN, trials were the safe option was chosen, and non-social trials
  1093. Thap2 = Thap(~isnan(Thap.happiness) & ~isnan(Thap.partnerWon),:);
  1094. writetable(Thap2,[mfilepath 'csv/' dataset ' - Happiness_singleTrialData_socialRiskyChoicesOnly.csv']);
  1095. % Make a nice simple plot relating reward to happiness change
  1096. if strcmpi(study,'both (-> paper)')
  1097. figure(paperFig2)
  1098. axes('position',happyRewardPanelPos1+studyOffset); regress_display(Thap.rewardSubj, Thap.happiness,'axesHandle',gca,'colors',colors(1,:),'inputNames',{'Participant reward [Euro]','\Delta Happiness [std]'},'regressType','robust');
  1099. title({[studyName ':'],'Impact of participant','reward on happiness'})
  1100. axes('position',happyRewardPanelPos2+studyOffset); regress_display(Thap.rewardPart, Thap.happiness,'axesHandle',gca,'colors',colors(2,:),'inputNames',{'Partner reward [Euro]','\Delta Happiness [std]'},'regressType','robust');
  1101. % title(' Impact of partner\newlinereward on happiness')
  1102. title({[studyName ':'],'Impact of partner','reward on happiness'})
  1103. else
  1104. figure
  1105. subplot(1,2,1); regress_display(Thap.rewardSubj, Thap.happiness,'axesHandle',gca,'colors',colors(1,:),'inputNames',{'Participant reward [Euro]','\Delta Happiness [std]'},'regressType','robust');
  1106. title('Impact of participant\newlinereward on happiness')
  1107. subplot(1,2,2); regress_display(Thap.rewardPart, Thap.happiness,'axesHandle',gca,'colors',colors(2,:),'inputNames',{'Partner reward [Euro]','\Delta Happiness [std]'},'regressType','robust');
  1108. title(' Impact of partner\newlinereward on happiness')
  1109. end
  1110. % Testing simple models relating happiness to reward
  1111. model = {}; modelName = {}; lm_data = [];
  1112. model{1} = 'happiness ~ 1 + rewardSubj + rewardPart + (1|subject)'; % modelName{1} = 'Subject and partner reward';
  1113. model{2} = 'happiness ~ 1 + rewardSubj + rewardPart + ineq + (1|subject)'; % modelName{2} = 'Subject reward + inequality (lotteries only)';
  1114. lm = {};
  1115. for m = 1:length(model)
  1116. lm{m} = fitglme(Thap,model{m});
  1117. end
  1118. for m = 2:length(model)
  1119. results = compare(lm{1},lm{m})%,'CheckNesting',true)
  1120. end
  1121. [~,best] = min(results.AIC);
  1122. disp('========= Linear mixed model regressing happiness on reward; best model was:')
  1123. lm{best}
  1124. printEconomicsStyleRegressionTableForGLMs(lm, modelName, [dataset ' - LMM happiness on reward'], [mfilepath 'csv/' dataset ' - LMM happiness on reward.csv']);
  1125. % show residuals of best-fitting model
  1126. [~,best] = min(results.AIC);
  1127. figure('position',[319 137 889 798],'name','Residuals of LM on happiness, simple and responsibility models');
  1128. [H,p,jbstat] = jbtest(lm{best}.residuals);
  1129. if H; str = 'Residuals not normally distributed'; else; str = 'Residuals normally distributed'; end
  1130. tit = sprintf('Jarque-Bera stat = %.1f, p = %.3f',jbstat,p);
  1131. subplot(2,2,1); plot(Thap.happiness,lm{best}.residuals,'.'); axis tight; xlabel('Happiness'); ylabel('Residuals'); title(str)
  1132. subplot(2,2,2); qqplot(lm{best}.residuals); xlabel('Normal quantiles'); ylabel('Residuals'); title(tit)
  1133. % Condition models
  1134. model = {}; lm = {}; modelName = {};
  1135. model{1} = 'happiness ~ 1 + cond + (1|subject)';
  1136. model{2} = 'happiness ~ 1 + subjDecided + (1|subject)';
  1137. model{3} = 'happiness ~ 1 + socialTrial + (1|subject)';
  1138. model{4} = 'happiness ~ 1 + subjDecided + socialTrial + (1|subject)';
  1139. for m = 1:length(model)
  1140. lm{m} = fitglme(Thap,model{m});
  1141. disp([lm{m}.LogLikelihood lm{m}.Rsquared.Adjusted]);
  1142. end
  1143. for m = 2:length(model)
  1144. results = compare(lm{1},lm{m})%,'CheckNesting',true)
  1145. end
  1146. [~,best] = min(results.AIC);
  1147. disp('========= Linear mixed model regressing happiness on subjDecided and social or not; best model was:')
  1148. lm{best}
  1149. printEconomicsStyleRegressionTableForGLMs(lm, modelName, [dataset ' - LMM happiness on conditions'], [mfilepath 'csv/' dataset ' - LMM happiness on conditions.csv']);
  1150. % Responsibility models
  1151. model = {}; lm = {}; modelName = {};
  1152. model{1} = 'happiness ~ 1 + subjectWon + partnerWon + subjDecided + (1|subject)';
  1153. model{2} = 'happiness ~ 1 + subjectWon + partnerWon + subjectWon:partnerWon + subjDecided + subjDecided:subjectWon + subjDecided:partnerWon + (1|subject)';
  1154. for m = 1:length(model)
  1155. lm{m} = fitglme(Thap,model{m});
  1156. disp([lm{m}.LogLikelihood lm{m}.Rsquared.Adjusted]);
  1157. end
  1158. for m = 2:length(model)
  1159. results = compare(lm{1},lm{m})%,'CheckNesting',true)
  1160. end
  1161. disp('========= Linear mixed model regressing happiness after lottery outcomes based on who won and who decided; best model was:')
  1162. lm{end}
  1163. % show residuals of best-fitting Responsibility LMM model
  1164. [~,best] = min(results.AIC);
  1165. [H,p,jbstat] = jbtest(lm{best}.residuals);
  1166. if H; str = 'Residuals not normally distributed'; else; str = 'Residuals normally distributed'; end
  1167. tit = sprintf('Jarque-Bera stat = %.1f, p = %.3f',jbstat,p);
  1168. subplot(2,2,3); plot(Thap.happiness,lm{best}.residuals,'.'); axis tight; xlabel('Happiness'); ylabel('Residuals'); title(str)
  1169. subplot(2,2,4); qqplot(lm{best}.residuals); xlabel('Normal quantiles'); ylabel('Residuals'); title(tit)
  1170. % show effect of outcome for partner X decision-maker on happiness
  1171. q = lm{end}.Coefficients(7,:);
  1172. fprintf('Study %d, happiness, linear model t statistic for %s: t(%d) = %.2f, p value = %f, beta = %.3f, 95%% CI = [%.3f %.3f]\n', currentStudy, q{1,1}, q{1,5}, q{1,4}, q{1,6}, q{1,2}, q{1,7}, q{1,8})
  1173. printEconomicsStyleRegressionTableForGLMs(lm, {}, [dataset ' - LMM happiness on outcomes and responsibility'], [mfilepath 'csv/' dataset ' - LMM happiness on outcomes and responsibility.csv']);
  1174. %% ------------------------------------------------------------------------
  1175. %
  1176. % NOW INTER-INDIVIDUAL DIFFERENCES
  1177. % EXPLORATION, NOT REPORTED IN PAPER BECAUSE TOO LOW N
  1178. %
  1179. % -------------------------------------------------------------------------
  1180. %% Relate responsibilityEffect to some outcomes of the computational analysis
  1181. if strcmpi(modelName,'Compare')
  1182. q=[responsibilityEffect resMtx{4}(:,9:10) resMtx{4}(:,9)-resMtx{4}(:,10)];
  1183. idx=~isnan(responsibilityEffect);
  1184. names={'responsibility','otherRPEact','otherRPEpass','diff'};
  1185. disp(names)
  1186. [rr,pp]=corr(q(idx,:))
  1187. end
  1188. %% Check if measures of risk aversion relate to the responsibility effect:
  1189. if flag.fitProbitFunction && flag.findCARArhoInSearchSpace
  1190. figure('name','Does risk aversion relate to the responsibility effect?','position',[202 83 840 612])
  1191. respo = 'Respons. effect happiness';
  1192. subplot(2,2,1);
  1193. inputNames = {respo,'\rho'};
  1194. regress_display(responsibilityEffect,mean(CARA_rho(:,:,1),2),'regressType','robust','axesHandle',gca,'inputNames',inputNames)
  1195. subplot(2,2,2);
  1196. inputNames = {respo,'Risk premium'};
  1197. regress_display(responsibilityEffect,mean(riskPremiumProbitFit(:,1),2),'regressType','robust','axesHandle',gca,'inputNames',inputNames)
  1198. subplot(2,2,3);
  1199. inputNames = {respo,'\Delta \rho (social-solo)'};
  1200. regress_display(responsibilityEffect,mean(CARA_rho(:,:,1)-CARA_rho(:,:,3),2),'regressType','robust','axesHandle',gca,'inputNames',inputNames)
  1201. subplot(2,2,4);
  1202. inputNames = {respo,'\Delta Risk premium (social-solo)'};
  1203. regress_display(responsibilityEffect,mean(riskPremiumProbitFit(:,1)-riskPremiumProbitFit(:,3),2),'regressType','robust','axesHandle',gca,'inputNames',inputNames)
  1204. end
  1205. end % which dataset
  1206. %% If output for paper, report mixed-model regressions on choices and make econ-style mixed model output tables
  1207. if paperFigure
  1208. disp('Stats for probit models of choices')
  1209. for st = 1:2 % Study 1 or 2
  1210. % Stats for effect of EVdiff in probit model of choices
  1211. q = choiceLMMs{st,1}.Coefficients(2,:); % Probit model
  1212. fprintf('Study %d, probit model t statistic for %s: t(%d) = %.2f, p value = %d, beta = %.3f, 95%% CI = [%.3f %.3f]\n', st, q{1,1}, q{1,5}, q{1,4}, q{1,6}, q{1,2}, q{1,7}, q{1,8})
  1213. % Stats for effect of condition (social vs solo)
  1214. q = choiceLMMs{st,1}.Coefficients(3,:); % Probit model for Study 1
  1215. fprintf('Study %d, probit model t statistic for %s: t(%d) = %.2f, p value = %d, beta = %.3f, 95%% CI = [%.3f %.3f]\n', st, q{1,1}, q{1,5}, q{1,4}, q{1,6}, q{1,2}, q{1,7}, q{1,8})
  1216. end
  1217. % Print all model stats to file
  1218. modelNames = {'Study 1 probit','Study 1 linear','Study 2 probit','Study 2 linear'};
  1219. printEconomicsStyleRegressionTableForGLMs(choiceLMMs([1 3 2 4]), modelNames, 'Choices', [mfilepath 'csv/LMMs choices.csv']);
  1220. end
  1221. %% If paperFigure, add letters and print as SVG
  1222. panLetterFontSize = 30; % 40 previously
  1223. if paperFigure
  1224. figure(paperFig1)
  1225. axes('position',[0 0 1 1],'visible','off')
  1226. text(repmat([.02 .49 .73],1,2),kron([.89 .44],[1 1 1]),cellstr(['ABCDEF']'),'fontsize',panLetterFontSize)
  1227. cd([mfilepath 'Figures/'])
  1228. printSVG
  1229. printfig
  1230. figure(paperFig2)
  1231. axes('position',[0 0 1 1],'visible','off') %.41
  1232. text(repmat([.02 .23 .44 .67],1,2),kron([.89 .44],[1 1 1 1]),cellstr(['ABCDEFGH']'),'fontsize',panLetterFontSize)
  1233. printSVG
  1234. printfig
  1235. cd(mfilepath)
  1236. end
  1237. %% Show parameter recovery
  1238. % A nice supplementary materials figure of the parameter recovery results
  1239. compModelParameterRecoveryFigure
  1240. %% POSSIBLE TO DOs
  1241. set(0,'defaultAxesFontSize',12) % back to normal defaults
  1242. disp('Could check whether the variance of the lotteries correlates with their EV or EV diff to alternative safe option, as both variance and deltaEV can affect choices')
  1243. disp('Could relate sympathy levels to responsibilityEffect, if I had more participants')

master_behavAnalysis_revised.m at commit 11854fe, under MIT · at the source

Overview

Authors: Maria Gädeke1, Tom Eric Willems1,2, Omar Salah Ahmed1,3,4, Bernd Weber3,4, Rene Hurlemann5, Johannes Schultz3,4
  1. Masters in Neuroscience Program, University of Bonn, Bonn, Germany
  2. Institute of Psychology, University of Bern, Bern, Switzerland
  3. Center for Economics and Neuroscience, University of Bonn, Bonn, Germany
  4. Institute of Experimental Epileptology and Cognition Research, Medical Faculty, University of Bonn, Bonn, Germany
  5. Department of Psychiatry, University of Oldenburg, Oldenburg, Germany
Institutions: University of Bonn (Germany); University of Bern (Switzerland); Carl von Ossietzky Universität Oldenburg (Germany)
Journal: eLife, volume 14, article RP105391
Dates: published online 24 March 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.7554/elife.105391 · PMID 41873443 · PMCID PMC13012722 · OpenAlex W4408798353
Open access: gold, a free copy (OpenAlex)
Status: code verified (how the code is found and verified)
Categories: human (organism), cognitive (subfield)
Methods: Connectivity, Statistics, Machine learning, Preprocessing, fMRI & imaging, Single-unit activity, calcium imaging
Keywords: Human
MeSH: Decision Making*, Guilt*, Insular Cortex*, Interpersonal Relations*, Social Behavior*, Temporal Lobe*, Adult, Brain Mapping, Female, Happiness, Humans, Magnetic Resonance Imaging, Male, Young Adult (* major topic)
Topic: Emotions and Moral Behavior (Social Psychology, Psychology), according to OpenAlex
Citations: not cited yet (Europe PMC); 73 references in the paper

Abstract

This study investigated the neural mechanisms involved in feelings of interpersonal guilt and responsibility evoked by social decisions in humans. In two studies (one during fMRI), participants repeatedly chose between safe and risky monetary outcomes in social contexts. Across conditions, each participant chose for both themselves and a partner (Social condition), or the partner chose for both themselves and the participant (Partner condition), or the participant chose just for themselves (Solo condition, control). If the risky option was chosen in the Social or Partner condition, participant and partner could each receive either the high or the low outcome of a lottery with 50% probability, independently of each other. Participants were shown the outcomes for themselves and for their partner on each trial and reported their momentary happiness every few trials. As expected, participant happiness decreased following both low lottery outcomes for themselves and for the partner. Crucially, happiness decreases following low outcomes for the partner were larger when the participant rather than their partner had made the choice, which fits an operational definition of guilt. This guilt effect was associated with BOLD signal increase in the left anterior insula. Connectivity between this region and the right inferior frontal gyrus varied depending on choice and experimental condition, suggesting that this part of prefrontal cortex is sensitive to guilt-related information during social choices. Variations in happiness were well explained by computational models based on participants’ and partners’ rewards and reward prediction errors. A model-based analysis revealed a left superior temporal sulcus cluster that tracked partner reward prediction errors that followed participant choices. Our findings identify neural mechanisms of guilt and social responsibility during social decisions under risk.

Reproduced under the paper's license (CC BY), from the paper cited above.

Repositories

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

canlab/neuroimaging_pattern_masks

License: GPL-3.0
State: the link answers, verified on 29 October 2026
Evidence: files inventoried
Commit: 961d0033f7074ef8d6c25c6ac318d016a92bba12, 23 October 2026
Languages: MATLAB (264), Python (45), Shell (26), JavaScript (7)
Size: 5,409 files, 342 scripts
Software Heritage: not archived
Found in: the text, “Comparison with multivariate neural guilt signat”
Holds: environment (Atlases_and_parcellations/2020_Thiebaut_de_Schotten_white_matter_atlas/setup.py), continuous integration, documentation, 4 notebooks
Not found: README, license file, CITATION.cff, tests
Tools: NumPy (22 files), NiBabel (21 files), Statistics and Machine Learning Toolbox (15 files), SciPy (12 files), FSL (9 files), pandas (6 files), ANTs (5 files), scikit-learn (5 files), fMRIPrep (4 files), Parallel Computing Toolbox (4 files), Nilearn (4 files), Connectome Workbench (4 files), FreeSurfer (3 files), SPM (3 files), Image Processing Toolbox (2 files), Nipype (2 files), Pillow (2 files), abagen (1 file), Matplotlib (1 file), MRtrix3 (1 file), statsmodels (1 file)
Availability: 2 checks, the latest on 29 October 2026: the link answers
  • 29 October 2026: the link answers
  • 28 September 2026: the link answers
344 files

bonnsocialneuroscienceunit/responsibilityexperiment

License: MIT
State: the link answers, verified on 30 September 2026
Evidence: files inventoried
Commit: 11854fee85b7b75e23b24cbf98b284c44f6de94d, 12 March 2026
Languages: MATLAB (54)
Size: 455 files, 54 scripts
Software Heritage: not archived
Found in: the references
Holds: README, license file
Not found: CITATION.cff, environment file, tests, continuous integration, documentation
Tools: Statistics and Machine Learning Toolbox (18 files), Optimization Toolbox (13 files), SPM (8 files), Psychtoolbox (1 file)
Availability: 1 check, the latest on 30 September 2026: the link answers
  • 30 September 2026: the link answers
56 files

The paper's code and data availability statement is in the Data section.

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:

  • 2 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 396 scripts, each with its path and the digest of its content;
  • 27 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

Datasets cited

Data availability

All behavioural data and group fMRI results maps needed to reproduce all the results and the figures of this study are freely available at GitHub (https://github.com/BonnSocialNeuroscienceUnit/ResponsibilityExperiment) (copy archived at Schultz, 2026). The entire raw dataset (anonymous data) is publicly available on OpenNeuro (https://doi.org/10.18112/openneuro.ds005588.v1.0.0). All the code used to replicate the experiment, analyse the data and produce the figures of this study is freely available at GitHub (https://github.com/BonnSocialNeuroscienceUnit/ResponsibilityExperiment) (Schultz, 2026).

The following previously published dataset was used:

Schultz J. 2024. SoDec - Responsibility fMRI experiment dataset. OpenNeuro.

Reproduced under the paper's license (CC BY), from the paper cited above.

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, 30 September 2026: the first record

Recorded: type, language, journal, volume, pages, dates, 6 authors, 1 keyword, 14 MeSH terms, 1 funder, 70 references, 7 RRIDs.

Cite

This paper

Gädeke, M., Willems, T. E., Ahmed, O. S., Weber, B., Hurlemann, R., & Schultz, J. (2026). Contributions of insula and superior temporal sulcus to interpersonal guilt and responsibility in social decisions. eLife, 14, RP105391. https://doi.org/10.7554/elife.105391

BibTeX

@article{gadeke2026contributions,
author = {Gädeke, Maria and Willems, Tom Eric and Ahmed, Omar Salah and Weber, Bernd and Hurlemann, Rene and Schultz, Johannes},
title = {{Contributions of insula and superior temporal sulcus to interpersonal guilt and responsibility in social decisions}},
journal = {eLife},
year = {2026},
month = mar,
volume = {14},
pages = {RP105391},
publisher = {eLife Sciences Publications, Ltd},
issn = {2050-084X},
doi = {10.7554/elife.105391},
url = {https://doi.org/10.7554/elife.105391},
pmid = {41873443},
pmcid = {PMC13012722}
}

RIS

TY - JOUR
AU - Gädeke, Maria
AU - Willems, Tom Eric
AU - Ahmed, Omar Salah
AU - Weber, Bernd
AU - Hurlemann, Rene
AU - Schultz, Johannes
TI - Contributions of insula and superior temporal sulcus to interpersonal guilt and responsibility in social decisions
T2 - eLife
J2 - eLife
PY - 2026
DA - 2026/03/24
VL - 14
SP - RP105391
SN - 2050-084X
PB - eLife Sciences Publications, Ltd
DO - 10.7554/elife.105391
UR - https://doi.org/10.7554/elife.105391
LA - en
ER -

CSL-JSON

{
"id": "10.7554/elife.105391",
"type": "article-journal",
"title": "Contributions of insula and superior temporal sulcus to interpersonal guilt and responsibility in social decisions",
"container-title": "eLife",
"author": [
{
"family": "Gädeke",
"given": "Maria"
},
{
"family": "Willems",
"given": "Tom Eric"
},
{
"family": "Ahmed",
"given": "Omar Salah"
},
{
"family": "Weber",
"given": "Bernd"
},
{
"family": "Hurlemann",
"given": "Rene"
},
{
"family": "Schultz",
"given": "Johannes"
}
],
"container-title-short": "eLife",
"volume": "14",
"page": "RP105391",
"DOI": "10.7554/elife.105391",
"PMID": "41873443",
"PMCID": "PMC13012722",
"ISSN": "2050-084X",
"publisher": "eLife Sciences Publications, Ltd",
"URL": "https://doi.org/10.7554/elife.105391",
"language": "en",
"issued": {
"date-parts": [
[
2026,
3,
24
]
]
}
}

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-71568-9 [code]
Convergent and selective representations of pain, appetitive processes, aversive processes, and cognitive control in the insula.
Journal: Nature communications
In common: fMRIPrep, abagen, MRtrix3, 18 other tools, cognitive, 3 references
[2] doi:10.1002/hbm.26468 [code]
Healthcare experience affects pain-specific responses to others' suffering in the anterior insula.
Journal: Human brain mapping
In common: fMRIPrep, abagen, MRtrix3, 18 other tools, cognitive, 3 references
[3] doi:10.1038/s41467-026-71151-2 [code]
Common and distinct neural correlates of social interaction processing and theory of mind in narratives.
Journal: Nature communications
In common: fMRIPrep, abagen, MRtrix3, 20 other tools, cognitive
[4] doi:10.1002/advs.202514044 [code]
Light Therapy Alleviates Addiction-Related Symptoms and Reshapes Habenula and Midbrain Pathways.
Journal: Advanced science (Weinheim, Baden-Wurttemberg, Germany)
In common: fMRIPrep, abagen, MRtrix3, 18 other tools, 1 reference
[5] doi:10.1038/s41366-026-02018-1 [code]
The neural pathways of change: an fMRI study of the effects of behavioral change suggestions on value-based dietary decision-making.
Journal: International journal of obesity (2005)
In common: fMRIPrep, abagen, MRtrix3, 18 other tools, cognitive
[6] doi:10.7554/elife.87962 [code]
A distributed brain response predicting the facial expression of acute nociceptive pain.
Journal: eLife
In common: fMRIPrep, abagen, MRtrix3, 18 other tools
[7] doi:10.1093/ijnp/pyac037 [code]
Oxytocinergic Modulation of Stress-Associated Amygdala-Hippocampus Pathways in Humans Is Mediated by Serotonergic Mechanisms.
Journal: The international journal of neuropsychopharmacology
In common: fMRIPrep, abagen, MRtrix3, 18 other tools
[8] doi:10.7554/elife.107223 [code]
Human neurocomputational mechanisms of guilt-driven and shame-driven altruistic behavior.
Journal: eLife
In common: 15 references
[9] doi:10.1038/s41467-023-44286-9 [code]
The psychological, computational, and neural foundations of indebtedness.
Journal: Nature communications
In common: Optimization Toolbox, Nilearn, SPM, 6 other tools, 9 references
[10] doi:10.1038/s41592-025-02599-1 [code]
DeepPrep: an accelerated, scalable and robust pipeline for neuroimaging preprocessing empowered by deep learning.
Journal: Nature methods
In common: fMRIPrep, Nipype, Connectome Workbench, 14 other tools

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.

Add the badge to the code's README

OSCR: the badge of this paper

If you are an author or a maintainer of this paper's code, you can add this badge. It says what OSCR knows of the paper (its code, its validated tracing map) and links the code to this page. Paste one of these snippets under the README's title. Keep the two marks around it, so that the badge can be replaced in place and is never added twice. OSCR changes nothing in your repository.

Markdown
<!-- oscr-badge:start -->
[![OSCR](https://openscicode.org/badge/doi/10.7554/elife.105391.svg)](https://openscicode.org/badge/doi/10.7554/elife.105391)
<!-- oscr-badge:end -->
reStructuredText
.. oscr-badge:start

.. image:: https://openscicode.org/badge/doi/10.7554/elife.105391.svg
   :target: https://openscicode.org/badge/doi/10.7554/elife.105391
   :alt: OSCR

.. oscr-badge:end
HTML
<!-- oscr-badge:start -->
<a href="https://openscicode.org/badge/doi/10.7554/elife.105391"><img src="https://openscicode.org/badge/doi/10.7554/elife.105391.svg" alt="OSCR"></a>
<!-- oscr-badge:end -->

On GitHub, open the README, choose Edit (the pencil), paste the snippet under the title, then "Commit changes".

If you choose to, you can have the badge kept up to date for you, with oscr badge --write from the command line or with the GitHub Action in your repository's workflows. Every other form and option (a card, AsciiDoc, LaTeX, shields.io) is on the badge 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: code errors and mismatches between the code and the paper about this paper and its code, from readers and its authors, beside the paper and its tracing map.

Report a mismatch between the code and the paper · Report a code error (signed in)

Reproductions: reports from readers who ran the authors' code and did not get the paper's result, what they ran, with which environment, commit and data.

Report a reproduction failure (signed in)

Versions of its code: the releases of its code tied to a version of this paper (the preprint, the accepted manuscript, the version of record…), each with the tracing map versioned with it.

Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.