OSCR

Fluctuations in arousal reflect latent state transitions that facilitate behavioural optimization.

Code ↔ Paper

10 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 10 matches
  1. [1] § Methods › Behavioural data analysis ↔ analysis/eyeAnalysis.m, lines 837–983 · score 0.77 · 0–200 ms, gaze attention, away, horizontal, variable, error
  2. [2] § Results › Individual differences supported a single mechanism linking arousal to bias and learning ↔ analysis/master_analysis_script_all.m, lines 3301–3357 · score 0.61 · learning slopes, arousal slope, bias slope, regression coefficient, bars, Hypothesized
  3. [3] § Results › Pupil dilations reflected an internally generated latent state transition ↔ analysis/master_analysis_script_all.m, lines 1764–1840 · score 0.61 · behavioural PE, OB coefficient, prediction phase, background, permutation, Correlation
  4. [4] § Methods › Task generative model ↔ analysis/modelCP.m, lines 41–125 · score 0.59 · von Mises distribution, 0–360, models, changepoint, block, Stimulus
  5. [5] § Methods › Behavioural data analysis ↔ analysis/master_analysis_script_all.m, lines 340–389 · score 0.58 · gaze attention variable, perceptual errors, zero, regression, bias
  6. [6] § Results › Perceptual bias was reduced with arousal responses to latent state transitions › EEG and pupil signals reflecting state transitions were accompanied by reduced perceptual bias ↔ analysis/master_analysis_script_all.m, lines 3301–3357 · score 0.54 · learning slopes, Bias slope, arousal slope, residuals, bars, CP
  7. [7] § Methods › Pupil and EEG data analysis ↔ analysis/master_analysis_script_all.m, lines 2392–2456 · score 0.54 · dot product, baseline regressed, map, pupil, EEG
  8. [8] § Methods › Pupil and EEG data analysis ↔ analysis/master_analysis_script_all.m, lines 1386–1526 · score 0.53 · Regression coefficients, permuted, sines, mass, permutation, sum
  9. [9] § Methods › Pupil and EEG data analysis ↔ analysis/getPupil_clusterSize.m, lines 1–65 · score 0.52 · cluster forming threshold, mass, permutation, sum, zero, pupil
  10. [10] § Methods › Task design ↔ task/colorTools/displayCharacterization/colorSandbox_426C_2022.m, lines 1–135 · score 0.51 · CIELAB, chromaticity, luminance, background, circle, space

Paper

Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC

The paper is loaded when this pane is shown.

The authors' code

MATLAB · 4,178 lines · 194 KB · no license · 6 matches

  1. clear
  2. %Functions Called: eeg_analysisFunc eyeRegressionFunc eyeRegressionPredResp computeLearningRate getEEGClusterSize getPupilClusterSize modelCP modelOB eyeAnalysis shared_variables
  3. %Data Needed: behave data all blocks; behave data 3 and 4; eye data; eeg data; chanlocs;
  4. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  5. %%% %%%
  6. %%% SETUP INSTRUCTIONS: %%%
  7. %%% %%%
  8. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  9. % 0. you're probably going to need 70 GB worth of space on your computer to run this with every subject
  10. % 1. set up some folder to put data and results in, and set that folder as the basePath
  11. % 2. place this script and the functions "eyeRegressionFunc", "eyeRegressionPredResp", "eeg_analysisFunc", "modelOB", "modelCP", "getEEGClusterSize", "computeLearningRate", "eyeAnalysis", "shared_variables", and "chanlocs.mat" in the basePath folder
  12. % 3. in basePath make subfolders for behaveData, eyeData and eegData, and set them as behaveDir, eyeDir, and eegDir respectively
  13. % 4. download CLEANED eeg data (files titled XXXX_ALP_FILT_STIM.mat) from ALP_Summer2022\vwm_task_Harry\eegData\ and place in eegData subfolder
  14. % 5. download eye data (files titled XXXX.mat) from ALP_Summer2022\vwm_task_Harry\ET_data\ and place in eyeData subfolder
  15. % 6. inside the behaveData subfolder, create folders titled "allSubCombined" and "subCombined"
  16. % 7. download the full behavioral data (files titled XXXX_allBlockData.mat) from ALP_Summer2022\vwm_task_Harry\behaveData\allSubCombined and place in allSubCombined subfolder
  17. % 8. download the prediction phase's behavioral data (files titled XXXX_3and4BlockData.mat) from ALP_Summer2022\vwm_task_Harry\behaveData\subCombined and place in subCombined subfolder
  18. % 9. create a final subfolder for figures that the script will generate figures and set that folder as figDir
  19. % 10. download the version of sharedMatlabUtilities that exists in the ALP_Summer2022 folder and place that as a subfolder in basePath. Set smuPath to the helperFuncs location
  20. % 11. review directories, it should look something like
  21. %
  22. % basePath
  23. % *analysis functions go here*
  24. % behaveData
  25. % allSubCombined
  26. % XXXX_allBlockData.mat
  27. % subCombined
  28. % XXXX_3and4BlockData.mat
  29. % eyeData
  30. % XXXX.mat
  31. % eegData
  32. % XXXX_ALP_FILT_STIM.mat
  33. % figDir
  34. %
  35. %
  36. % 12. review parameters, note that the first time you run the script, runEEGRegression and runModel should both be true
  37. % 13. verify that the EEGSubs, eyeSubs, and behaveSubs lists in the script match up with the data that has been downloaded to your computer
  38. % (script should stop and inform you if data isn't on your path)
  39. %% Step 1: Set parameters/paths
  40. whichComp = 2;
  41. if whichComp == 1
  42. basePath = '~/Documents/GitHub/Li-Marble-2025/analysis/';
  43. eyeDir = '~/Documents/GitHub/Li-Marble-2025/data/ET_data/';
  44. behaveDir = '~/Documents/GitHub/Li-Marble-2025/data/behaveData/';
  45. smuPath = '~/Documents/GitHub/Li-Marble-2025/analysis/helperFuncs/';
  46. subFunc = '~/Documents/GitHub/Li-Marble-2025/analysis/subFunctions/';
  47. eegDir = '~/Documents/GitHub/Li-Marble-2025/data/eegDataSmall/';
  48. figDir = '~/Documents/GitHub/Li-Marble-2025/data/figures/generatedFigs/';
  49. elseif whichComp == 2
  50. basePath = 'C:\Users\hmarble\Brown Dropbox\Harrison Marble\ALP_Summer2022\vwm_task_Harry\';
  51. eyeDir = 'C:\Users\hmarble\Brown Dropbox\Harrison Marble\ALP_Summer2022\vwm_task_Harry\ET_data\';
  52. behaveDir = 'C:\Users\hmarble\Brown Dropbox\Harrison Marble\ALP_Summer2022\vwm_task_Harry\behaveData\';
  53. smuPath = 'C:\Users\hmarble\Brown Dropbox\Harrison Marble\ALP_Summer2022\sharedMatlabUtilities';
  54. eegDir = 'C:\Users\hmarble\Brown Dropbox\Harrison Marble\ALP_Summer2022\vwm_task_Harry\eegDataSmall\';
  55. figDir = 'C:\Users\hmarble\Brown Dropbox\Harrison Marble\ALP_Summer2022\vwm_task_Harry\figures\generatedFigs\';
  56. end
  57. addpath(genpath(basePath))
  58. addpath(genpath(smuPath))
  59. dirs.basePath = basePath;
  60. dirs.eyeDir = eyeDir;
  61. dirs.behaveDir = behaveDir;
  62. dirs.smuPath = smuPath;
  63. dirs.eegDir = eegDir;
  64. dirs.figDir = figDir;
  65. %colors for figures
  66. cpColor = [246 146 30]./255;
  67. obColor = [0 173 238]./255;
  68. cpLColor = [251 200 143]./255;
  69. obLColor = [128 214 247]./255;
  70. cbColors=[0 0 0; 230 159 0; 86 180 233; 200 50 200; 0 158 115; 240 228 66; 0 114 178; 213 94 0; 204 121 167; 256 256 256]./256;
  71. % Set parameters
  72. nAllTrials = 300;
  73. nPracticeTrials = 60;
  74. sigThresh = 0.025;
  75. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  76. %%% %%%
  77. %%% set subject IDs %%%
  78. %%% %%%
  79. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  80. % realData=input('are you using the whole dataset? Yes(1)/No(0):'); if script is public
  81. realData=0;
  82. if realData
  83. % EEGSubs = [20280 2030 2033:2037 20380 2039:2048 2050 2053 2055 2056 2058 2060 2062 ...
  84. % 2063 2065 2066 2068 2069 2071 2073:2075 2080:2088 2090 2092:2101 2104:2106];
  85. % eyeSubs = [20280 2030 2033:2037 20380 2039:2048 2050 2053 2055:2058 2060 2062 2063 ...
  86. % 2065 2066 2068:2071 2073:2075 2079:2084 2086:2088 2090 2092:2101 2103:2106];
  87. % behaveSubs = [20280 2030 2031 2033:2037 20380 2039:2048 2050 2053 2055:2058 2060 ...
  88. % 2062 2063 2065 2066 2068:2071 2073:2075 2079:2088 2090 2092:2106 3002 3006:3011 3014 3016:3023 4001:4039];
  89. % behaveSubs = [20280,2030,2031,2036,2037,20380,2040,2043,2046,2047,2050,2053,2055,2056,2058,2060,2063,2065,2068,2069,2070,2071,2073,2080,2081,2082,2083,2087,2088,2090,2092,2093,2094,2097,2100,2101,2102,2106];
  90. EEGSubs = 4001:4045;
  91. eyeSubs = [3002 3006:3011 3014 3016:3023 4001:4041 4043:4045]; %3004 3012 3013 4042 has bad et data
  92. behaveSubs = [3002 3004 3006:3014 3016:3023 4001:4045];
  93. % eyeSubs = [4001:4039];
  94. % behaveSubs = [4001:4039];
  95. else
  96. %Use this data if running from github
  97. EEGSubs=[1001,1002,1003];
  98. eyeSubs=[1001,1002,1003];
  99. behaveSubs=[1001,1002,1003];
  100. end
  101. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  102. %%% %%%
  103. %%% Analysis parameters %%%
  104. %%% %%%
  105. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  106. runModel = 1; %if 0, load previous behaveAll and reuses previous allModelDataCombScript
  107. numModelReps = 40; %behavioral model repetitions, for testing, set this low (1-5) for real analysis, set to 40
  108. doSTPResiduals = 0; %regresses stp out of trial-by-trial signal, learning, and bias
  109. runEEGRegression = 1; %if 0, loads a previous b_mat_eeg
  110. trialMeasure = 3; %3 is the right one (dot product of regressed baseline and STP map) but it takes a while (~40-120 min) to run, 2 doesn't regress baseline but is quicker
  111. %need to do 3 if you're doing stp residuals
  112. eegTimestepMode = 0; %if 0, looks at clusters, if 1 looks at bins of timepoints in specified channels
  113. oddballFigNewVer = 1;
  114. rejTrialsPerBlock = 30;
  115. sigma_y = 30.5; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%CHANGEBACK%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  116. saveText = ['CombScript_',num2str(sigma_y),'_',datestr(now,'mm-dd-yy-hh'),'trialDataTest'];
  117. % figTime = datestr(now,'mm-dd-yy-hh');
  118. figTime = saveText;
  119. % saveText = ['CombScript_31_12-02-24-14_Official'];
  120. %Stimulus eye params
  121. if realData
  122. timeBeforeEye = 1000;
  123. timeAfterEye = 4000;
  124. baselineTimeEye=1000;
  125. blinkWindow = 150;
  126. else
  127. timeBeforeEye = 250;
  128. timeAfterEye = 1000;
  129. baselineTimeEye= 250;
  130. blinkWindow = 35;
  131. end
  132. nBlockTrials = 120;
  133. blinkThresh = 0.2;
  134. numPermEye=2500; % permutation test number
  135. leftArea = 4;
  136. rightArea = 7;
  137. clustThreshEye = 0.025;
  138. combBlinkThresh = 0.5;
  139. %EEG Params
  140. timeBeforeEEG = 1999;
  141. timeAfterEEG = 2000;
  142. EEGTimes = -timeBeforeEEG:timeAfterEEG;
  143. numPermEEG = 1000;
  144. connectThresh=.40;
  145. clustThreshEEG = 0.01;
  146. recreateConnectionMat = 1;
  147. %prepares to removes number of trials from rejTrialsPerBlock at the beginning of each block
  148. remTrials = [];
  149. nTrials = 240;
  150. rejEarlyTrials = zeros(nTrials,1);
  151. if rejTrialsPerBlock>0
  152. rejEarlyTrials([1:rejTrialsPerBlock,nBlockTrials+1:nBlockTrials+rejTrialsPerBlock])=1;
  153. % rejEarlyTrials([nBlockTrials-rejTrialsPerBlock+1:nBlockTrials,2*nBlockTrials-rejTrialsPerBlock+1:2*nBlockTrials])=1;
  154. end
  155. %Prediction eye params
  156. if realData
  157. timeBeforePred = 2000;
  158. timeAfterPred = 4000;
  159. baselineTimeStart = 2000;
  160. baselineTimeEnd = 500;
  161. else
  162. timeBeforePred = 500;
  163. timeAfterPred = 1000;
  164. baselineTimeStart = 500;
  165. baselineTimeEnd = 125;
  166. end
  167. noPredTrials = [239,240,479,480];
  168. clustThreshPred = 0.025;
  169. %Behavioral Regression params
  170. conditionTogether=1;
  171. useModel = 0;
  172. splitHalf = true;
  173. nStart = 100; %%%%%%%%%
  174. nr = 1;
  175. narrowWidth = .05;
  176. betaWidth = narrowWidth;
  177. %usually i keep the bounds here so there's no ceiling effect at 1
  178. LB = -1.5;
  179. UB = 1.5;
  180. lastTrials = [120,240];
  181. % file names will contain sigma_y, date, and hour you ran script
  182. % e.g. if sigma_y = 33 and you start the script at 5:29 on November 1 2024, files would have the tag 'CombScript_33_11-01-24-17'
  183. % you can also set this manually if you want to include more info about the run
  184. % saveTest = {'CombScript_'}
  185. % saveText = ['CombScript_33_10-29-24-13'];
  186. % if you want to load some results from a previous run but keep the new figures with the new time, don't change figTime
  187. if runEEGRegression ~=1
  188. % if you're skipping the eeg regression, load a b_mat_eeg file of your choice
  189. % load("b_mat_eegCombScript_30.5_05-13-25-14_newDatasetTest.mat")
  190. % load("b_mat_eegCombScript_31_12-02-24-14_Official.mat")
  191. load("b_mat_eegCombScript_31_09-09-25-191000Rep.mat")
  192. end
  193. if runModel ~=1
  194. % if you're skipping the behavioral regression, load results from a previous run and resave them with the new run's saveText tag so
  195. % the script can load the right allModelData files later
  196. % load('behaveAllCombScript_30.5_05-13-25-14_newDatasetTest.mat')
  197. % load('behaveAllCombScript_31_12-02-24-14_Official.mat')
  198. behaveAll=[];
  199. for s=1:length(behaveSubs)
  200. subStr = num2str(behaveSubs(s));
  201. fileName=sprintf('behaveData/subCombined/%s_3and4BlockData.mat',subStr);
  202. DP = fullfile(basePath, fileName);
  203. vars = shared_variables(DP);
  204. % allModelData = load(fullfile(behaveDir,['allModelDataCombScript_30.5_05-13-25-14_newDatasetTest/', subStr, '_allBlockData.mat']));
  205. % allModelData = load(fullfile(behaveDir,['allModelDataCombScript_31_12-02-24-14_Official/', subStr, '_allBlockData.mat']));
  206. % allModelData = load(fullfile(behaveDir,['allModelDataCombScript_31_08-25-25-16_40RepGoodEst/', subStr, '_allBlockData.mat']));
  207. % allModelData = load(fullfile(behaveDir,['allModelDataCombScript_31_09-09-25-191000Rep/', subStr, '_allBlockData.mat']));
  208. allModelData = load(fullfile(behaveDir,['allModelData30.5/', subStr, '_allBlockData.mat']));
  209. % allModelData = load(fullfile(behaveDir,['allModelData10/', subStr, '_allBlockData.mat']));
  210. allDataStruct = allModelData.allDataStruct;
  211. saveDir=[behaveDir,'allModelData',saveText,'/'];
  212. if s == 1
  213. mkdir(saveDir)
  214. end
  215. fn=fullfile(saveDir,[subStr,'_allBlockData.mat']);
  216. save(fn,'allDataStruct')
  217. if isempty(behaveAll)
  218. behaveAll=allDataStruct;
  219. elseif exist('behaveAll')&& ~isempty(behaveAll)
  220. behaveAll=catBehav(allDataStruct,behaveAll);
  221. end
  222. end
  223. end
  224. % verify that all subject data (behavioral, eye, and EEG) exists on computer
  225. for s = 1:length(behaveSubs)
  226. subStr = num2str(behaveSubs(s));
  227. if exist(['allSubCombined\',subStr,'_allBlockData.mat']) ~= 2
  228. disp(['Missing data for subject ',subStr,' in allSubCombined folder'])
  229. keyboard
  230. end
  231. if exist(['subCombined\',subStr,'_3and4BlockData.mat']) ~=2
  232. disp(['Missing data for subject ',subStr,' in subCombined folder'])
  233. keyboard
  234. end
  235. end
  236. for s = 1:length(eyeSubs)
  237. subStr = num2str(eyeSubs(s));
  238. if exist([subStr,'.mat']) ~= 2
  239. disp(['Missing data for subject ',subStr,' in eyeData folder'])
  240. keyboard
  241. end
  242. end
  243. for s = 1:length(EEGSubs)
  244. subStr = num2str(EEGSubs(s));
  245. if exist([subStr,'_ALP_FILT_STIM.mat']) ~= 2
  246. disp(['Missing data for subject ',subStr,' in eegData folder'])
  247. keyboard
  248. end
  249. end
  250. %% Behavioral Model stuff
  251. %determine which subjects have eye/eeg data
  252. noEyeSubs = behaveSubs(~ismember(behaveSubs,eyeSubs));
  253. noEEGSubs = behaveSubs(~ismember(behaveSubs,EEGSubs));
  254. missingOneSubs = unique([noEyeSubs,noEEGSubs]);
  255. %if you don't want to run model, you can just load results of a previous run
  256. if runModel == 1
  257. behaveAll=[];
  258. for s=1:length(behaveSubs) %loop through all subs
  259. tic
  260. %define subject number & file names
  261. subNum=behaveSubs(s);
  262. subStr=num2str(subNum);
  263. disp(subNum)
  264. fileName=sprintf('subCombined/%s_3and4BlockData.mat',subStr);
  265. allBlockFileName = sprintf('allSubCombined/%s_allBlockData.mat',subStr);
  266. % load shared variables
  267. DP = fullfile(behaveDir, fileName);
  268. vars = shared_variables(DP);
  269. vars.H = .15;
  270. dataPath=DP;
  271. % load behavioral data
  272. data = load(vars.path);
  273. allBlockData = load([behaveDir,allBlockFileName],'alldata');
  274. allBlockData = allBlockData.alldata;
  275. allDataStruct = data.alldata;% (data.alldata.block == 3 | data.alldata.block == 4);
  276. allDataStruct = straightStruct(allDataStruct);
  277. alldata = allDataStruct;
  278. %calculate standard deviation of estimation error (in case you want to
  279. %use this as sigma_y)
  280. estStd(s) = std(allBlockData.estErr(21:60,:),[],'all');
  281. vars.sigma_y = sigma_y;
  282. disp(vars.sigma_y)
  283. nTrials = 120;
  284. % Steps:
  285. % 1 -- use colorArray in modeling script instead of presented color
  286. % 2 -- run modeling script lots of times, take "average" of everything
  287. % you will use.
  288. % 3 -- create one structure to store data could be allDataStruct. Add
  289. % fields for each variable you will extract from model. Plug in
  290. % "averaged" model values to those fields for appropriate condition.
  291. % especially for STP and Entropy
  292. % 4 -- rerun behavioral analyses with averaged model data. Make sure to
  293. %run eye analysis for gazeAttention variable of bias regression
  294. %ismember list below is list of subjects with bad/no eye data, so gaze
  295. %attention is set to zero
  296. if ~ismember(subNum,[2031,2085,2102,3004,3012,3013,7777,1001:1003])
  297. eyePath=sprintf('%s.mat',subStr);
  298. eyePath=[eyeDir,eyePath];
  299. resultEye = eyeAnalysis(eyePath,timeBeforeEye, timeAfterEye, blinkWindow,subStr,basePath,DP,smuPath);
  300. if allDataStruct.condition(1)==1
  301. CPgazeAttention=[resultEye.gazeAttention(1:nTrials,1);resultEye.gazeAttention(1:nTrials,2)];
  302. OBgazeAttention=[resultEye.gazeAttention(nTrials+1:end,1);resultEye.gazeAttention(nTrials+1:end,2)];
  303. else
  304. OBgazeAttention=[resultEye.gazeAttention(1:nTrials,1);resultEye.gazeAttention(1:nTrials,2)];
  305. CPgazeAttention=[resultEye.gazeAttention(nTrials+1:end,1);resultEye.gazeAttention(nTrials+1:end,2)];
  306. end
  307. else
  308. CPgazeAttention=zeros(2*nTrials,1);
  309. OBgazeAttention=zeros(2*nTrials,1);
  310. end
  311. %preallocate variables for model loop
  312. allCPEntropy = [];
  313. allCPSurprise = [];
  314. allCPobjPE = [];
  315. allCPsubPE = [];
  316. allCPestErr = [];
  317. allCPmodelPred = [];
  318. allCPmodelEst = [];
  319. allOBEntropy = [];
  320. allOBSurprise =[];
  321. allOBobjPE =[];
  322. allOBsubPE =[];
  323. allOBestErr = [];
  324. allOBmodelPred = [];
  325. allOBmodelEst = [];
  326. %model runs multiple times and takes average surprise, entropy, etc of
  327. %all runs. More runs = more runtime, but also higher accuracy
  328. for i = 1:numModelReps
  329. % Get surprise and entropy for changepoint trials:
  330. vars.treatOBCP = 0;
  331. dataCP = modelCP(vars);
  332. allCPEntropy=[allCPEntropy; dataCP.entropyCP'];
  333. allCPSurprise=[allCPSurprise; dataCP.surpriseCP'];
  334. allCPobjPE=[allCPobjPE;dataCP.predictionErrorOnX'];
  335. allCPestErr=[allCPestErr;dataCP.perceptualErrorOnX'];
  336. allCPsubPE=[allCPsubPE;dataCP.predErrorCP'];
  337. allCPmodelPred=[allCPmodelPred;dataCP.maxLikePostMu'];
  338. allCPmodelEst=[allCPmodelEst;dataCP.maxLikePostX'];
  339. % Get surprise and entropy for oddball trials:
  340. dataOB = modelOB(vars);
  341. allOBEntropy=[allOBEntropy; dataOB.entropyOB'];
  342. allOBSurprise=[allOBSurprise; dataOB.surpriseOB'];
  343. allOBobjPE=[allOBobjPE;dataOB.predictionErrorOnB'];
  344. allOBestErr=[allOBestErr;dataOB.perceptualErrorOnB'];
  345. allOBsubPE=[allOBsubPE;dataOB.predErrorOB'];
  346. allOBmodelPred=[allOBmodelPred;dataOB.maxLikePostC'];
  347. allOBmodelEst=[allOBmodelEst;dataOB.maxLikePostB'];
  348. if mod(i,10)==0
  349. disp(i)
  350. end
  351. end
  352. %calculates learning rate with correction
  353. %correction is if difference between prediction update and prediction
  354. %error is >3*pi/2, prediction update gets "bumped" to have the same
  355. %sign as pred error
  356. predictions = allDataStruct.pred;
  357. outcomes = (allDataStruct.est);
  358. newBlock = 121;
  359. %run CLR function (done twice, one for left and right stimulus
  360. [LR1,UP1,subPE1] = computeLearningRate(outcomes(:,1),predictions(:,1),newBlock,'polarHalfCorrect');
  361. [LR2,UP2,subPE2] = computeLearningRate(outcomes(:,2),predictions(:,2),newBlock,'polarHalfCorrect');
  362. adjPE = [subPE1,subPE2];
  363. UP = [UP1,UP2;nan,nan];
  364. LR = [LR1,LR2;nan,nan];
  365. bias = allDataStruct.estErr(:,:)./allDataStruct.predictErr(:,:);
  366. % order learning and bias based on trial order
  367. if allDataStruct.condition(1) == 1
  368. LRCP = [LR(1:nTrials,1);LR(1:nTrials,2)];
  369. LROB = [LR(nTrials+1:end,1);LR(nTrials+1:end,2)];
  370. biasCP = [bias(1:nTrials,1);bias(1:nTrials,2)];
  371. biasOB = [bias(nTrials+1:end,1);bias(nTrials+1:end,2)];
  372. else
  373. LRCP = [LR(nTrials+1:end,1);LR(nTrials+1:end,2)];
  374. LROB = [LR(1:nTrials,1);LR(1:nTrials,2)];
  375. biasCP = [bias(1:nTrials,1);bias(1:nTrials,2)];
  376. biasOB = [bias(nTrials+1:end,1);bias(nTrials+1:end,2)];
  377. end
  378. %save variables in allDataStruct
  379. allDataStruct.entropyCP=mean(allCPEntropy, 1);
  380. allDataStruct.surpriseCP=mean(allCPSurprise,1);
  381. allDataStruct.entropyOB=mean(allOBEntropy,1);
  382. allDataStruct.surpriseOB=mean(allOBSurprise,1);
  383. allDataStruct.subNum=nan(size(allDataStruct.isRand));
  384. allDataStruct.subNum(:)=subNum;
  385. allDataStruct.blockCond=nan(size(allDataStruct.isRand));
  386. allDataStruct.OBgazeAttention = OBgazeAttention;
  387. allDataStruct.CPgazeAttention = CPgazeAttention;
  388. allDataStruct.perceptualErrorOnX=circ_mean(allCPestErr);
  389. allDataStruct.perceptualErrorOnB=circ_mean(allOBestErr);
  390. allDataStruct.predictionErrorOnX=circ_mean(allCPobjPE);
  391. allDataStruct.predictionErrorOnB=circ_mean(allOBobjPE);
  392. allDataStruct.subPredErrorCP=circ_mean(allCPsubPE);
  393. allDataStruct.subPredErrorOB=circ_mean(allOBsubPE);
  394. allDataStruct.maxLikePostX=circ_mean(deg2rad(allCPmodelEst));
  395. allDataStruct.maxLikePostMu=circ_mean(deg2rad(allCPmodelPred));
  396. allDataStruct.maxLikePostB=circ_mean(deg2rad(allOBmodelEst));
  397. allDataStruct.maxLikePostC=circ_mean(deg2rad(allOBmodelPred));
  398. allDataStruct.LRCP = LRCP;
  399. allDataStruct.LROB = LROB;
  400. allDataStruct.biasCP = biasCP;
  401. allDataStruct.biasOB = biasOB;
  402. %straighten allDataStruct for later selbehav function which requires
  403. %that all variables be the same length as # of trials
  404. allDataStruct = straightStruct(allDataStruct);
  405. % add blockCond (tells you what trials were in which condition) variable to aDS
  406. t=length(allDataStruct.isRand);
  407. if allDataStruct.condition(1)==1
  408. allDataStruct.blockCond(1:t/2)=1;
  409. allDataStruct.blockCond(t/2+1:end)=-1;
  410. else
  411. allDataStruct.blockCond(1:t/2)=-1;
  412. allDataStruct.blockCond(t/2+1:end)=1;
  413. end
  414. %Save subject's model calculated surprise,entropy,etc.
  415. %can use model values on future runs
  416. saveDir=[behaveDir,'allModelData',saveText,'/'];
  417. if s == 1
  418. mkdir(saveDir)
  419. end
  420. fn=fullfile(saveDir,[subStr,'_allBlockData.mat']);
  421. save(fn,'allDataStruct')
  422. %add allDataStruct to behaveAll, which is essentially a stack of all
  423. %the allDataStructs
  424. if isempty(behaveAll)
  425. behaveAll=allDataStruct;
  426. elseif exist('behaveAll')&& ~isempty(behaveAll)
  427. behaveAll=catBehav(allDataStruct,behaveAll);
  428. end
  429. toc
  430. end
  431. beep
  432. end
  433. % straighten behave all structure
  434. behaveAll=straightStruct(behaveAll);
  435. %save all subjects' model calculated surprise,entropy,etc.
  436. saveDir=[basePath];
  437. fn=fullfile(saveDir,['behaveAll',saveText,'.mat']);
  438. save(fn,'behaveAll')
  439. %% Raw Behavior
  440. % this code saves results for panels B and C of figures 3 and 4
  441. % preallocate variables for loop (specify allerrors/updates variables)
  442. oddballPredErrorAll = [];
  443. oddballPredUpdateAll = [];
  444. changepointPredErrorAll = [];
  445. changepointPredUpdateAll = [];
  446. oddballEstErrAll = [];
  447. oddballobjPredErrorAll = [];
  448. changepointEstErrAll = [];
  449. changepointobjPredErrorAll = [];
  450. allCPSurprise = [];
  451. allOBSurprise = [];
  452. nBlockTrials = 120;
  453. nTrials = 240;
  454. %specify which trials have no bias(first trial) and no learning (first & last
  455. nanTrialsBias = [1,121-rejTrialsPerBlock];
  456. nanTrialsLearning = [120-rejTrialsPerBlock,240-2*rejTrialsPerBlock];
  457. for subno = behaveSubs
  458. disp(subno)
  459. subnoStr = num2str(subno);
  460. s = find(behaveSubs==subno);
  461. %load behavior data
  462. behaveMat = sprintf('allsubCombined/%s_allBlockData.mat',subnoStr);
  463. file2 = fullfile(behaveDir,behaveMat);
  464. load(file2)
  465. allDataStruct = alldata;
  466. %load model generated parameters
  467. allModelData = load(fullfile(behaveDir,['allModelData',saveText,'/', subnoStr, '_allBlockData.mat']));
  468. allModelData = allModelData.allDataStruct;
  469. surpriseCP = reshape(allModelData.surpriseCP',[nBlockTrials,2]);
  470. surpriseOB = reshape(allModelData.surpriseOB',[nBlockTrials,2]);
  471. if allDataStruct.condition(1) == 1
  472. surprise = [surpriseCP;surpriseOB];
  473. else
  474. surprise = [surpriseOB;surpriseCP];
  475. end
  476. %separate reproduction error for blcoks 3 and 4
  477. b3Ts = 61+rejTrialsPerBlock:180;
  478. b4Ts = 181+rejTrialsPerBlock:300;
  479. estErr3 = [allDataStruct.estErr(b3Ts,1);allDataStruct.estErr(b3Ts,2)];
  480. estErr4 = [allDataStruct.estErr(b4Ts,1);allDataStruct.estErr(b4Ts,2)];
  481. %separate subjective prediciton error for blcoks 3 and 4
  482. subPredError3 = [allDataStruct.subPredErr(b3Ts,1);allDataStruct.subPredErr(b3Ts,2)];
  483. subPredError4 = [allDataStruct.subPredErr(b4Ts,1);allDataStruct.subPredErr(b4Ts,2)];
  484. %separate objective prediction error for blcoks 3 and 4
  485. objPredError3 = [allDataStruct.predictErr(b3Ts,1);allDataStruct.predictErr(b3Ts,2)];
  486. objPredError4 = [allDataStruct.predictErr(b4Ts,1);allDataStruct.predictErr(b4Ts,2)];
  487. %load shortened data (only blocks 3 and 4)
  488. behaveMat = sprintf('subCombined/%s_3and4BlockData.mat',subnoStr);
  489. file2 = fullfile(behaveDir,behaveMat);
  490. alldataShort = load(file2);
  491. %define predictions and outcomes(estimations for subjective)
  492. predictions = alldataShort.alldata.pred;
  493. outcomes = (alldataShort.alldata.est);
  494. newBlock = nBlockTrials + 1;
  495. %run CLR function (done twice, one for left and right stimulus
  496. [LR1,UP1,~] = computeLearningRate(outcomes(:,1),predictions(:,1),newBlock,'polarHalfCorrect');
  497. [LR2,UP2,~] = computeLearningRate(outcomes(:,2),predictions(:,2),newBlock,'polarHalfCorrect');
  498. %concatenate LR UP and PE
  499. LR3 = [LR1(rejTrialsPerBlock+1:nBlockTrials-1);LR2(rejTrialsPerBlock+1:nBlockTrials-1)];
  500. LR4 = [LR1(nBlockTrials+rejTrialsPerBlock+1:end);LR2(nBlockTrials+rejTrialsPerBlock+1:end)];
  501. UP3 = [UP1(rejTrialsPerBlock+1:nBlockTrials-1);UP2(rejTrialsPerBlock+1:nBlockTrials-1)];
  502. UP4 = [UP1(nBlockTrials+rejTrialsPerBlock+1:end);UP2(nBlockTrials+rejTrialsPerBlock+1:end)];
  503. %nan trials with no learning (first and last) or no bias (first)
  504. learningTrials = true(nTrials-2*rejTrialsPerBlock,1);
  505. biasTrials = true(nTrials-2*rejTrialsPerBlock,1);
  506. learningTrials(nanTrialsLearning) = false;
  507. biasTrials(nanTrialsBias) = false;
  508. %specify which block (3 or 4) of data is CP/OB
  509. if allDataStruct.condition(1) == 1
  510. oddballPredError = subPredError4(learningTrials);
  511. oddballPredUpdate = UP4;
  512. oddballobjPredError = objPredError4(biasTrials);
  513. oddballEstErr = estErr4(biasTrials);
  514. changepointPredError = subPredError3(learningTrials);
  515. changepointPredUpdate = UP3;
  516. changepointobjPredError = objPredError3(biasTrials);
  517. changepointEstErr = estErr3(biasTrials);
  518. else
  519. oddballPredError = subPredError3(learningTrials);
  520. oddballPredUpdate = UP3;
  521. oddballobjPredError = objPredError3(biasTrials);
  522. oddballEstErr = estErr3(biasTrials);
  523. changepointPredError = subPredError4(learningTrials);
  524. changepointPredUpdate = UP4;
  525. changepointobjPredError = objPredError4(biasTrials);
  526. changepointEstErr = estErr4(biasTrials);
  527. end
  528. %add subject's data to all data variables
  529. oddballPredErrorAll = [oddballPredErrorAll;oddballPredError];
  530. oddballPredUpdateAll = [oddballPredUpdateAll;oddballPredUpdate];
  531. changepointPredErrorAll = [changepointPredErrorAll;changepointPredError];
  532. changepointPredUpdateAll = [changepointPredUpdateAll;changepointPredUpdate];
  533. oddballEstErrAll = [oddballEstErrAll;oddballEstErr];
  534. oddballobjPredErrorAll = [oddballobjPredErrorAll;oddballobjPredError];
  535. changepointEstErrAll = [changepointEstErrAll;changepointEstErr];
  536. changepointobjPredErrorAll = [changepointobjPredErrorAll;changepointobjPredError];
  537. subsEstErr(s) = mean(abs(allDataStruct.estErr),'all');
  538. subsEstErrL(s) = mean(abs(allDataStruct.estErr(:,1)));
  539. subsEstErrR(s) = mean(abs(allDataStruct.estErr(:,2)));
  540. %calculate average pred err on non surprise trials
  541. allDataStruct.predictErr(1:60,:)=[];
  542. allDataStruct.subPredErr(1:60,:)=[];
  543. subsObjPredErr(s) = nanmean(abs(allDataStruct.predictErr(surprise<0.25)),'all');
  544. subsSubPredErr(s) = nanmean(abs(allDataStruct.subPredErr(surprise<0.25)),'all');
  545. subsObjPredErrL(s) = nanmean(abs(allDataStruct.predictErr(surprise(:,1)<0.25,1)));
  546. subsObjPredErrR(s) = nanmean(abs(allDataStruct.predictErr(surprise(:,2)<0.25,2)));
  547. %adjust bias and learning rate to be between 0 and 1
  548. biasL = allDataStruct.estErr(61:end,1)./allDataStruct.predictErr(:,1);
  549. biasR = allDataStruct.estErr(61:end,2)./allDataStruct.predictErr(:,2);
  550. biasL(biasL>1) = 1;
  551. biasR(biasR>1) = 1;
  552. biasL(biasL<0) = 0;
  553. biasR(biasR<0) = 0;
  554. subsBiasL(s) = nanmean(biasL);
  555. subsBiasR(s) = nanmean(biasR);
  556. LRL = LR1;
  557. LRR = LR2;
  558. LRL(LRL>1) = 1;
  559. LRR(LRR>1) = 1;
  560. LRL(LRL<0) = 0;
  561. LRR(LRR<0) = 0;
  562. subsLRL(s) = nanmean(LRL);
  563. subsLRR(s) = nanmean(LRR);
  564. % subsObjPredErrL(s) = nanmean(abs(allDataStruct.subPredErr(:,1)));
  565. % subsObjPredErrR(s) = nanmean(abs(allDataStruct.subPredErr(:,2)));
  566. % subsObjPredErr(s) = nanmean(abs(allDataStruct.subPredErr),'all');
  567. % subsSubPredErr(s) = nanmean(abs(allDataStruct.predictErr),'all');
  568. end
  569. %calculate median est/pred err for "good subs" plot threshold, and find list of good subs
  570. medianEstErr=median(subsEstErr);
  571. goodEstSubs = subsEstErr<medianEstErr;
  572. medianObjPredErr=median(subsObjPredErr);
  573. goodPredSubs = subsObjPredErr<medianObjPredErr;
  574. %selects out trials for good subjects for both estimation and prediction
  575. goodEstSel = reshape(repmat(goodEstSubs,nTrials-2*rejTrialsPerBlock,1),[],1);
  576. goodPredSel = reshape(repmat(goodPredSubs,nTrials-2*rejTrialsPerBlock-2,1),[],1);
  577. % steps for these loops
  578. % 1 - preallocate quantile borders
  579. % 2 - add trials in a quantile to that quantile
  580. % 3 - find mean error/update for that quantile
  581. % 4 - repeat until quantiles are filled
  582. % 5 - repeat whole process for bias and learning for all and good subjects
  583. nBins = 40;
  584. bordersAllCP = quantile(changepointobjPredErrorAll,nBins-1);
  585. bordersAllOB = quantile(oddballobjPredErrorAll,nBins-1);
  586. quantilesAllOB = zeros(size(oddballobjPredErrorAll,1),1);
  587. quantilesAllCP = zeros(size(changepointobjPredErrorAll,1),1);
  588. for q = nBins:-1:1
  589. %defines everything below a border as in that bin in descending order
  590. if q<nBins
  591. quantilesAllCP(changepointobjPredErrorAll<=bordersAllCP(q)) = q;
  592. quantilesAllOB(oddballobjPredErrorAll<=bordersAllOB(q)) = q;
  593. else
  594. quantilesAllCP(changepointobjPredErrorAll>bordersAllCP(q-1)) = q;
  595. quantilesAllOB(oddballobjPredErrorAll>bordersAllOB(q-1)) = q;
  596. end
  597. end
  598. %find mean estimation error (y) and objective prediction error (x) for each
  599. %bin for plotting (Figure 3B)
  600. for q = 1:nBins
  601. meanQuantilesCPAllErrBias(q) = mean(changepointEstErrAll(quantilesAllCP==q));
  602. meanQuantilesOBAllErrBias(q) = mean(oddballEstErrAll(quantilesAllOB==q));
  603. quantileAllCPxesBias(q) = mean(changepointobjPredErrorAll(quantilesAllCP==q));
  604. quantileAllOBxesBias(q) = mean(oddballobjPredErrorAll(quantilesAllOB==q));
  605. end
  606. bordersAllCP = quantile(changepointPredErrorAll,nBins-1);
  607. bordersAllOB = quantile(oddballPredErrorAll,nBins-1);
  608. quantilesAllOB = zeros(size(oddballPredErrorAll,1),1);
  609. quantilesAllCP = zeros(size(changepointPredErrorAll,1),1);
  610. for q = nBins:-1:1
  611. %defines everything below a border as in that bin in descending order
  612. if q<nBins
  613. quantilesAllCP(changepointPredErrorAll<=bordersAllCP(q)) = q;
  614. quantilesAllOB(oddballPredErrorAll<=bordersAllOB(q)) = q;
  615. else
  616. quantilesAllCP(changepointPredErrorAll>bordersAllCP(q-1)) = q;
  617. quantilesAllOB(oddballPredErrorAll>bordersAllOB(q-1)) = q;
  618. end
  619. end
  620. %find mean pred update (y) and subjective prediction error (x) for each
  621. %bin for plotting (Figure 4B)
  622. for q = 1:nBins
  623. meanQuantilesCPAllErrLR(q) = mean(changepointPredUpdateAll(quantilesAllCP==q));
  624. meanQuantilesOBAllErrLR(q) = mean(oddballPredUpdateAll(quantilesAllOB==q));
  625. quantileAllCPxesLR(q) = mean(changepointPredErrorAll(quantilesAllCP==q));
  626. quantileAllOBxesLR(q) = mean(oddballPredErrorAll(quantilesAllOB==q));
  627. end
  628. %repeat above process for good subjects (subjects with below median est/pred err) for figures 3C and 4C
  629. changepointobjPredErrorGood = changepointobjPredErrorAll(goodEstSel);
  630. oddballobjPredErrorGood = oddballobjPredErrorAll(goodEstSel);
  631. changepointEstErrGood = changepointEstErrAll(goodEstSel);
  632. oddballEstErrGood = oddballEstErrAll(goodEstSel);
  633. bordersGoodCP = quantile(changepointobjPredErrorGood,nBins-1);
  634. bordersGoodOB = quantile(oddballobjPredErrorGood,nBins-1);
  635. quantilesGoodOB = zeros(size(oddballobjPredErrorGood,1),1);
  636. quantilesGoodCP = zeros(size(changepointobjPredErrorGood,1),1);
  637. for q = nBins:-1:1
  638. if q<nBins
  639. quantilesGoodCP(changepointobjPredErrorGood<=bordersGoodCP(q)) = q;
  640. quantilesGoodOB(oddballobjPredErrorGood<=bordersGoodOB(q)) = q;
  641. else
  642. quantilesGoodCP(changepointobjPredErrorGood>bordersGoodCP(q-1)) = q;
  643. quantilesGoodOB(oddballobjPredErrorGood>bordersGoodOB(q-1)) = q;
  644. end
  645. end
  646. %These values go into Figure 3C
  647. for q = 1:nBins
  648. meanQuantilesCPGoodErrBias(q) = mean(changepointEstErrGood(quantilesGoodCP==q));
  649. meanQuantilesOBGoodErrBias(q) = mean(oddballEstErrGood(quantilesGoodOB==q));
  650. quantileGoodCPxesBias(q) = mean(changepointobjPredErrorGood(quantilesGoodCP==q));
  651. quantileGoodOBxesBias(q) = mean(oddballobjPredErrorGood(quantilesGoodOB==q));
  652. end
  653. changepointPredErrorGood = changepointPredErrorAll(goodPredSel);
  654. oddballPredErrorGood = oddballPredErrorAll(goodPredSel);
  655. changepointPredUpdateGood = changepointPredUpdateAll(goodPredSel);
  656. oddballPredUpdateGood = oddballPredUpdateAll(goodPredSel);
  657. nBins = 40;
  658. bordersGoodCP = quantile(changepointPredErrorGood,nBins-1);
  659. bordersGoodOB = quantile(oddballPredErrorGood,nBins-1);
  660. quantilesGoodOB = zeros(size(oddballPredErrorGood,1),1);
  661. quantilesGoodCP = zeros(size(changepointPredErrorGood,1),1);
  662. for q = nBins:-1:1
  663. if q<nBins
  664. quantilesGoodCP(changepointPredErrorGood<=bordersGoodCP(q)) = q;
  665. quantilesGoodOB(oddballPredErrorGood<=bordersGoodOB(q)) = q;
  666. else
  667. quantilesGoodCP(changepointPredErrorGood>bordersGoodCP(q-1)) = q;
  668. quantilesGoodOB(oddballPredErrorGood>bordersGoodOB(q-1)) = q;
  669. end
  670. end
  671. %These values go into Figure 4C
  672. for q = 1:nBins
  673. meanQuantilesCPGoodUpLR(q) = mean(changepointPredUpdateGood(quantilesGoodCP==q));
  674. meanQuantilesOBGoodUpLR(q) = mean(oddballPredUpdateGood(quantilesGoodOB==q));
  675. quantileGoodCPxesLR(q) = mean(changepointPredErrorGood(quantilesGoodCP==q));
  676. quantileGoodOBxesLR(q) = mean(oddballPredErrorGood(quantilesGoodOB==q));
  677. end
  678. %calculate subject's standard deviations of errors and add subject's errors to list of all errors made by all subjects
  679. %These values are used for the supplementary bias figure
  680. for s = 1:length(behaveSubs)
  681. subno = behaveSubs(s);
  682. subNum = num2str(subno);
  683. allData=load(fullfile([behaveDir,'allSubCombined/', subNum, '_allBlockData.mat']));
  684. allData=allData.alldata;
  685. estErrPractice = allData.estErr(21:60,:);
  686. estErrPred = allData.estErr(61:300,:);
  687. predErrPred = allData.predictErr([62:180,182:end],:);
  688. allEstErrPractice(:,:,s) = estErrPractice;
  689. allEstErrPred(:,:,s) = estErrPred;
  690. allPredErrPred(:,:,s) = predErrPred;
  691. stdSubEstPractice(s) = std(estErrPractice,0,'all');
  692. stdSubEstPred(s) = std(estErrPred,0,'all');
  693. stdSubPredPred(s) = std(predErrPred,0,'all');
  694. meanSubEstPractice(s) = mean(abs(estErrPractice),'all');
  695. meanSubEstPred(s) = mean(abs(estErrPred),'all');
  696. meanSubPredPred(s) = mean(abs(predErrPred),'all');
  697. end
  698. numPractice = numel(allEstErrPractice);
  699. numPred = numel(allEstErrPred);
  700. pPracticeErrs = ttest(meanSubEstPractice);
  701. pPredBlockErrs = ttest(meanSubEstPred);
  702. %calculate subject level variance of error
  703. varSubEstPractice = stdSubEstPractice.*stdSubEstPractice;
  704. varSubPredPred = stdSubPredPred.*stdSubPredPred;
  705. %calculate predicted std based on bayesian combination
  706. predictedVar = 1./((1./varSubPredPred)+(1./varSubEstPractice));
  707. predictedStd = sqrt(predictedVar);
  708. %plot figure S1
  709. %panel A practice est err vs task est err
  710. figure("Position",[250,250,1200,330])
  711. subplot(1,3,1)
  712. scatter(meanSubEstPractice,meanSubEstPred,20,[.5,.5,.5],'filled','MarkerEdgeColor','k');
  713. [h,pEsts,~,statsEsts] = ttest(meanSubEstPractice-meanSubEstPred);
  714. hold on
  715. plot([0,1.22],[0,1.22],"--k","LineWidth",0.25);
  716. xlabel("Calibration Estimation μ","FontSize",11)
  717. ylabel("Task Estimation μ","FontSize",11)
  718. ylim([0,1.22])
  719. xlim([0,1.22])
  720. xticks(0:0.5:1.5)
  721. yticks(0:0.5:1.5)
  722. set(gca, 'box', 'off')
  723. set(gca,"FontName","Arial","FontWeight","bold","FontSize",14)
  724. %panel B pred err vs task est err
  725. subplot(1,3,2)
  726. scatter(meanSubPredPred,meanSubEstPred,20,[.5,.5,.5],'filled','MarkerEdgeColor','k');
  727. [h,pEstPred,~,statsPred] = ttest(meanSubPredPred-meanSubEstPred);
  728. hold on
  729. plot([0,1.6],[0,1.6],"--k","LineWidth",0.25);
  730. xlabel("Task Prediction μ","FontSize",11)
  731. ylabel("Task Estimation μ","FontSize",11)
  732. ylim([0,1.6])
  733. xlim([0,1.6])
  734. xticks(0:0.5:1.5)
  735. yticks(0:0.5:1.5)
  736. set(gca, 'box', 'off')
  737. set(gca,"FontName","Arial","FontWeight","bold","FontSize",14)
  738. %panel C predicted err based on bayesian combination vs task est err
  739. subplot(1,3,3)
  740. scatter(predictedStd,stdSubEstPred,20,[.5,.5,.5],'filled','MarkerEdgeColor','k');
  741. [h,pModel,~,statsModel] = ttest(predictedStd-stdSubEstPred);
  742. hold on
  743. plot([0,1],[0,1],"--k","LineWidth",0.25);
  744. ylabel("Task Estimation σ","FontSize",11)
  745. xlabel("Bayesian Predicted σ","FontSize",11)
  746. ylim([0,1])
  747. xlim([0,1])
  748. xticks(0:0.5:1.5)
  749. yticks(0:0.5:1.5)
  750. set(gca, 'box', 'off')
  751. set(gca,"FontName","Arial","FontWeight","bold","FontSize",14)
  752. % save figure S1
  753. if doSTPResiduals == 0
  754. fig = gcf;
  755. figName = append("Figure_S1_",figTime,'.eps');
  756. figLoc = append(figDir,figName);
  757. exportgraphics(fig,figLoc,'BackgroundColor','none','ContentType','vector')
  758. figName = append("Figure_S1_",figTime,'.png');
  759. figLoc = append(figDir,figName);
  760. saveas(fig,figLoc)
  761. else
  762. fig = gcf;
  763. figName = append("Figure_S1_Residual_",figTime,'.eps');
  764. figLoc = append(figDir,figName);
  765. exportgraphics(fig,figLoc,'BackgroundColor','none','ContentType','vector')
  766. figName = append("Figure_S1_Residual",figTime,'.png');
  767. figLoc = append(figDir,figName);
  768. saveas(fig,figLoc)
  769. end
  770. %%
  771. % figure
  772. % scatter(subsObjPredErrL*180/pi,subsObjPredErrR*180/pi,20,[.5,.5,.5],'filled','MarkerEdgeColor','k');
  773. % hold on
  774. % plot([0,max(subsObjPredErrR*180/pi)],[0,max(subsObjPredErrR*180/pi)],'k--')
  775. % ylabel("Mean Right Prediction Error")
  776. % xlabel("Mean Left Prediction Error")
  777. % set(gca, 'box', 'off')
  778. % set(gca,"FontName","Arial","FontWeight","bold","FontSize",14)
  779. %% Run Behavioral regression
  780. % preallocate variables for loop
  781. %This section will generate results for figure 3D and 4D
  782. %also some of the values used here will be used for other figures
  783. %i.e behavioral values in oddball pupil figure, and good/bad eeg/pupil plots
  784. paramsCircUpdateAll=[];
  785. paramsCircBiasAll =[];
  786. paramsCircUpdateAllModel=[];
  787. paramsCircBiasAllModel =[];
  788. normalizedCoefUpdate=[];
  789. normalizedCoefBias=[];
  790. %specify which trials will be included in regression
  791. %Maybe later we'll add an early vs late regression here for learning task?
  792. if rejTrialsPerBlock == 0
  793. noTrial = [1,120,121,240,241,360,361,480];
  794. else
  795. noTrial = [1:rejTrialsPerBlock,120,121:rejTrialsPerBlock+120,240,241:rejTrialsPerBlock+240,360,361:rejTrialsPerBlock+360,480];
  796. end
  797. LRTrial = true(480,1);
  798. LRTrial(noTrial) = false;
  799. %remove initial prediction from model prediction variable so it lines up with the rest
  800. behaveAll.modelPredCP = behaveAll.maxLikePostMu;
  801. behaveAll.modelPredCP(1:241:end) = [];
  802. behaveAll.modelPredOB = behaveAll.maxLikePostC;
  803. behaveAll.modelPredOB(1:241:end) = [];
  804. for s=1:length(behaveSubs)
  805. subNum=behaveSubs(s);
  806. subStr=num2str(subNum);
  807. disp(subNum)
  808. %get eye data
  809. % Get useful variables for descriptive analyses:
  810. decomposeSine=0;
  811. decomposeCosine=0;
  812. nTrials = 120; %length(behaveAll.block(behaveAll.subNum==subNum))*.5;
  813. %find subject's model variables (separate for cp and ob)
  814. %X and Mu are CP variables, B and C are OB variables
  815. OBpredErrorSubModel = behaveAll.subPredErrorOB(behaveAll.subNum==subNum);
  816. CPpredErrorSubModel = behaveAll.subPredErrorCP(behaveAll.subNum==subNum);
  817. perceptualErrorOnXModel = behaveAll.perceptualErrorOnX(behaveAll.subNum==subNum);
  818. perceptualErrorOnBModel = behaveAll.perceptualErrorOnB(behaveAll.subNum==subNum);
  819. CPpredErrorModel = behaveAll.predictionErrorOnX(behaveAll.subNum==subNum);
  820. OBpredErrorModel = behaveAll.predictionErrorOnB(behaveAll.subNum==subNum);
  821. CPupdateModel = behaveAll.modelPredCP(behaveAll.subNum==subNum);
  822. OBupdateModel = behaveAll.modelPredOB(behaveAll.subNum==subNum);
  823. %certain run's predictions are in degrees and some are in radians, so
  824. %this converts any that are in degrees to radians
  825. if max(behaveAll.modelPredCP(behaveAll.subNum==subNum))>100
  826. CPupdateModel = deg2rad(CPupdateModel);
  827. OBupdateModel = deg2rad(OBupdateModel);
  828. end
  829. CPupdateModel = [nan;circ_dist(CPupdateModel(2:end),CPupdateModel(1:end-1))];
  830. OBupdateModel = [nan;circ_dist(OBupdateModel(2:end),OBupdateModel(1:end-1))];
  831. %find subject's error/update variables
  832. OBpredError = [behaveAll.predictErr(behaveAll.subNum==subNum & behaveAll.blockCond==-1,1);behaveAll.predictErr(behaveAll.subNum==subNum & behaveAll.blockCond==-1,2)];
  833. CPpredError = [behaveAll.predictErr(behaveAll.subNum==subNum & behaveAll.blockCond==1,1);behaveAll.predictErr(behaveAll.subNum==subNum & behaveAll.blockCond==1,2)];
  834. OBpredErrorSub = [behaveAll.subPredErr(behaveAll.subNum==subNum & behaveAll.blockCond==-1,1);behaveAll.subPredErr(behaveAll.subNum==subNum & behaveAll.blockCond==-1,2)];
  835. CPpredErrorSub = [behaveAll.subPredErr(behaveAll.subNum==subNum & behaveAll.blockCond==1,1);behaveAll.subPredErr(behaveAll.subNum==subNum & behaveAll.blockCond==1,2)];
  836. OBupdate = [behaveAll.predUpdate(behaveAll.subNum==subNum & behaveAll.blockCond==-1,1);behaveAll.predUpdate(behaveAll.subNum==subNum & behaveAll.blockCond==-1,2)];
  837. CPupdate = [behaveAll.predUpdate(behaveAll.subNum==subNum & behaveAll.blockCond==1,1);behaveAll.predUpdate(behaveAll.subNum==subNum & behaveAll.blockCond==1,2)];
  838. perceptualErrorOnX = [behaveAll.estErr(behaveAll.subNum==subNum & behaveAll.blockCond==1,1);behaveAll.estErr(behaveAll.subNum==subNum & behaveAll.blockCond==1,2)];
  839. perceptualErrorOnB = [behaveAll.estErr(behaveAll.subNum==subNum & behaveAll.blockCond==-1,1);behaveAll.estErr(behaveAll.subNum==subNum & behaveAll.blockCond==-1,2)];
  840. %extract subjects surprise, entropy, lr, bias, condition from
  841. %behaveall
  842. OBsurprise = behaveAll.surpriseOB(behaveAll.subNum==subNum);
  843. CPsurprise = behaveAll.surpriseCP(behaveAll.subNum==subNum);
  844. OBentropy = behaveAll.entropyOB(behaveAll.subNum==subNum);
  845. CPentropy = behaveAll.entropyCP(behaveAll.subNum==subNum);
  846. CPLR = [behaveAll.LRCP(behaveAll.subNum==subNum)];
  847. CPBias = [behaveAll.biasCP(behaveAll.subNum==subNum)];
  848. OBLR = [behaveAll.LROB(behaveAll.subNum==subNum)];
  849. OBBias = [behaveAll.biasOB(behaveAll.subNum==subNum)];
  850. conNum=behaveAll.blockCond(behaveAll.subNum==subNum);
  851. condNum=[conNum(1:nTrials);conNum(1:nTrials);conNum(nTrials+1:end);conNum(nTrials+1:end)];
  852. if conNum(1) == 1
  853. condition=1;
  854. else
  855. condition=2;
  856. end
  857. %other variables for regressions and uniform model
  858. predictionErrorOnX = [behaveAll.predictionErrorOnX(behaveAll.subNum==subNum)];
  859. predictionErrorOnB = [behaveAll.predictionErrorOnB(behaveAll.subNum==subNum)];
  860. OBsurpriseTrialNum=sum(nansum(behaveAll.surpriseTrial(behaveAll.subNum==subNum & behaveAll.blockCond==-1,:)));
  861. CPsurpriseTrialNum=sum(nansum(behaveAll.surpriseTrial(behaveAll.subNum==subNum & behaveAll.blockCond==1,:)));
  862. CPgazeAttention=[behaveAll.CPgazeAttention(behaveAll.subNum==subNum,:)];
  863. OBgazeAttention=[behaveAll.OBgazeAttention(behaveAll.subNum==subNum,:)];
  864. subjectPEobj=[OBpredError;CPpredError];
  865. modelPEobj=[predictionErrorOnB;predictionErrorOnX];
  866. subModPEobjDiff=modelPEobj-subjectPEobj;
  867. subModPEobjDiffModel= modelPEobj-[OBpredErrorModel;CPpredErrorModel];
  868. clear data
  869. data.signedError=subModPEobjDiff;
  870. data.signedError_allTargs=[];
  871. whichParams=[1 1 0 0];
  872. data.doFit=true;
  873. %mixture model to calcultate uniform probability
  874. % data.signedError --> signed errors (or just angles if not for VWM task)
  875. % data.signedError_allTargs --> errors computed as if subject were
  876. % estimating all of the colors in the array (ie colorArray - subject
  877. % response).
  878. % data.xMat --> all variables that could affect recall or precision
  879. % data.doFit --> fit? if not, just evaluate at startPoint
  880. %params: maximum likelihood model parameters,
  881. % 1= proportion gaussian,
  882. % 2= concentration (ie 1./sigma^2) of von mises,
  883. % 3= mean of gaussian (should be zero... but who knows!)
  884. % 4= proportion binding error (ie propr of gaussian that are evenly distributed across targets)
  885. % simplex order: gaussian, binding error, uniform
  886. [~,~,~, uniformProb]=fit_VWM_mixtureModelTrial(data,whichParams);
  887. data.signedError=subModPEobjDiffModel;
  888. data.signedError_allTargs=[];
  889. [~,~,~, uniformProbModel]=fit_VWM_mixtureModelTrial(data,whichParams);
  890. side = [ones(nBlockTrials,1);ones(nBlockTrials,1)*-1;ones(nBlockTrials,1);ones(nBlockTrials,1)*-1];
  891. if condition==1
  892. gazeAttention=[CPgazeAttention;OBgazeAttention];
  893. entropy = [nanzscore(CPentropy);nanzscore(OBentropy)];
  894. else
  895. gazeAttention=[OBgazeAttention;CPgazeAttention];
  896. entropy = [nanzscore(OBentropy);nanzscore(CPentropy)];
  897. end
  898. % Regression for Prediction Update
  899. % xes and ys for both model and subject based regressions
  900. % only differences are condition (OB or CP First) or the fact that the
  901. % model is using model prediction errors
  902. if condition==1
  903. xes = [ ones(4*nTrials,1), ... %This is one that actually gets used
  904. ([CPpredErrorSub;OBpredErrorSub]),...
  905. ([CPpredErrorSub;OBpredErrorSub] .* nanzscore([CPsurprise;OBsurprise]).* condNum),...
  906. ([CPpredErrorSub;OBpredErrorSub] .* nanzscore([CPsurprise;OBsurprise])),...
  907. ([CPpredErrorSub;OBpredErrorSub] .* entropy), ...
  908. ([CPpredErrorSub;OBpredErrorSub] .* condNum), ...
  909. ([CPpredErrorSub;OBpredErrorSub] .* nanzscore(round(uniformProb,9))), ...
  910. ([CPpredErrorSub;OBpredErrorSub] .* side)];
  911. xes = [xes(:,1),nanzscore(xes(:,2:end))];
  912. Y=[ CPupdate; OBupdate];
  913. xesMod = [ ones(4*nTrials,1), ... %This is one that actually gets used
  914. ([CPpredErrorSubModel;OBpredErrorSubModel]),...
  915. ([CPpredErrorSubModel;OBpredErrorSubModel] .* nanzscore([CPsurprise;OBsurprise]).* condNum),...
  916. ([CPpredErrorSubModel;OBpredErrorSubModel] .* nanzscore([CPsurprise;OBsurprise])),...
  917. ([CPpredErrorSubModel;OBpredErrorSubModel] .* entropy), ...
  918. ([CPpredErrorSubModel;OBpredErrorSubModel] .* condNum), ...
  919. ([CPpredErrorSubModel;OBpredErrorSubModel] .* nanzscore(round(uniformProb,9))), ...
  920. ([CPpredErrorSubModel;OBpredErrorSubModel] .* side)];
  921. xesMod = [xesMod(:,1),nanzscore(xesMod(:,2:end))];
  922. YMod=[ CPupdateModel; OBupdateModel];
  923. else
  924. xes = [ ones(4*nTrials,1), ... %This is one that actually gets used
  925. ([OBpredErrorSub;CPpredErrorSub]),...
  926. ([OBpredErrorSub;CPpredErrorSub] .* nanzscore([OBsurprise;CPsurprise]) .* condNum),...
  927. ([OBpredErrorSub;CPpredErrorSub] .* nanzscore([OBsurprise;CPsurprise])),...
  928. ([OBpredErrorSub;CPpredErrorSub] .* entropy), ...
  929. ([OBpredErrorSub;CPpredErrorSub] .* condNum), ...
  930. ([OBpredErrorSub;CPpredErrorSub] .* nanzscore(round(uniformProb,9))), ...
  931. ([OBpredErrorSub;CPpredErrorSub] .* side)];
  932. xes = [xes(:,1),nanzscore(xes(:,2:end))];
  933. Y=[OBupdate; CPupdate];
  934. xesMod = [ ones(4*nTrials,1), ... %This is one that actually gets used
  935. ([OBpredErrorSubModel;CPpredErrorSubModel]),...
  936. ([OBpredErrorSubModel;CPpredErrorSubModel] .* nanzscore([OBsurprise;CPsurprise]) .* condNum),...
  937. ([OBpredErrorSubModel;CPpredErrorSubModel] .* nanzscore([OBsurprise;CPsurprise])),...
  938. ([OBpredErrorSubModel;CPpredErrorSubModel] .* entropy), ...
  939. ([OBpredErrorSubModel;CPpredErrorSubModel] .* condNum), ...
  940. ([OBpredErrorSubModel;CPpredErrorSubModel] .* nanzscore(round(uniformProb,9))), ...
  941. ([OBpredErrorSubModel;CPpredErrorSubModel] .* side)];
  942. xesMod = [xesMod(:,1),nanzscore(xesMod(:,2:end))];
  943. YMod=[OBupdateModel; CPupdateModel];
  944. end
  945. %set up data for subject circular regression
  946. % data.Y = ydata
  947. % data.X = xdata
  948. % data.includeUniform = do you want to include a uniform mixture component? (yes)
  949. % data.whichParams = which parameters should we fit? (all)
  950. % data.startPoint = where should we start parameter search
  951. % data.lb = lower bound
  952. % data.ub = upper bound
  953. % data.priorMean = mean of gaussian parameter priors (should have one for each coefficient [NOT PRECISION OR MIXTURE parameters])
  954. % data.priorWidth = width of gaussian priors (same as above).
  955. % data.nStart = number of start points to use for optimizer
  956. regData.X=xes;
  957. regData.Y=Y;
  958. nanTrials = noTrial;
  959. regData.startPoint=[5,zeros(1,size(regData.X,2)),0.05];
  960. regData.whichParams=logical([ones(1,size(regData.X,2)+1),0]);
  961. regData.includeUniform=1;
  962. regData.priorMean=[0,0,0,0,0,0,0,0];
  963. regData.priorWidth=[1,1,narrowWidth,narrowWidth,narrowWidth,narrowWidth,narrowWidth,narrowWidth];
  964. %bounds for concentration are 0.0001-100, bounds for other parameters are LB and UB
  965. regData.lb=[.0001, ones(1, size(regData.X, 2)).*LB];
  966. regData.ub=[100, ones(1, size(regData.X, 2)).*UB];
  967. regData.nStart=nStart;
  968. regData.Y(nanTrials)=[];
  969. regData.X(nanTrials,:)=[];
  970. %parameters for model regression should be the same as the params for
  971. %the human regression
  972. regDataModel = regData;
  973. regDataModel.X = xesMod;
  974. regDataModel.Y = YMod;
  975. regDataModel.Y(nanTrials)=[];
  976. regDataModel.X(nanTrials,:)=[];
  977. %runs subject and model-behavior circular error model
  978. [paramsUpdate, negLogLikeUpdate]=fitLinearModWCircErrs(regData);
  979. [paramsUpdateModel, negLogLikeUpdateModel]=fitLinearModWCircErrs(regDataModel);
  980. % Regression for Perceptual Error
  981. % specify xes and ys for human and model
  982. if condition==1
  983. xes = [ ones(4*nTrials,1), ...
  984. ([CPpredError;OBpredError]),...
  985. ([CPpredError;OBpredError] .* [nanzscore(CPsurprise); nanzscore(OBsurprise)].* condNum),...
  986. ([CPpredError;OBpredError] .* [nanzscore(CPsurprise); nanzscore(OBsurprise)]),...
  987. ([CPpredError;OBpredError] .* entropy),...
  988. ([CPpredError;OBpredError] .* condNum), ...
  989. ([CPpredError;OBpredError] .* nanzscore(round(uniformProb,9))),...
  990. ([CPpredError;OBpredError] .* nanzscore(gazeAttention)), ...
  991. ([CPpredError;OBpredError] .* side)];
  992. xes = [xes(:,1),nanzscore(xes(:,2:end))];
  993. Y=[perceptualErrorOnX; perceptualErrorOnB];
  994. xesMod = [ ones(4*nTrials,1), ...
  995. ([CPpredErrorModel;OBpredErrorModel]),...
  996. ([CPpredErrorModel;OBpredErrorModel] .* [nanzscore(CPsurprise); nanzscore(OBsurprise)].* condNum),...
  997. ([CPpredErrorModel;OBpredErrorModel] .* [nanzscore(CPsurprise); nanzscore(OBsurprise)]),...
  998. ([CPpredErrorModel;OBpredErrorModel] .* entropy),...
  999. ([CPpredErrorModel;OBpredErrorModel] .* condNum), ...
  1000. ([CPpredErrorModel;OBpredErrorModel] .* nanzscore(round(uniformProb,9))),...
  1001. ([CPpredErrorModel;OBpredErrorModel] .* nanzscore(gazeAttention)), ...
  1002. ([CPpredErrorModel;OBpredErrorModel] .* side)];
  1003. xesMod = [xesMod(:,1),nanzscore(xesMod(:,2:end))];
  1004. YMod=[perceptualErrorOnXModel; perceptualErrorOnBModel];
  1005. else
  1006. xes = [ ones(4*nTrials,1), ...
  1007. ([OBpredError;CPpredError]),...
  1008. ([OBpredError;CPpredError] .* [nanzscore(OBsurprise); nanzscore(CPsurprise)].* condNum),...
  1009. ([OBpredError;CPpredError] .* [nanzscore(OBsurprise); nanzscore(CPsurprise)]),...
  1010. ([OBpredError;CPpredError] .* entropy),...
  1011. ([OBpredError;CPpredError] .* condNum), ...
  1012. ([OBpredError;CPpredError] .* nanzscore(round(uniformProb,9))),...
  1013. ([OBpredError;CPpredError] .* nanzscore(gazeAttention)), ...
  1014. ([OBpredError;CPpredError] .* side)];
  1015. xes = [xes(:,1),nanzscore(xes(:,2:end))];
  1016. Y=[perceptualErrorOnB; perceptualErrorOnX];
  1017. xesMod = [ ones(4*nTrials,1), ...
  1018. ([OBpredErrorModel;CPpredErrorModel]),...
  1019. ([OBpredErrorModel;CPpredErrorModel] .* [nanzscore(OBsurprise); nanzscore(CPsurprise)].* condNum),...
  1020. ([OBpredErrorModel;CPpredErrorModel] .* [nanzscore(OBsurprise); nanzscore(CPsurprise)]),...
  1021. ([OBpredErrorModel;CPpredErrorModel] .* entropy),...
  1022. ([OBpredErrorModel;CPpredErrorModel] .* condNum), ...
  1023. ([OBpredErrorModel;CPpredErrorModel] .* nanzscore(round(uniformProb,9))),...
  1024. ([OBpredErrorModel;CPpredErrorModel] .* nanzscore(gazeAttention)),...
  1025. ([OBpredErrorModel;CPpredErrorModel] .* side)];
  1026. xesMod = [xesMod(:,1),nanzscore(xesMod(:,2:end))];
  1027. YMod=[perceptualErrorOnBModel; perceptualErrorOnXModel];
  1028. end
  1029. %fill regData for circular models (see explanation of parameters above in prediction update model)
  1030. regData.X=xes;
  1031. regData.Y=Y;
  1032. regData.startPoint=[5,zeros(1,size(regData.X,2)),0.05];
  1033. regData.whichParams=logical([ones(1,size(regData.X,2)+1),0]);
  1034. regData.includeUniform=1;
  1035. regData.priorMean=[0,0,0,0,0,0,0,0,0];
  1036. regData.priorWidth=[1,1,narrowWidth,narrowWidth,narrowWidth,narrowWidth,narrowWidth,narrowWidth,narrowWidth];
  1037. regData.lb=[.0001, ones(1, size(regData.X, 2)).*LB];
  1038. regData.ub=[100, ones(1, size(regData.X, 2)).*UB];
  1039. regData.nStart=nStart;
  1040. regData.Y(nanTrials)=[];
  1041. regData.X(nanTrials,:)=[];
  1042. regDataModel = regData;
  1043. regDataModel.X = xesMod;
  1044. regDataModel.Y = YMod;
  1045. regDataModel.Y(nanTrials)=[];
  1046. regDataModel.X(nanTrials,:)=[];
  1047. %run circular models
  1048. [paramsBias, negLogLikeBias]=fitLinearModWCircErrs(regData);
  1049. [paramsBiasModel, negLogLikeBiasModel]=fitLinearModWCircErrs(regDataModel);
  1050. % Saving coefficient values
  1051. paramsCircUpdateAll=cat(1,paramsCircUpdateAll,paramsUpdate);
  1052. paramsCircBiasAll=cat(1,paramsCircBiasAll,paramsBias);
  1053. paramsCircUpdateAllModel=cat(1,paramsCircUpdateAllModel,paramsUpdateModel);
  1054. paramsCircBiasAllModel=cat(1,paramsCircBiasAllModel,paramsBiasModel);
  1055. end
  1056. %calculate p values for distributions of human coefficients for both models
  1057. for i = 1:size(paramsCircUpdateAll,2)
  1058. [~,pUp(i),~,statsUp] = ttest(paramsCircUpdateAll(:,i));
  1059. tStatUp(i) = statsUp.tstat;
  1060. end
  1061. for i = 1:size(paramsCircBiasAll,2)
  1062. [~,pBias(i),~,statsBias] = ttest(paramsCircBiasAll(:,i));
  1063. tStatBias(i) = statsBias.tstat;
  1064. end
  1065. %% Step 2: Load EEG/eye data & run regression
  1066. % Raw EEG data regression
  1067. if runEEGRegression == 1
  1068. for s = 1:length(EEGSubs)
  1069. subno=EEGSubs(s);
  1070. subNum=num2str(subno);
  1071. disp(subNum)
  1072. resultEEG=eeg_analysisFunc(subNum,saveText,dirs,rejEarlyTrials);
  1073. b_mat_eeg(s,:,:,:)=resultEEG.mat; %subject by channel by trial by regressor
  1074. end
  1075. saveDir=[basePath];
  1076. fn=fullfile(saveDir,['b_mat_eeg',saveText,'.mat']);
  1077. save(fn,'b_mat_eeg')
  1078. beep
  1079. end
  1080. %%
  1081. %Eye data Regression
  1082. for s=1:length(eyeSubs)
  1083. subno=eyeSubs(s);
  1084. subNum=num2str(subno);
  1085. disp(subNum)
  1086. %2 eye regressions, first for stimulus phase, second for prediction phase
  1087. resultEye=eyeRegressionFunc(subNum,saveText,timeBeforeEye,timeAfterEye,blinkWindow,baselineTimeEye,dirs,rejEarlyTrials);
  1088. resultEyePred=eyeRegressionPredResp(subNum,saveText,timeBeforePred,timeAfterPred,blinkWindow,baselineTimeStart,baselineTimeEnd,dirs,rejEarlyTrials);
  1089. %saves coefs for stim regression on pupil size and baseline effects
  1090. allBs(:,:,s) = resultEye.B;
  1091. BBaseline(s,:) = resultEye.BBaseline;
  1092. %saves coefs for prediction regression on pupil size and pupil derivative
  1093. allBsPred(:,:,s) = resultEyePred.B;
  1094. allDiffBsPred(:,:,s) = resultEyePred.diffB;
  1095. end
  1096. %permute from coef x timepoint x subs to subs x timepoint x coef
  1097. allBsPerm = permute(allBs,[3,2,1]);
  1098. allBsPredPerm = permute(allBsPred,[3,2,1]);
  1099. allBsDiffPerm = permute(allDiffBsPred,[3,2,1]);
  1100. %% Clustering/Permutation Test
  1101. %specify variables for permutation test (can remove these lines and specify
  1102. %above as well, but I spend a lot of time here messing with these numbers)
  1103. clustThreshEEG = 0.01;
  1104. clustThreshEye = 0.025;
  1105. connectThresh = 0.40;
  1106. %load channel locations
  1107. load("chanlocs.mat")
  1108. % NOTE EEG.dat
  1109. % GET CONNECTION MATRIX specifying which electrodes are connected to which:
  1110. % if exist('connectionMat.mat')
  1111. % load connectionMat.mat % if we've already got one made, load it.
  1112. % else
  1113. % otherwise, create one from scratch:
  1114. % Then get the XYZ coordinates for each channel:
  1115. clear eye
  1116. allLocas=[[chanlocs.X]; [chanlocs.Y]; [chanlocs.Z]]' ;
  1117. % Loop through the channels and get the distance between that channel and
  1118. % all other channels.
  1119. for i = 1:length(allLocas)
  1120. relDist(:,i)=sqrt(sum((allLocas-repmat(allLocas(i,:), length(allLocas), 1)).^2, 2));
  1121. end
  1122. % Set a threshold on distance... and mark channels that fall within that threshold:
  1123. connectionMat=relDist<connectThresh;
  1124. connectionMat=connectionMat-eye(length(connectionMat));
  1125. % CHECK OUT CONNECTIONS:
  1126. % figure
  1127. % imagesc(connectionMat);
  1128. % keyboard
  1129. %close all
  1130. % end
  1131. % STEP 1b: compute t-stats at each channel/time point and define clusters
  1132. regDat = b_mat_eeg(:,:,:,:);
  1133. EEG_dat=regDat(:,:,:,2);
  1134. % get clusters, cluster sizes, cluster masses for positive clusters (ie
  1135. % p<CkustThreshEEG in a one tailed positive test):
  1136. posClusterInfo=getEEG_clusterSize(EEG_dat, connectionMat, clustThreshEEG, 'right');
  1137. % and negative effects:
  1138. negClusterInfo=getEEG_clusterSize(EEG_dat, connectionMat, clustThreshEEG, 'left');
  1139. %%STEP 1c:
  1140. % 1: Randomly flip signs of coefficients for each subject
  1141. % 2: redo t-test and cluster formation
  1142. % 3: record the cluster mass of the "biggest" cluster
  1143. % 4: repeat procedure 1000 or more times
  1144. % 5: see where cluster mass values from actual data fall along distribution
  1145. % of permutation cluster mass values
  1146. for k=1:numPermEEG
  1147. % create a subject length array containing randomly assigned -1's and
  1148. % 1s:
  1149. permArray=ones(size(EEG_dat, 1), 1);
  1150. permArray(logical(binornd(1, .5, size(EEG_dat, 1), 1)))=-1;
  1151. % multiply each subject timeseries by the -1 or 1 assigned randomly on
  1152. % this trial
  1153. sz=size(EEG_dat);
  1154. permMat=repmat(permArray, [1 sz(2:end)]);
  1155. % get cluster statistics for permuted dataset:
  1156. permClusterInfo=getEEG_clusterSize(EEG_dat.*permMat, connectionMat, clustThreshEEG, 'right');
  1157. % store the maximum of the statistics, for use in null distribution:
  1158. maxSize(k)=(max(permClusterInfo.clustSizeMap(:)));
  1159. maxWt(k)=(max(permClusterInfo.clustWtMap(:)));
  1160. if mod(k,100)==0
  1161. disp(k)
  1162. end
  1163. end
  1164. % For a two tailed test, find the the minimum cluster statistics necessary
  1165. % to beat 97.5% of the null distribution, based on "mass"
  1166. massTh = prctile(maxWt, 97.5);
  1167. %find positive and negative cluster IDs with weights greater than threshold
  1168. gPosEEG=unique(posClusterInfo.ID_map(posClusterInfo.clustWtMap > massTh));
  1169. gNegEEG=unique(negClusterInfo.ID_map(negClusterInfo.clustWtMap > massTh));
  1170. %make new "threshMap" which just has the t values of significant clusters and zeros everywhere else
  1171. threshMapEEG=zeros(size(negClusterInfo.tMap));
  1172. threshMapEEG(posClusterInfo.clustWtMap > massTh)=posClusterInfo.tMap(posClusterInfo.clustWtMap > massTh);
  1173. threshMapEEG(negClusterInfo.clustWtMap > massTh)=negClusterInfo.tMap(negClusterInfo.clustWtMap > massTh);
  1174. %save cluster masses and cluster pValues
  1175. clustMasses = [unique(posClusterInfo.clustWtMap(posClusterInfo.clustWtMap > massTh),'stable');unique(negClusterInfo.clustWtMap(negClusterInfo.clustWtMap > massTh),'stable')];
  1176. clear pVal
  1177. for k = 1:length([gPosEEG;gNegEEG])
  1178. pVal(k) = (sum(maxWt>clustMasses(k))+1)/numPermEEG;
  1179. end
  1180. %image plot of threshMap (shows significant eeg clusters and their tvalues)
  1181. figure
  1182. imagesc(threshMapEEG);
  1183. %% repeats permutation test for eye data
  1184. % 1 - surprise @ clustThreshEye for analysis
  1185. % 2 - surprise @ 0.025 for figures
  1186. % 3 - entropy @ 0.025 for figures
  1187. % 4 - prediction phase STPCPOB @ 0.025 for figures
  1188. downSampTimesEye = timeBeforeEye:timeAfterEye;
  1189. titles = ["Intercept","MeanSTP","MeanSTPCPOB","MeanEntropy","Condition","SumSinColor","SumCosColor","Baseline 1000 ms"];
  1190. for i = 1:size(allBsPerm,3)
  1191. [h,p(i,:)] = ttest(allBsPerm(:,:,i));
  1192. end
  1193. % same steps as previous test, with possibly more permutations since this goes a lot faster
  1194. % 5 clusters calculated
  1195. % 1. stimulus STP regression thresholded at clustThreshEye
  1196. % 2. stimulus STP regression thresholed at 0.025
  1197. % 3. stimulus entropy regression thresholded at 0.025
  1198. % 4. prediction phase STPCPOB thresholded at 0.025
  1199. % 5. prediction phase derivative STPCPOB thresholded at 0.025
  1200. clusterMaxPerm=zeros(numPermEye,1);
  1201. clusterMaxPermSig=zeros(numPermEye,1);
  1202. clusterMaxPermEnt=zeros(numPermEye,1);
  1203. clusterMaxPermPredSTP=zeros(numPermEye,1);
  1204. clusterMaxPermDiffSTP=zeros(numPermEye,1);
  1205. for i=1:numPermEye
  1206. allBsVar = allBsPerm(:,:,2);
  1207. allBsEnt = allBsPerm(:,:,4);
  1208. allBsPredSTP= allBsPredPerm(:,:,3);
  1209. allBsDiffSTP= allBsDiffPerm(:,:,3);
  1210. %randomly select 1 and -1
  1211. random_flip=randsample([1, -1], size(allBsPerm,1), true);
  1212. random_flip_mat = random_flip'*ones(1,size(allBsPerm,2));
  1213. data_flippedVar = random_flip_mat.*allBsVar;
  1214. %randomly select 1 and -1
  1215. random_flip=randsample([1, -1], size(allBsPerm,1), true);
  1216. random_flip_mat = random_flip'*ones(1,size(allBsPerm,2));
  1217. data_flippedEnt = random_flip_mat.*allBsEnt;
  1218. %randomly select 1 and -1
  1219. random_flip=randsample([1, -1], size(allBsPredPerm,1), true);
  1220. random_flip_mat = random_flip'*ones(1,size(allBsPredPerm,2));
  1221. data_flippedPredSTP = random_flip_mat.*allBsPredSTP;
  1222. %randomly select 1 and -1
  1223. random_flip=randsample([1, -1], size(allBsDiffPerm,1), true);
  1224. random_flip_mat = random_flip'*ones(1,size(allBsDiffPerm,2));
  1225. data_flippedDiffSTP = random_flip_mat.*allBsDiffSTP;
  1226. %calculate t stats for permuted data
  1227. pupilClusterInfo = getPupil_clusterSize(data_flippedVar,0,clustThreshEye,'right');
  1228. clusterMaxPerm(i) = max(pupilClusterInfo.clustWtMap);
  1229. pupilClusterInfo = getPupil_clusterSize(data_flippedVar,0,sigThresh,'right');
  1230. clusterMaxPermSig(i) = max(pupilClusterInfo.clustWtMap);
  1231. pupilClusterInfo = getPupil_clusterSize(data_flippedEnt,0,sigThresh,'right');
  1232. clusterMaxPermEnt(i) = max(pupilClusterInfo.clustWtMap);
  1233. pupilClusterInfo = getPupil_clusterSize(data_flippedPredSTP,0,sigThresh,'right');
  1234. clusterMaxPermPredSTP(i) = max(pupilClusterInfo.clustWtMap);
  1235. pupilClusterInfo = getPupil_clusterSize(data_flippedDiffSTP,0,sigThresh,'right');
  1236. clusterMaxPermDiffSTP(i) = max(pupilClusterInfo.clustWtMap);
  1237. if mod(i,100)==0
  1238. disp(i)
  1239. end
  1240. end
  1241. % calculate cluster size of real data and the pValues for those clusters
  1242. pupilClusterInfo = getPupil_clusterSize(allBsVar,0,clustThreshEye*2,'both');
  1243. clusterMax = max(pupilClusterInfo.clustWtMap);
  1244. pupilClusterInfoSig = getPupil_clusterSize(allBsVar,0,sigThresh*2,'both');
  1245. clusterMaxSig = max(pupilClusterInfoSig.clustWtMap);
  1246. pValEye = (sum(clusterMaxPermSig>=clusterMaxSig)+1)/numPermEye*2;
  1247. pupilClusterInfoEnt = getPupil_clusterSize(allBsEnt,0,sigThresh*2,'both');
  1248. clusterMaxEnt = max(pupilClusterInfoEnt.clustWtMap);
  1249. pValEnt = (sum(clusterMaxPermEnt>=clusterMaxEnt)+1)/numPermEye*2;
  1250. pupilClusterInfoPredSTP = getPupil_clusterSize(allBsPredSTP,0,sigThresh*2,'both');
  1251. clusterMaxPredSTP = max(pupilClusterInfoPredSTP.clustWtMap);
  1252. pValPredSTP = (sum(clusterMaxPermPredSTP>=clusterMaxPredSTP)+1)/numPermEye*2;
  1253. pupilClusterInfoDiffSTP = getPupil_clusterSize(allBsDiffSTP,0,sigThresh*2,'both');
  1254. clusterMaxDiffSTP = max(pupilClusterInfoDiffSTP.clustWtMap);
  1255. pValDiffSTP = (sum(clusterMaxPermDiffSTP>=clusterMaxDiffSTP)+1)/numPermEye*2;
  1256. %find mass threshold and get clusters where data is larger than threshold
  1257. %for the 2nd 3rd 4th, and 5th get a map of where cluster size is significantly large
  1258. massThEye=prctile(clusterMaxPerm, 97.5);
  1259. gSig=unique(pupilClusterInfo.ID_map(pupilClusterInfo.clustWtMap>massThEye));
  1260. threshMapEye=zeros(size(pupilClusterInfo.tMap));
  1261. threshMapEye(pupilClusterInfo.clustWtMap>massThEye)=pupilClusterInfo.tMap(pupilClusterInfo.clustWtMap>massThEye);
  1262. massThSig=prctile(clusterMaxPermSig, 97.5);
  1263. gSigSig=unique(pupilClusterInfoSig.ID_map(pupilClusterInfoSig.clustWtMap>massThSig));
  1264. threshMapEyeSig=zeros(size(pupilClusterInfoSig.tMap));
  1265. threshMapEyeSig(pupilClusterInfoSig.clustWtMap>massThSig)=pupilClusterInfoSig.tMap(pupilClusterInfoSig.clustWtMap>massThSig);
  1266. sigTimes = find(threshMapEyeSig~=0);
  1267. %IF THERE ARE NO CLUSTERS IN EYE STP REGRESSION (as is the case in new dataset):
  1268. %analyses further in the script wouldn't work, so we'll just pretend that pupil
  1269. %size is significant in roughly the same window as it was in the first dataset (700ms-4sec)
  1270. if isempty(sigTimes)
  1271. if realData == 1
  1272. sigTimes = 1700:5000;
  1273. pupilClusterInfo.ID_map(1700:5000)=1000;
  1274. pupilClusterInfo.clustWtMap(1700:5000)=3401;
  1275. pupilClusterInfo.tMap(1700:5000)=1;
  1276. gSig=unique(pupilClusterInfo.ID_map(pupilClusterInfo.clustWtMap>massThEye));
  1277. threshMapEye=zeros(size(pupilClusterInfo.tMap));
  1278. threshMapEye(pupilClusterInfo.clustWtMap>massThEye)=pupilClusterInfo.tMap(pupilClusterInfo.clustWtMap>massThEye);
  1279. else
  1280. sigTimes = 283:1251;
  1281. pupilClusterInfo.ID_map(283:1251)=1000;
  1282. pupilClusterInfo.clustWtMap(283:1251)=3000;
  1283. pupilClusterInfo.tMap(283:1251)=1;
  1284. gSig=unique(pupilClusterInfo.ID_map(pupilClusterInfo.clustWtMap>massThEye));
  1285. threshMapEye=zeros(size(pupilClusterInfo.tMap));
  1286. threshMapEye(pupilClusterInfo.clustWtMap>massThEye)=pupilClusterInfo.tMap(pupilClusterInfo.clustWtMap>massThEye);
  1287. end
  1288. end
  1289. %other regression coefficients can be insignificant, those figures will just be skipped
  1290. massThEnt=prctile(clusterMaxPermEnt, 97.5);
  1291. gSigEnt=unique(pupilClusterInfoEnt.ID_map(pupilClusterInfoEnt.clustWtMap>massThEnt));
  1292. threshMapEyeEnt=zeros(size(pupilClusterInfoEnt.tMap));
  1293. threshMapEyeEnt(pupilClusterInfoEnt.clustWtMap>massThEnt)=pupilClusterInfoEnt.tMap(pupilClusterInfoEnt.clustWtMap>massThEnt);
  1294. sigTimesEnt = find(threshMapEyeEnt~=0);
  1295. massThPredSTP=prctile(clusterMaxPermPredSTP, 97);
  1296. gSigPredSTP=unique(pupilClusterInfoPredSTP.ID_map(pupilClusterInfoPredSTP.clustWtMap>massThPredSTP));
  1297. threshMapEyePredSTP=zeros(size(pupilClusterInfoPredSTP.tMap));
  1298. threshMapEyePredSTP(pupilClusterInfoPredSTP.clustWtMap>massThPredSTP)=pupilClusterInfoPredSTP.tMap(pupilClusterInfoPredSTP.clustWtMap>massThPredSTP);
  1299. sigTimesPredSTP = find(threshMapEyePredSTP~=0);
  1300. massThDiffSTP=prctile(clusterMaxPermDiffSTP, 97.5);
  1301. gSigDiffSTP=unique(pupilClusterInfoDiffSTP.ID_map(pupilClusterInfoDiffSTP.clustWtMap>massThDiffSTP));
  1302. threshMapEyeDiffSTP=zeros(size(pupilClusterInfoDiffSTP.tMap));
  1303. threshMapEyeDiffSTP(pupilClusterInfoDiffSTP.clustWtMap>massThDiffSTP)=pupilClusterInfoDiffSTP.tMap(pupilClusterInfoDiffSTP.clustWtMap>massThDiffSTP);
  1304. sigTimesDiffSTP = find(threshMapEyeDiffSTP~=0);
  1305. %% Make big summary figure (figure 2 in manuscript)
  1306. % panel12 = [1:4,13:16,25:28,37:40,49:52,61:64];
  1307. % panel22a = [6:12,18:24,30:36];
  1308. % panel22b = [42:48,54:60,66:72];
  1309. %these are coordinates of each of the panel's locations in figure
  1310. %it is very convoluted, do not edit
  1311. panel12 = [9:12,21:24,33:36,45:48,57:60,69:72];
  1312. panel22a = [1:7,13:19,25:31];
  1313. panel22b = [37:43,49:55,61:67];
  1314. panel32 = [97:99,109:111,121:123];
  1315. panel42 = [100:102,112:114,124:126];
  1316. panel52 = [103:105,115:117,127:129];
  1317. panel62 = [106:108,118:120,130:132];
  1318. panel72 = [133:168];
  1319. panel82 = [181:185,193:197];
  1320. panel92 = [205:209,217:221];
  1321. panel102 = [187:191,199:203];
  1322. panel112 = [211:215,223:227];
  1323. load('chanlocs.mat')
  1324. clusterInfo = getEEG_clusterSize(b_mat_eeg(:,:,:,2), connectionMat, clustThreshEEG*2,'both');
  1325. figure("Position",[100,50,700,1000])
  1326. set(gcf,'renderer','Painters')
  1327. subplot(19,12,panel12);
  1328. %Baseline Pupil
  1329. xticklabels(["Entropy","Cond","STP","STP*Cond"])
  1330. xticks(1:4)
  1331. xlim([0,5])
  1332. sem = std(BBaseline)/sqrt(length(eyeSubs));
  1333. hold on
  1334. errorbar(1,mean(BBaseline(:,4)),sem(4),'.',"Color",cbColors(2,:),"MarkerSize",20,"Marker",'.',"LineWidth",2)
  1335. errorbar(2,mean(BBaseline(:,5)),sem(5),'.',"Color",cbColors(3,:),"MarkerSize",20,"Marker",'.',"LineWidth",2)
  1336. errorbar(3,mean(BBaseline(:,2)),sem(2),'.',"Color",cbColors(5,:),"MarkerSize",20,"Marker",'.',"LineWidth",2)
  1337. errorbar(4,mean(BBaseline(:,3)),sem(3),'.',"Color",cbColors(4,:),"MarkerSize",20,"Marker",'.',"LineWidth",2)
  1338. yline(0)
  1339. yticks([-.1,0,.05])
  1340. set(gca,"FontName","Arial","FontWeight","bold","FontSize",12)
  1341. set(gca, 'box', 'off')
  1342. ylabel("Regression Coefficient")
  1343. subplot(19,12,panel22b);
  1344. %Running pupil regressors
  1345. %plot each regressor with error bars in right color
  1346. if realData
  1347. sem = std(allBsPerm(:,:,2))./sqrt(length(eyeSubs)-1);
  1348. shadedErrorBar((-timeBeforeEye:timeAfterEye)./1000,mean(allBsPerm(:,:,2)),[mean(allBsPerm(:,:,2))-sem;mean(allBsPerm(:,:,2))+sem],{'-','color',cbColors(5,:),'markerfacecolor',cbColors(5,:)},1)
  1349. hold on
  1350. sem = std(allBsPerm(:,:,3))./sqrt(length(eyeSubs)-1);
  1351. shadedErrorBar((-timeBeforeEye:timeAfterEye)./1000,mean(allBsPerm(:,:,3)),[mean(allBsPerm(:,:,3))-sem;mean(allBsPerm(:,:,3))+sem],{'-','color',cbColors(4,:),'markerfacecolor',cbColors(4,:)},1)
  1352. sem = std(allBsPerm(:,:,4))./sqrt(length(eyeSubs)-1);
  1353. shadedErrorBar((-timeBeforeEye:timeAfterEye)./1000,mean(allBsPerm(:,:,4)),[mean(allBsPerm(:,:,4))-sem;mean(allBsPerm(:,:,4))+sem],{'-','color',cbColors(2,:),'markerfacecolor',cbColors(2,:)},1)
  1354. % sem = std(allBsPerm(:,:,5))./sqrt(length(eyeSubs)-1);
  1355. % shadedErrorBar((-timeBeforeEye:timeAfterEye)./1000,mean(allBsPerm(:,:,5)),[mean(allBsPerm(:,:,5))-sem;mean(allBsPerm(:,:,5))+sem],{'-','color',cbColors(3,:),'markerfacecolor',cbColors(3,:)},1)
  1356. else
  1357. sem = std(allBsPerm(:,:,2))./sqrt(length(eyeSubs)-1);
  1358. shadedErrorBar((-timeBeforeEye:timeAfterEye)./250,mean(allBsPerm(:,:,2)),[mean(allBsPerm(:,:,2))-sem;mean(allBsPerm(:,:,2))+sem],{'-','color',cbColors(5,:),'markerfacecolor',cbColors(5,:)},1)
  1359. hold on
  1360. sem = std(allBsPerm(:,:,3))./sqrt(length(eyeSubs)-1);
  1361. shadedErrorBar((-timeBeforeEye:timeAfterEye)./250,mean(allBsPerm(:,:,3)),[mean(allBsPerm(:,:,3))-sem;mean(allBsPerm(:,:,3))+sem],{'-','color',cbColors(4,:),'markerfacecolor',cbColors(4,:)},1)
  1362. sem = std(allBsPerm(:,:,4))./sqrt(length(eyeSubs)-1);
  1363. shadedErrorBar((-timeBeforeEye:timeAfterEye)./250,mean(allBsPerm(:,:,4)),[mean(allBsPerm(:,:,4))-sem;mean(allBsPerm(:,:,4))+sem],{'-','color',cbColors(2,:),'markerfacecolor',cbColors(2,:)},1)
  1364. % sem = std(allBsPerm(:,:,5))./sqrt(length(eyeSubs)-1);
  1365. % shadedErrorBar((-timeBeforeEye:timeAfterEye)./250,mean(allBsPerm(:,:,5)),[mean(allBsPerm(:,:,5))-sem;mean(allBsPerm(:,:,5))+sem],{'-','color',cbColors(3,:),'markerfacecolor',cbColors(3,:)},1)
  1366. end
  1367. % the part where you add significant clusters to figure if present
  1368. if realData==1
  1369. if ~isempty(sigTimes)
  1370. scatter((sigTimes-timeBeforeEye-1)/1000,mean(allBsPerm(:,sigTimes,2)),5,[0.1621 0.3301 0.1992],"filled")
  1371. end
  1372. if ~isempty(sigTimesEnt)
  1373. scatter((sigTimesEnt-timeBeforeEye-1)/1000,mean(allBsPerm(:,sigTimesEnt,4)),5,[0.6289 0.4348 0],"filled")
  1374. end
  1375. end
  1376. xlabel('Time Relative to Stimulus Onset (s)')
  1377. ylabel('Coefficients')
  1378. xticks([-1:4])
  1379. xlim([-1,4])
  1380. yticks([-0.02,0,0.04])
  1381. yline(0)
  1382. xline(0)
  1383. set(gca,"FontName","Arial","FontWeight","bold","FontSize",12)
  1384. set(gca, 'box', 'off')
  1385. subplot(19,12,panel22a);
  1386. %Running pupil intercept (mean pupil signal) with error bars
  1387. if realData==1
  1388. sem = std(allBsPerm(:,:,1))./sqrt(length(eyeSubs)-1);
  1389. shadedErrorBar((-timeBeforeEye:timeAfterEye)./1000,mean(allBsPerm(:,:,1)),[mean(allBsPerm(:,:,1))-sem;mean(allBsPerm(:,:,1))+sem],{'-','color',[.5,.5,.5],'markerfacecolor',[.5,.5,.5]},1)
  1390. else
  1391. sem = std(allBsPerm(:,:,1))./sqrt(length(eyeSubs)-1);
  1392. shadedErrorBar((-timeBeforeEye:timeAfterEye)./250,mean(allBsPerm(:,:,1)),[mean(allBsPerm(:,:,1))-sem;mean(allBsPerm(:,:,1))+sem],{'-','color',[.5,.5,.5],'markerfacecolor',[.5,.5,.5]},1)
  1393. end
  1394. ylabel('Intercept')
  1395. xticks([])
  1396. xlim([-1,4])
  1397. yticks([-0.25,0,0.4])
  1398. yline(0)
  1399. xline(0)
  1400. set(gca,"FontName","Arial","FontWeight","bold","FontSize",12)
  1401. set(gca, 'box', 'off')
  1402. %next 4 panels are each a topoplot of STP coefficient at a specific timepoint
  1403. %320 ms, 450 ms, 580 ms, and 1000 ms
  1404. subplot(19,12,panel32);
  1405. %topoplot 1
  1406. currplot = topoplot(clusterInfo.tMap(:,EEGTimes==319), chanlocs,'Colormap',jet);
  1407. caxis([-6,6])
  1408. title('320 ms')
  1409. set(gca,"FontName","Arial","FontWeight","bold","FontSize",12)
  1410. subplot(19,12,panel42);
  1411. %topoplot 2
  1412. currplot = topoplot(clusterInfo.tMap(:,EEGTimes==449), chanlocs,'Colormap',jet);
  1413. caxis([-6,6])
  1414. title('450 ms')
  1415. set(gca,"FontName","Arial","FontWeight","bold","FontSize",12)
  1416. subplot(19,12,panel52);
  1417. %topoplot 3
  1418. currplot = topoplot(clusterInfo.tMap(:,EEGTimes==579), chanlocs,'Colormap',jet);
  1419. caxis([-6,6])
  1420. title('580 ms')
  1421. set(gca,"FontName","Arial","FontWeight","bold","FontSize",12)
  1422. subplot(19,12,panel62);
  1423. %topoplot 4
  1424. currplot = topoplot(clusterInfo.tMap(:,EEGTimes==999), chanlocs,'Colormap',jet);
  1425. caxis([-6,6])
  1426. title('1000 ms')
  1427. set(gca,"FontName","Arial","FontWeight","bold","FontSize",12)
  1428. traceTimes = -500:2000;
  1429. subplot(19,12,panel72);
  1430. %eeg heatmap
  1431. imagesc(traceTimes./1000, [],clusterInfo.tMap(:,traceTimes+timeBeforeEEG))
  1432. cb=colorbar;
  1433. ylabel('Channel')
  1434. xlabel('Time (s)')
  1435. yticklabels([])
  1436. caxis([-6,6])
  1437. cb.Ticks = [-6,0,6];
  1438. set(gca,"FontName","Arial","FontWeight","bold","FontSize",12)
  1439. set(gca, 'box', 'off')
  1440. mat1=b_mat_eeg(:,[63],:,:); %FCz
  1441. mat2=reshape(mean(mean(mat1,2),1),4000,[]);
  1442. mat3 = mat2';
  1443. mat4 = reshape(mean(mat1,2),size(b_mat_eeg,[1,3,4]));
  1444. %next 4 plots are running coefficients for individual channels (FCz and Pz) for intercept and STP
  1445. subplot(19,12,panel82);
  1446. %intercept plot (FCz)
  1447. sem = std(mat4(:,:,1))./sqrt(size(b_mat_eeg,1)-1);
  1448. shadedErrorBar(traceTimes./1000,movmean(mat3(1,traceTimes+timeBeforeEEG),40),[movmean(mat3(1,traceTimes+timeBeforeEEG),40)-sem(traceTimes+timeBeforeEEG);movmean(mat3(1,traceTimes+timeBeforeEEG),40)+sem(traceTimes+timeBeforeEEG)],{'b-','markerfacecolor','b'},1)
  1449. yline(0,'--')
  1450. yticks(-2:1)
  1451. xlim([-0.5,1.5])
  1452. xticks([])
  1453. ylabel("Intercept")
  1454. title("FCz")
  1455. set(gca,"FontName","Arial","FontWeight","bold","FontSize",12)
  1456. set(gca, 'box', 'off')
  1457. subplot(19,12,panel92);
  1458. %stp plot (FCz)
  1459. sem = std(mat4(:,:,2))./sqrt(size(b_mat_eeg,1)-1);
  1460. shadedErrorBar(traceTimes./1000,movmean(mat3(2,traceTimes+timeBeforeEEG),40),[movmean(mat3(2,traceTimes+timeBeforeEEG),40)-sem(traceTimes+timeBeforeEEG);movmean(mat3(2,traceTimes+timeBeforeEEG),40)+sem(traceTimes+timeBeforeEEG)],{'b-','markerfacecolor','b'},1)
  1461. yline(0,'--')
  1462. yticks(-0.2:0.1:0.3)
  1463. xlim([-0.5,1.5])
  1464. xticks(-0.5:0.5:1.5)
  1465. xtickangle(0)
  1466. xlabel("Time (s)")
  1467. ylabel("STP")
  1468. set(gca,"FontName","Arial","FontWeight","bold","FontSize",12)
  1469. set(gca, 'box', 'off')
  1470. mat1=b_mat_eeg(:,[13],:,:); %Pz
  1471. mat2=reshape(mean(mean(mat1,2),1),4000,[]);
  1472. mat3 = mat2';
  1473. mat4 = reshape(mean(mat1,2),size(b_mat_eeg,[1,3,4]));
  1474. subplot(19,12,panel102);
  1475. %intercept plot (Pz)
  1476. sem = std(mat4(:,:,1))./sqrt(size(b_mat_eeg,1)-1);
  1477. shadedErrorBar(traceTimes./1000,movmean(mat3(1,traceTimes+timeBeforeEEG),40),[movmean(mat3(1,traceTimes+timeBeforeEEG),40)-sem(traceTimes+timeBeforeEEG);movmean(mat3(1,traceTimes+timeBeforeEEG),40)+sem(traceTimes+timeBeforeEEG)],{'b-','markerfacecolor','b'},1)
  1478. yline(0,'--')
  1479. yticks(-2:3)
  1480. xlim([-0.5,1.5])
  1481. xticks([])
  1482. ylabel("Intercept")
  1483. title("Pz")
  1484. set(gca,"FontName","Arial","FontWeight","bold","FontSize",12)
  1485. set(gca, 'box', 'off')
  1486. subplot(19,12,panel112);
  1487. %stp plot (Pz)
  1488. sem = std(mat4(:,:,2))./sqrt(size(b_mat_eeg,1)-1);
  1489. shadedErrorBar(traceTimes./1000,movmean(mat3(2,traceTimes+timeBeforeEEG),40),[movmean(mat3(2,traceTimes+timeBeforeEEG),40)-sem(traceTimes+timeBeforeEEG);movmean(mat3(2,traceTimes+timeBeforeEEG),40)+sem(traceTimes+timeBeforeEEG)],{'b-','markerfacecolor','b'},1)
  1490. yline(0,'--')
  1491. yticks(-0.3:0.1:0.3)
  1492. xlim([-0.5,1.5])
  1493. xticks(-0.5:0.5:1.5)
  1494. xtickangle(0)
  1495. xlabel("Time (s)")
  1496. ylabel("STP")
  1497. set(gca,"FontName","Arial","FontWeight","bold","FontSize",12)
  1498. set(gca, 'box', 'off')
  1499. %save figure 2 (summary)
  1500. if doSTPResiduals == 0
  1501. fig = gcf;
  1502. figName = append("Figure_2_",figTime,'.eps');
  1503. figLoc = append(figDir,figName);
  1504. exportgraphics(fig,figLoc,'BackgroundColor','none','ContentType','vector')
  1505. figName = append("Figure_2_",figTime,'.png');
  1506. figLoc = append(figDir,figName);
  1507. saveas(fig,figLoc)
  1508. else
  1509. fig = gcf;
  1510. figName = append("Figure_2_Residual_",figTime,'.eps');
  1511. figLoc = append(figDir,figName);
  1512. exportgraphics(fig,figLoc,'BackgroundColor','none','ContentType','vector')
  1513. figName = append("Figure_2_Residual",figTime,'.png');
  1514. figLoc = append(figDir,figName);
  1515. saveas(fig,figLoc)
  1516. end
  1517. %% Make Figure 5 (oddball pupil)
  1518. %only runs if there is a significant oddball pupil cluster
  1519. if ~isempty(sigTimesPredSTP)
  1520. if oddballFigNewVer == 1
  1521. figure('Position',[200 250 1300 600])
  1522. subplot(1,2,1)
  1523. else
  1524. figure('Position',[400 250 700 600])
  1525. end
  1526. set(gcf,'renderer','Painters')
  1527. sem = std(allBsPredPerm(:,:,3))./sqrt(length(eyeSubs)-1);
  1528. shadedErrorBar((-timeBeforePred:timeAfterPred)./1000,(mean(allBsPredPerm(:,:,3))),[(mean(allBsPredPerm(:,:,3)))-sem;(mean(allBsPredPerm(:,:,3)))+sem],{'-','color',cbColors(4,:),'markerfacecolor',cbColors(4,:)},1)
  1529. hold on
  1530. % the part where you add significant clusters to figure
  1531. scatter((sigTimesPredSTP-timeBeforePred-1)./1000,mean(allBsPredPerm(:,sigTimesPredSTP,3)),5,[0.5004 0.2352 0.5469],"filled")
  1532. xlabel("Time Relative to Prediction (s)")
  1533. xticks([-2,0,2,4])
  1534. yticks([-0.02,0,0.02])
  1535. yline(0)
  1536. xline(0)
  1537. ylim([-0.021,0.021])
  1538. ylabel("STP*CP/OB Coefficient")
  1539. text(1.7,-0.0155,"Larger Oddball Pupil","FontName","Arial","FontWeight","bold","FontSize",16)
  1540. text(1.1,0.0155,"Larger Changepoint Pupil","FontName","Arial","FontWeight","bold","FontSize",16)
  1541. set(gca,"FontName","Arial","FontWeight","bold","FontSize",16)
  1542. set(gca, 'box', 'off')
  1543. %second panel is coefficient of learning regression correlated with mean STPCPOB coefficient in prediction phase
  1544. if oddballFigNewVer == 1
  1545. subplot(1,2,2)
  1546. % meanResponse = mean(allBsPredPerm(:,timeBeforePred-1500:timeBeforePred-800,:),2);
  1547. meanResponse = mean(allBsPredPerm(:,sigTimesPredSTP,:),2);
  1548. scatter(paramsCircUpdateAll(ismember(behaveSubs,eyeSubs),4),meanResponse(:,3),30,[227 152 227]./255,'filled','MarkerEdgeColor',[200 50 200]./255)
  1549. hold on
  1550. set(gca, 'box', 'off')
  1551. set(gca,"FontName","Arial","FontWeight","bold","FontSize",14)
  1552. ylabel("Eye STP*CP/OB Coefficient");
  1553. xlabel("Behavioral PE*STP*CP/OB Coef");
  1554. yticks(-0.1:0.05:0.1)
  1555. xticks(0)
  1556. maxVal = max(paramsCircUpdateAll(ismember(behaveSubs,eyeSubs),4));
  1557. minVal = min(paramsCircUpdateAll(ismember(behaveSubs,eyeSubs),4));
  1558. xlim([minVal-0.05*(maxVal-minVal),maxVal+0.05*(maxVal-minVal)])
  1559. maxVal = max(meanResponse(:,3))*1.05;
  1560. minVal = min(meanResponse(:,3))*1.05;
  1561. ylim([minVal-0.05*(maxVal-minVal),maxVal+0.05*(maxVal-minVal)])
  1562. yline(0,'--','LineWidth',1)
  1563. xline(0,'--','LineWidth',1)
  1564. mOdd = polyfit(paramsCircUpdateAll(ismember(behaveSubs,eyeSubs),4),meanResponse(:,3),1);
  1565. plot((linspace(min(paramsCircUpdateAll(ismember(behaveSubs,eyeSubs),4)),max(paramsCircUpdateAll(ismember(behaveSubs,eyeSubs),4)),2)),mOdd(1)*(linspace(min(paramsCircUpdateAll(ismember(behaveSubs,eyeSubs),4)),max(paramsCircUpdateAll(ismember(behaveSubs,eyeSubs),4)),2))+mOdd(2),'Color',[200 50 200]./255);
  1566. end
  1567. [eyeCorr,eyeCorrP] = corr(paramsCircUpdateAll(ismember(behaveSubs,eyeSubs),4),meanResponse(:,3),"Type","spearman");
  1568. % displays r for correlation between STPCPOB in eye and behavior
  1569. % and displayes the p value for that correlation
  1570. disp(eyeCorr)
  1571. disp(eyeCorrP)
  1572. %save Figure 5 (oddball 2nd transition in pupil figure)
  1573. if doSTPResiduals == 0
  1574. fig = gcf;
  1575. figName = append("Figure_5_",figTime,'.eps');
  1576. figLoc = append(figDir,figName);
  1577. exportgraphics(fig,figLoc,'BackgroundColor','none','ContentType','vector')
  1578. figName = append("Figure_5_",figTime,'.png');
  1579. figLoc = append(figDir,figName);
  1580. saveas(fig,figLoc)
  1581. else
  1582. fig = gcf;
  1583. figName = append("Figure_5_Residual_",figTime,'.eps');
  1584. figLoc = append(figDir,figName);
  1585. exportgraphics(fig,figLoc,'BackgroundColor','none','ContentType','vector')
  1586. figName = append("Figure_5_Residual",figTime,'.png');
  1587. figLoc = append(figDir,figName);
  1588. saveas(fig,figLoc)
  1589. end
  1590. beep
  1591. end
  1592. %% Make Figure S3 (oddball pupil Derivative)
  1593. figure('Position',[400 250 700 600])
  1594. set(gcf,'renderer','Painters')
  1595. % plot mean and sem STPCPOB coefficient for pupil derivative
  1596. sem = std(allBsDiffPerm(:,:,3))./sqrt(length(eyeSubs)-1);
  1597. shadedErrorBar((-timeBeforePred:timeAfterPred)./1000,(mean(allBsDiffPerm(:,:,3))),[(mean(allBsDiffPerm(:,:,3)))-sem;(mean(allBsDiffPerm(:,:,3)))+sem],{'-','color',cbColors(4,:),'markerfacecolor',cbColors(4,:)},1)
  1598. hold on
  1599. % the part where you add significant clusters to figure
  1600. scatter((sigTimesDiffSTP-timeBeforePred-1)./1000,mean(allBsDiffPerm(:,sigTimesDiffSTP,3)),5,[0.5004 0.2352 0.5469],"filled")
  1601. xlabel("Time Relative to Prediction (s)")
  1602. xticks([-2,0,2,4])
  1603. yticks([-0.003:0.001:0.003])
  1604. yline(0)
  1605. xline(0)
  1606. ylim([-0.002,0.002])
  1607. ylabel("STP*CP/OB Coefficient")
  1608. text(1.1,-0.00155,"Larger Oddball Derivative","FontName","Arial","FontWeight","bold","FontSize",16)
  1609. text(.65,0.00155,"Larger Changepoint Derivative","FontName","Arial","FontWeight","bold","FontSize",16)
  1610. set(gca,"FontName","Arial","FontWeight","bold","FontSize",16)
  1611. set(gca, 'box', 'off')
  1612. %save Figure 5 (oddball 2nd transition in pupil figure)
  1613. if doSTPResiduals == 0
  1614. fig = gcf;
  1615. figName = append("Figure_S3_",figTime,'.eps');
  1616. figLoc = append(figDir,figName);
  1617. exportgraphics(fig,figLoc,'BackgroundColor','none','ContentType','vector')
  1618. figName = append("Figure_S3_",figTime,'.png');
  1619. figLoc = append(figDir,figName);
  1620. saveas(fig,figLoc)
  1621. else
  1622. fig = gcf;
  1623. figName = append("Figure_S3_Residual_",figTime,'.eps');
  1624. figLoc = append(figDir,figName);
  1625. exportgraphics(fig,figLoc,'BackgroundColor','none','ContentType','vector')
  1626. figName = append("Figure_S3_Residual",figTime,'.png');
  1627. figLoc = append(figDir,figName);
  1628. saveas(fig,figLoc)
  1629. end
  1630. %% Trial-by-trial Effect
  1631. clear relROIEEG relROIEye
  1632. % setup, specify where the clusters we're looking at are
  1633. % make a matrix for each that is the cluster mass at the cluster and 0 everywhere else
  1634. if ~isempty(gSig)
  1635. k=1;
  1636. while k <=length(gSig)
  1637. relROIEye.maps(:,:,k)=pupilClusterInfo.ID_map==gSig(k);
  1638. k=k+1;
  1639. end
  1640. for k = 1:length(gSig)
  1641. clustTs=relROIEye.maps(:,:,k).*abs(pupilClusterInfo.tMap);
  1642. end
  1643. relROIEye.fullTMap=pupilClusterInfo.tMap;
  1644. relROIEEG.sign=[ones(size(gPosEEG)); -ones(size(gNegEEG))];
  1645. k =1;
  1646. while k <=length(gPosEEG)
  1647. relROIEEG.maps(:,:,k)=posClusterInfo.ID_map==gPosEEG(k);
  1648. k=k+1;
  1649. end
  1650. while k <= length(gPosEEG) +length(gNegEEG)
  1651. relROIEEG.maps(:,:,k)=negClusterInfo.ID_map==gNegEEG(k-length(gPosEEG));
  1652. k=k+1;
  1653. end
  1654. for k = 1:length(relROIEEG.sign)
  1655. clustTs=relROIEEG.maps(:,:,k).*abs(posClusterInfo.tMap);
  1656. % [relROIEEG.peakChannel(k),J] = find(clustTs==max(clustTs(:)));
  1657. end
  1658. %
  1659. relROIEEG.fullTMap=posClusterInfo.tMap;
  1660. if exist('relROIEEG.maps','var') == 0
  1661. relROIEEG.maps = false(size(relROIEEG.fullTMap,1),size(relROIEEG.fullTMap,2),1);
  1662. relROIEEG.maps([2,3,6,7,27,28,29,31,33,34,35,36,57,59,60,61,62,63],2300:2500)=true;
  1663. end
  1664. if eegTimestepMode == 1
  1665. % Instead of using the clusters, you can use regions of clusters or regions of timepoints
  1666. relROIEEG.maps = zeros(size(relROIEEG.fullTMap,1),size(relROIEEG.fullTMap,2));
  1667. % relROIEEG.maps([2,3,6,7,27,28,29,31,33,34,35,36,57,59,60,61,62,63],:) = 1; %Frontals
  1668. % relROIEEG.maps([12 13 14 19 23 42 43 44 46 47 48 50 51 52 53],:) = -1; %Parietals
  1669. % relROIEEG.maps([3,4,5,6,8,9,10,11,14,15,32,33,36,37,38,40,41,42,44,45,46],:) = 1; %Lefts
  1670. % relROIEEG.maps([19,20,21,22,24,25,26,27,29,30,48,49,50,53,54,55,57,58,59,60,61],:) = -1; %Rights
  1671. % relROIEEG.maps = ones(size(relROIEEG.fullTMap,1),size(relROIEEG.fullTMap,2)); %All
  1672. % relROIEEG.maps([2,3,6,7,27,28,29,31,33,34,35,36,57,59,60,61,62,63,12 13 14 19 23 42 43 44 46 47 48 50 51 52 53],:) = 1; %Frontal & Parietal
  1673. relROIEEG.maps = sum(relROIEEG.maps,3);
  1674. %relROI.maps = relROI.fullTMap;
  1675. increment = 100;
  1676. timeOI = [1500,4000];
  1677. borderTimes = timeOI(1):increment:timeOI(end);
  1678. trueMap = relROIEEG.maps(:,:,1);
  1679. relROIEEG.maps = false(size(relROIEEG.maps,1),size(relROIEEG.maps,2),size(relROIEEG.maps,3));
  1680. for i = 1:length(borderTimes)-1
  1681. relROIEEG.maps(:,borderTimes(i):borderTimes(i+1),i) = trueMap(:,borderTimes(i):borderTimes(i+1));
  1682. end
  1683. %plots all clusters you will be using, each cluster is a different color
  1684. figMap = zeros(size(relROIEEG.maps,1),size(relROIEEG.maps,2));
  1685. for m = 1:size(relROIEEG.maps,3)
  1686. figMap(relROIEEG.maps(:,:,m)) = m;
  1687. end
  1688. figure
  1689. imagesc(figMap)
  1690. % relROIEEG.fullTMap = ones(size(relROIEEG.maps,1),size(relROIEEG.maps,2));
  1691. end
  1692. % Instead of using the whole period of pupil dilation, you can use bins of timepoints
  1693. % relROIEye.maps = ones(1,size(relROIEye.fullTMap,2));
  1694. % relROIEye.maps = sum(relROIEye.maps,3);
  1695. %
  1696. % increment = 200;
  1697. % timeOI = [2001,10001];
  1698. % borderTimes = timeOI(1):increment:timeOI(end);
  1699. % trueMap = relROIEye.maps(:,:,1);
  1700. %
  1701. % relROIEye.maps = false(size(relROIEye.maps,1),size(relROIEye.maps,2),size(relROIEye.maps,3));
  1702. %
  1703. % for i = 1:length(borderTimes)-1
  1704. % relROIEye.maps(:,borderTimes(i):borderTimes(i+1),i) = trueMap(:,borderTimes(i):borderTimes(i+1));
  1705. % end
  1706. %
  1707. nTrials = 240;
  1708. eegEyeNumSubs = sum(ismember(EEGSubs,eyeSubs));
  1709. %preallocate for loop
  1710. allContext = nan(nTrials,1,length(behaveSubs));
  1711. allRegLRs = nan(nTrials,1,length(behaveSubs));
  1712. allRegBias = nan(nTrials,1,length(behaveSubs));
  1713. allMaxBias = nan(nTrials,1,length(behaveSubs));
  1714. allContextAll = nan(nTrials,1,length(behaveSubs));
  1715. allRegLRsAll = nan(nTrials,1,length(behaveSubs));
  1716. allRegBiasAll = nan(nTrials,1,length(behaveSubs));
  1717. allMaxBiasAll = nan(nTrials,1,length(behaveSubs));
  1718. allIndivRegLRs = nan(nTrials,1,length(behaveSubs));
  1719. allIndivRegBias = nan(nTrials,1,length(behaveSubs));
  1720. allIndivRegLRsAll = nan(nTrials,1,length(behaveSubs));
  1721. allIndivRegBiasAll = nan(nTrials,1,length(behaveSubs));
  1722. allMaxPredErr = nan(nTrials,1,length(behaveSubs));
  1723. allMaxPredErrAll = nan(nTrials,1,length(behaveSubs));
  1724. allRejTrials = nan(nTrials,1,length(behaveSubs));
  1725. allRejTrialsAll = nan(nTrials,1,length(behaveSubs));
  1726. allDoEye = zeros(length(behaveSubs),1);
  1727. allDoEEG = zeros(length(behaveSubs),1);
  1728. allDoEyeEEG = zeros(length(behaveSubs),1);
  1729. meanTrialEffectEEG = nan(nTrials,size(relROIEEG.maps,3),length(EEGSubs));
  1730. meanEffectEpochNumbers = nan(nTrials,size(relROIEEG.maps,3),length(EEGSubs));
  1731. meanTrialEffectPupil = nan(nTrials,size(relROIEye.maps,3),length(eyeSubs));
  1732. meanTrialEffectPGoodEEG = nan(nTrials,size(relROIEye.maps,3),eegEyeNumSubs);
  1733. allBadBlinksEEG = nan(nTrials,1,eegEyeNumSubs);
  1734. for s = 1:length(behaveSubs)
  1735. subNum = num2str(behaveSubs(s));
  1736. subno = behaveSubs(s);
  1737. %specify whether subject is eeg/pupil/both/neither
  1738. %a lot of indexing will use the sums of allDoEEG/Eye, as that is essentially an index for what subject we're on
  1739. %except it skips the subjects without that type of data
  1740. doEEG = ismember(subno,EEGSubs);
  1741. allDoEEG(s) = doEEG;
  1742. doEye = ismember(subno,eyeSubs);
  1743. allDoEye(s) = doEye;
  1744. if doEye && doEEG
  1745. doEyeEEG = 1;
  1746. else
  1747. doEyeEEG = 0;
  1748. end
  1749. allDoEyeEEG(s) = doEyeEEG;
  1750. if doEEG == 1
  1751. %load eeg data
  1752. eegDat = load(fullfile([eegDir,subNum,'_ALP_FILT_STIM.mat']));
  1753. if ismember(subno,[2046,2047,2063,2086,2071,2073,2090,2094,2099,2104,4029,4031,4040])
  1754. eegDat.epochNumbers = eegDat.epochNumbers - 1;
  1755. disp(subno)
  1756. end
  1757. %define "good" trials for EEG (after practice and non-rejected)
  1758. isGoodEEG = false(size(eegDat.EEG.data,3),1);
  1759. ind_OBCPstart=find(eegDat.epochNumbers>nPracticeTrials,1); %practice 20, random 40
  1760. epochNumbers = eegDat.epochNumbers;
  1761. epoch_OBCP=epochNumbers(ind_OBCPstart:end);
  1762. end
  1763. if doEye == 1
  1764. load(fullfile([eyeDir, subNum, '.mat']));
  1765. eyeData = data;
  1766. %interpolate single eye data
  1767. if size(eyeData,2)==5
  1768. eyeData(:,6:8)=0;
  1769. eyeData(:,8)=eyeData(:,5);
  1770. eyeData(:,5:7)=eyeData(:,2:4);
  1771. end
  1772. %Remove bad eye from data with one bad eye
  1773. if ismember(subno,[2030,2063,3014,4002,4021,4024])
  1774. eyeData(:,2:4)=eyeData(:,5:7);
  1775. end
  1776. if ismember(subno,[2035 2057 2058 2062 2071 2083 2087 2098 2101 2103 2106 3018 4022])
  1777. eyeData(:,5:7)=eyeData(:,2:4);
  1778. end
  1779. % identify blinks change from 0 to NaN
  1780. eyeData((eyeData(:,leftArea)==0),leftArea)=NaN;
  1781. eyeData((eyeData(:,rightArea)==0),rightArea)=NaN;
  1782. % make sure other eye is also NaN when one eye is closed
  1783. eyeData(isnan(eyeData(:,leftArea)),rightArea)=NaN;
  1784. eyeData(isnan(eyeData(:,rightArea)),leftArea)=NaN;
  1785. %NaN blink window
  1786. blinks = find(isnan(eyeData(:,leftArea)));
  1787. isBlink = isnan(eyeData(:,leftArea));
  1788. for t=1:length(blinks)
  1789. eyeData(max(blinks(t)-blinkWindow,1):min(blinks(t)+blinkWindow,length(eyeData)),leftArea)= NaN;
  1790. eyeData(max(blinks(t)-blinkWindow,1):min(blinks(t)+blinkWindow,length(eyeData)),rightArea)= NaN;
  1791. end
  1792. %interpolate blink window
  1793. [value,indices] = fillmissing(eyeData(:,leftArea),'linear', 'EndValues', 'nearest');
  1794. eyeData(indices,leftArea)=value(indices);
  1795. [value,indices] = fillmissing(eyeData(:,rightArea),'linear', 'EndValues', 'nearest');
  1796. eyeData(indices,rightArea)=value(indices);
  1797. %calculate mean pupil area
  1798. meanArea=(eyeData(:,leftArea)+eyeData(:,rightArea))/2;
  1799. %add meanArea to eyeData
  1800. eyeData(:,9) = meanArea;
  1801. eyeData(:,10) = isBlink;
  1802. %cut out data before start and after end of session
  1803. startTime = find(eyeData(:,8) == 15);
  1804. endTime = find(eyeData(:,8) == 14);
  1805. eyeData = eyeData(startTime(end):endTime(1),:);
  1806. % Find start of each trial (stimOn) in terms of eyeData timesteps
  1807. trialStartAll = [0; find(eyeData(:,8) == 4)];
  1808. trialStart = [];
  1809. for i = 2:(length(trialStartAll))
  1810. diffStart = trialStartAll(i,1) - trialStartAll(i-1,1);
  1811. if diffStart > 5
  1812. trialStart = [trialStart trialStartAll(i)];
  1813. end
  1814. end
  1815. trialStart = trialStart';
  1816. %Find start of prediction phases for each trial
  1817. if ~ismember(subno,[20280 2030 2079 2103])
  1818. predStartAll = [0; find(eyeData(:,8) == 10)]; %predCueOn1
  1819. else
  1820. pred1StartAll = [0; find(eyeData(:,8) == 10)]; %predCueOn1
  1821. pred2StartAll = [0; find(eyeData(:,8) == 12)]; %predCueOn2
  1822. predStartAll = sort([pred1StartAll;pred2StartAll]); %put them all in order
  1823. end
  1824. predStart = [];
  1825. for i = 2:(length(predStartAll))
  1826. diffStart = predStartAll(i,1) - predStartAll(i-1,1);
  1827. if diffStart > 5
  1828. predStart = [predStart predStartAll(i)];
  1829. end
  1830. end
  1831. predStart = predStart';
  1832. %establish time window in terms of eyeData timesteps
  1833. timeWindow = length([-timeBeforeEye:timeAfterEye]);
  1834. allTrialAreas = zeros([length(trialStart),timeWindow]);
  1835. allTrialBlinks = zeros([length(trialStart),timeWindow]);
  1836. %fill trial areas based on trial start times
  1837. for i = 1:height(allTrialAreas)
  1838. if trialStart(i) + timeAfterEye <= length(eyeData(:,1))
  1839. allTrialAreas(i,:) = eyeData(trialStart(i)-timeBeforeEye:trialStart(i)+timeAfterEye,9);
  1840. allTrialBlinks(i,:) = eyeData(trialStart(i)-timeBeforeEye:trialStart(i)+timeAfterEye,10);
  1841. else
  1842. allTrialAreas(i,:) = nan;
  1843. allTrialBlinks(i,:) = 1;
  1844. end
  1845. end
  1846. %remove eyeTrials that you want to get rid of by making them all blinks
  1847. allTrialBlinks(remTrials,:)=1;
  1848. %subjects 20280 and 20380 have very shortened first 2 blocks for eye data so that's why they show up a lot
  1849. %finding bad blink trials
  1850. if ismember(subno,[20280,20380])
  1851. allTrialAreas(1:4,:) = [];
  1852. allTrialBlinks(1:4,:) = [];
  1853. badBlinks = mean(allTrialBlinks,2)>blinkThresh;
  1854. badBlinksComb = mean(allTrialBlinks,2)>combBlinkThresh;
  1855. else
  1856. badBlinks = mean(allTrialBlinks,2)>blinkThresh;
  1857. badBlinks(1:60)=[];
  1858. badBlinksComb = mean(allTrialBlinks,2)>combBlinkThresh;
  1859. badBlinksComb(1:60)=[];
  1860. end
  1861. %adding bad blinks to list of bad blink trials (bad blinks comb is for when EEG and eye data are being combined,
  1862. %i use a less stringent threshold there since trials are being removed for bad eeg and eye data, and i want to
  1863. %keep as many trials as possible
  1864. allBadBlinks(:,:,sum(allDoEye)) = badBlinks;
  1865. allBadBlinksComb(:,:,sum(allDoEye)) = badBlinksComb;
  1866. %eliminate first 2 blocks and normalize trial areas
  1867. if ~ismember(subno,[20280,20380])
  1868. allTrialAreas(1:60,:) = [];
  1869. end
  1870. allTrialAreasNorm = reshape(nanzscore(allTrialAreas(:)),size(allTrialAreas));
  1871. %calculate mean baseline for each trial
  1872. allBaselineMeansNorm(sum(allDoEye),:) = mean(allTrialAreasNorm(:,(timeBeforeEye-baselineTimeEye+1:timeBeforeEye+1)),2);
  1873. allBaselineMeans(sum(allDoEye),:) = mean(allTrialAreas(:,(timeBeforeEye-baselineTimeEye+1:timeBeforeEye+1)),2);
  1874. subBaselineMeansNorm = allBaselineMeansNorm(sum(allDoEye),:);
  1875. end
  1876. if doEye || doEEG
  1877. %This is where we calculate all the trial by trial parameters (pupil, eeg, LR, bias, etc)
  1878. %load behavioral data
  1879. allData=load(fullfile([behaveDir,'subCombined/', subNum, '_3and4BlockData.mat']));
  1880. allData=allData.alldata;
  1881. %load surprise previously calculated using model
  1882. allModelData = load(fullfile(behaveDir,['allModelData',saveText,'/', subNum, '_allBlockData.mat']));
  1883. allModelData = allModelData.allDataStruct;
  1884. meanSurpriseCP = mean(reshape(allModelData.surpriseCP',[nTrials/2,2]),2);
  1885. maxSurpriseCP = max(reshape(allModelData.surpriseCP',[nTrials/2,2]),[],2);
  1886. meanSurpriseOB = mean(reshape(allModelData.surpriseOB',[nTrials/2,2]),2);
  1887. maxSurpriseOB = max(reshape(allModelData.surpriseOB',[nTrials/2,2]),[],2);
  1888. entropyOB=allModelData.entropyOB;
  1889. entropyCP=allModelData.entropyCP;
  1890. entropyOB=[entropyOB(1:nTrials/2),entropyOB(nTrials/2+1:end)];
  1891. entropyOB=mean(entropyOB,2);
  1892. entropyCP=[entropyCP(1:nTrials/2),entropyCP(nTrials/2+1:end)];
  1893. entropyCP=mean(entropyCP,2);
  1894. %add surprise and entropy to regular data structure
  1895. if allData.condition(1) == 1
  1896. allData.meanSurprise = [zscore(meanSurpriseCP);zscore(meanSurpriseOB)];
  1897. allData.maxSurprise = [(maxSurpriseCP);(maxSurpriseOB)];
  1898. allData.entropy = [zscore(entropyCP);zscore(entropyOB)];
  1899. else
  1900. allData.meanSurprise = [zscore(meanSurpriseOB);zscore(meanSurpriseCP)];
  1901. allData.maxSurprise = [(maxSurpriseOB);(maxSurpriseCP)];
  1902. allData.entropy = [zscore(entropyOB);zscore(entropyCP)];
  1903. end
  1904. %replace condition with "context" which is just nTrials long
  1905. context = zeros(nTrials,1);
  1906. if allData.condition(1)==1
  1907. context(1:nTrials/2) = 1;
  1908. context((nTrials/2+1):nTrials) = -1;
  1909. elseif allData.condition(1)==2
  1910. context(1:nTrials/2) = -1;
  1911. context((nTrials/2+1):nTrials) = 1;
  1912. end
  1913. allData.context = context;
  1914. %remove non nTrial long fields
  1915. allData=rmfield(allData,'toPredict');
  1916. allData=rmfield(allData,'allScore');
  1917. allData=rmfield(allData,'totScore');
  1918. allData=rmfield(allData,'sumScore');
  1919. allData=rmfield(allData,'condition');
  1920. allData=rmfield(allData,'predRT');
  1921. if ismember(subno,4000:4100)
  1922. allData=rmfield(allData,'predStartPoint');
  1923. end
  1924. %define parameters to compute learning rate
  1925. predictions = allData.pred;
  1926. outcomes = (allData.est);
  1927. newBlock = 121;
  1928. %run CLR function (done twice, one for left and right stimulus
  1929. [LR1,UP1,subPE1] = computeLearningRate(outcomes(:,1),predictions(:,1),newBlock,'polarHalfCorrect');
  1930. [LR2,UP2,subPE2] = computeLearningRate(outcomes(:,2),predictions(:,2),newBlock,'polarHalfCorrect');
  1931. subPE = [subPE1,subPE2];
  1932. UP = [UP1,UP2;nan,nan];
  1933. LR = [LR1,LR2;nan,nan];
  1934. %define parameters to compute learning rate (for bias/objective prediction error)
  1935. predictions = allData.pred;
  1936. outcomes = (allData.colorArray);
  1937. newBlock = 121;
  1938. %run CLR function (done twice, one for left and right stimulus)
  1939. %this gives corrected prediction update so you don't have that
  1940. %problem from going around the circle, these are used for
  1941. %calculating avg trial learning/bias
  1942. [~,~,objPE1] = computeLearningRate(outcomes(:,1),predictions(:,1),newBlock,'polarHalfCorrect');
  1943. [~,~,objPE2] = computeLearningRate(outcomes(:,2),predictions(:,2),newBlock,'polarHalfCorrect');
  1944. objPE = [objPE1,objPE2];
  1945. %define parameters to compute learning rate
  1946. predictions = allData.pred;
  1947. outcomes = (allData.est);
  1948. newBlock = 121;
  1949. newUpdate = UP;
  1950. allData.newLR = newUpdate./subPE;
  1951. allData.newLR(allData.newLR > 1) = 1;
  1952. allData.newLR(allData.newLR < 0) = 0;
  1953. %Truncate learning rate to 0-1 also add it to allData
  1954. allData.LR = LR;
  1955. allData.LR(allData.LR > 1) = 1;
  1956. allData.LR(allData.LR < 0) = 0;
  1957. %new regressed way of calculating learning
  1958. updateX= [zeros(nTrials,1),subPE(:,:)];
  1959. updateY = [zeros(nTrials,1),allData.predUpdate(:,:)];
  1960. updateXes = zeros(nTrials,nTrials+1);
  1961. updateXes(:,1) = 1;
  1962. for i = 1:nTrials
  1963. indivRegLR(i,:) = regress(updateY(i,:)',updateX(i,:)');
  1964. updateXes(2*i-1,i+1) = subPE(i,1);
  1965. updateXes(2*i,i+1) = subPE(i,2);
  1966. end
  1967. updateYcol = reshape(allData.predUpdate',[],1);
  1968. regLRs = regress(updateYcol,updateXes);
  1969. allData.regLRs = regLRs(2:end);
  1970. allData.indivRegLRs = indivRegLR;
  1971. %Calculate regressed bias and add to allData
  1972. allData.bias = allData.estErr(:,:)./allData.predictErr(:,:);
  1973. biasX = [zeros(nTrials,1),allData.predictErr(:,:)];
  1974. biasY = [zeros(nTrials,1),allData.estErr(:,:)];
  1975. biasXes = zeros(nTrials,nTrials+1);
  1976. biasXes(:,1) = 1;
  1977. for i = 1:nTrials
  1978. biasXes(2*i-1,i+1) = allData.predictErr(i,1);
  1979. biasXes(2*i,i+1) = allData.predictErr(i,2);
  1980. indivRegBias(i,:) = regress(biasY(i,:)',biasX(i,:)');
  1981. end
  1982. biasYcol = reshape(allData.estErr',[],1);
  1983. regBias = regress(biasYcol,biasXes);
  1984. allData.regBias = regBias(2:end);
  1985. allData.indivRegBias = indivRegBias;
  1986. %if you're regressing STP, regress STP out of learning and bias now
  1987. if doSTPResiduals == 1
  1988. [~,~,allData.regBias] = regress(allData.regBias,allData.meanSurprise);
  1989. [~,~,allData.indivRegBias] = regress(allData.indivRegBias,allData.meanSurprise);
  1990. [~,~,allData.regLRs] = regress(allData.regLRs,allData.meanSurprise);
  1991. [~,~,allData.indivRegLRs] = regress(allData.indivRegLRs,allData.meanSurprise);
  1992. end
  1993. allData.goodTrials = ~rejEarlyTrials; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1994. % allData.goodTrials = max(abs(allData.subPredErr),[],2) > 60*pi/180; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1995. %add error vars to allData so good EEG trials can be selected
  1996. allData.subPE = subPE;
  1997. allData.objPE = objPE;
  1998. if doEEG == 1
  1999. %select out trials with good EEG data for behavioral stuff
  2000. epoch_OBCP=epochNumbers(ind_OBCPstart:end);
  2001. for i = remTrials
  2002. epoch_OBCP(epoch_OBCP==i) = [];
  2003. end
  2004. goodData=selBehav(allData, epoch_OBCP-nPracticeTrials);
  2005. else
  2006. goodData=allData;
  2007. end
  2008. %add LR, Bias and Context to "all" variables for EEG
  2009. if doEEG
  2010. allContext(1:size(goodData.context,1),:,s) = goodData.context;
  2011. allRegLRs(1:size(goodData.regLRs,1),:,s) = goodData.regLRs;
  2012. allRegBias(1:size(goodData.regBias,1),:,s) = goodData.regBias;
  2013. allIndivRegLRs(1:size(goodData.indivRegLRs,1),:,s) = goodData.indivRegLRs;
  2014. allIndivRegBias(1:size(goodData.indivRegBias,1),:,s) = goodData.indivRegBias;
  2015. allRejTrials(1:size(goodData.goodTrials,1),:,s) = goodData.goodTrials;
  2016. allMaxBias(1:size(goodData.bias,1),:,s) = mean(goodData.bias,2);
  2017. allMaxPredErr(1:size(goodData.predictErr,1),:,s) = max(goodData.predictErr,[],2);
  2018. end
  2019. %and eye data
  2020. if doEye
  2021. allContextAll(1:size(allData.context,1),:,s) = allData.context;
  2022. allRegLRsAll(1:size(allData.regLRs,1),:,s) = allData.regLRs;
  2023. allRegBiasAll(1:size(allData.regBias,1),:,s) = allData.regBias;
  2024. allIndivRegLRsAll(1:size(allData.indivRegLRs,1),:,s) = allData.indivRegLRs;
  2025. allIndivRegBiasAll(1:size(allData.indivRegBias,1),:,s) = allData.indivRegBias;
  2026. allRejTrialsAll(1:size(allData.goodTrials,1),:,s) = allData.goodTrials;
  2027. allMaxBiasAll(1:size(allData.bias,1),:,s) = mean(allData.bias,2);
  2028. allMaxPredErrAll(1:size(allData.predictErr,1),:,s) = max(allData.predictErr,[],2);
  2029. end
  2030. %regress baseline (and STP if set to) out of eye and eeg data
  2031. if doEEG == 1
  2032. relDataEEG = eegDat.EEG.data(:,:,find(ismember(epochNumbers,epoch_OBCP)));
  2033. baseTimes_roi= [1800:1999]; % figure out what times are in "baseline" period
  2034. if trialMeasure==3 % pull out variance that can be explained by baseline before taking dot product:
  2035. resDataEEG=nan(size(relDataEEG)); % preallocate space for residual data.
  2036. base_roi=(squeeze(nanmean(relDataEEG(:, baseTimes_roi,:), 2)));
  2037. for CH=1:size(base_roi, 1)
  2038. ch_base=base_roi(CH,:)';
  2039. ch_dat =squeeze(relDataEEG(CH,:,:)); % zscore original...
  2040. for TT=1:size(ch_dat, 1) % loop through time within trial
  2041. if doSTPResiduals == 1
  2042. % include STP in xes
  2043. xMat=[ones(size(ch_base)),goodData.meanSurprise,ch_base];
  2044. else
  2045. % exclude STP from xes
  2046. xMat=[ones(size(ch_base)),ch_base];
  2047. end
  2048. [~,~,resDataEEG(CH,TT,:)] = regress(zscore(ch_dat(TT,:)'),xMat);
  2049. end
  2050. end
  2051. end
  2052. end
  2053. if doEye == 1
  2054. relDataEye = allTrialAreasNorm;
  2055. if trialMeasure==3 % pull out variance that can be explained by baseline before taking dot product:
  2056. resDataEye=nan(size(relDataEye)); % preallocate space for residual data.
  2057. for TT=1:size(relDataEye, 2) % loop through time within trial
  2058. if doSTPResiduals == 1
  2059. % include STP in xes
  2060. xMat=[ones(size(subBaselineMeansNorm,2),1),allData.meanSurprise,subBaselineMeansNorm'];
  2061. else
  2062. % exclude STP from xes
  2063. xMat=[ones(size(subBaselineMeansNorm,2),1),subBaselineMeansNorm'];
  2064. end
  2065. y = allTrialAreasNorm(:,TT);
  2066. [~,~,resDataEye(:,TT)] = regress(y,xMat);
  2067. end
  2068. end
  2069. eye.resData = resDataEye;
  2070. end
  2071. %if subject has both good EEG and eye data, then for combined analyses you must remove bad eeg trials from
  2072. %eye data and then calculate mean trial effect again separately
  2073. if doEEG && doEye
  2074. goodData=selBehav(allData, epoch_OBCP-nPracticeTrials);
  2075. goodEyeData=selBehav(eye, epoch_OBCP-nPracticeTrials);
  2076. goodEyeData = goodEyeData.resData;
  2077. epochNumbersSel = epochNumbers-nPracticeTrials;
  2078. epochNumbersSel(epochNumbersSel<=0)=[];
  2079. allBadBlinksEEG(1:length(epoch_OBCP),:,sum(allDoEyeEEG))=allBadBlinksComb(epoch_OBCP-nPracticeTrials,:,sum(allDoEye));
  2080. end
  2081. %run loop to calculate trial by trial dot product for eeg...
  2082. if doEEG
  2083. for rr=1:size(relROIEEG.maps,3)
  2084. for t=1:size(relDataEEG,3)
  2085. tDataEEG=relDataEEG(:,:,t); % loop through trials.
  2086. if trialMeasure==1
  2087. meanTrialEffectEEG(t,rr,sum(allDoEEG))=nanmean(tDataEEG(relROIEEG.maps(:,:,rr)));
  2088. elseif trialMeasure==2
  2089. % use Anne Collins dot product method:
  2090. meanTrialEffectEEG(t,rr,sum(allDoEEG))=tData(relROIEEG.maps(:,:,rr))'*relROIEEG.fullTMap(relROIEEG.maps(:,:,rr));
  2091. elseif trialMeasure==3
  2092. % use dot product method on baseline-regressed residuals:
  2093. tDataEEG=resDataEEG(:,:,t); % loop through trials.
  2094. meanTrialEffectEEG(t,rr,sum(allDoEEG))=dot(tDataEEG(relROIEEG.maps(:,:,rr)),relROIEEG.fullTMap(relROIEEG.maps(:,:,rr)));
  2095. end
  2096. end
  2097. end
  2098. end
  2099. % ... and eye ...
  2100. if doEye
  2101. for rr=1:size(relROIEye.maps,3)
  2102. for t=1:size(relDataEye,1)
  2103. tDataEye=relDataEye(t,:); % loop through trials.
  2104. if trialMeasure==1
  2105. meanTrialEffectPupil(t,rr,sum(allDoEye))=nanmean(tDataEye(relROIEye.maps(:,:,rr)));
  2106. elseif trialMeasure==2
  2107. % use Anne Collins dot product method:
  2108. meanTrialEffectPupil(t,rr,sum(allDoEye))=tDataEye(relROIEye.maps(:,:,rr))'*relROIEye.fullTMap(relROIEye.maps(:,:,rr));
  2109. elseif trialMeasure==3
  2110. % use dot product method on baseline-regressed residuals:
  2111. tDataEye=resDataEye(t,:); % loop through trials.
  2112. meanTrialEffectPupil(t,rr,sum(allDoEye))=dot(tDataEye(relROIEye.maps(:,:,rr)),relROIEye.fullTMap(relROIEye.maps(:,:,rr)));
  2113. end
  2114. end
  2115. end
  2116. end
  2117. if doEEG
  2118. %make a version of mean trial effect with trials in true order rather than EEG epoch order
  2119. meanEffectEpochNumbers(epoch_OBCP-nPracticeTrials,:,sum(allDoEEG)) = meanTrialEffectEEG(1:length(epoch_OBCP),:,sum(allDoEEG));
  2120. end
  2121. % ... and eye data with EEG removed
  2122. if doEEG && doEye
  2123. for rr = 1:size(relROIEye.maps,3)
  2124. for t=1:size(goodEyeData,1)
  2125. tGoodEEGData = goodEyeData(t,:);
  2126. meanTrialEffectPGoodEEG(t,rr,sum(allDoEyeEEG))=dot(tGoodEEGData(relROIEye.maps(:,:,rr)),relROIEye.fullTMap(relROIEye.maps(:,:,rr)));
  2127. end
  2128. end
  2129. end
  2130. end
  2131. disp(subNum)
  2132. end
  2133. beep
  2134. %% Step 5: Quantify Relationship Between Learning/Bias and EEG/Pupil
  2135. % what follows is everything that needs to be done so mean trial effects can be combined in different ways
  2136. % eeg and eye data are different lengths, so the right trials have to be removed from both for them to be combined effectively
  2137. % this goes for trial average leaning and bias measurements as well
  2138. % CHANGE THIS BACK
  2139. % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2140. % allIndivRegBias = allMaxBias;
  2141. % allIndivRegBiasAll = allMaxBiasAll;
  2142. % allIndivRegBias = allRegBias;
  2143. % allIndivRegBiasAll = allRegBiasAll;
  2144. % CHANGE THIS BACK
  2145. % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2146. %sum/average meanTrialEffects
  2147. sumTrialEffectEEG = sum(meanTrialEffectEEG(:,:,:),2); %%%
  2148. meanTrialEffectEEGforEye = meanTrialEffectEEG(:,:,ismember(EEGSubs,eyeSubs)); %%%
  2149. sumTrialEffectEEGforEye = sumTrialEffectEEG(:,:,ismember(EEGSubs,eyeSubs));
  2150. eegEyeNumSubs = sum(ismember(EEGSubs,eyeSubs));
  2151. zMeanTrialEffectEEGforEye = [];
  2152. zMeanTrialEffectPGoodEEG = [];
  2153. zSumTrialEffectEEGforEye = [];
  2154. zMeanTrialEffectEEG = [];
  2155. slopes = [];
  2156. %zscore mean trial effects
  2157. for s = 1:eegEyeNumSubs
  2158. zSumTrialEffectEEGforEye(:,:,s) = nanzscore(sumTrialEffectEEGforEye(:,:,s));
  2159. zMeanTrialEffectEEGforEye(:,:,s) = nanzscore(meanTrialEffectEEGforEye(:,:,s));
  2160. zMeanTrialEffectPGoodEEG(:,:,s) = nanzscore(meanTrialEffectPGoodEEG(:,:,s));
  2161. end
  2162. for s = 1:length(EEGSubs)
  2163. zMeanTrialEffectEEG(:,:,s) = nanzscore(meanTrialEffectEEG(:,:,s)); %%%
  2164. end
  2165. sumTrialEffectEEG = sum(zMeanTrialEffectEEG(:,:,:),2);
  2166. %remove blinks from eye mean trial effects
  2167. sumTrialEffectEye = sum(zscore(meanTrialEffectPupil(:,:,:)),2);
  2168. sumTrialEffectEye(allBadBlinks) = nan;
  2169. %sum mean trial effect for eye
  2170. sumTrialEffectPGoodEEG = sum(zMeanTrialEffectPGoodEEG(:,:,:),2);
  2171. %preallocate variables for mini loop to combine eeg and eye data and remove the right trials from behavioral variables
  2172. allContextEEGEye = nan(nTrials,1,eegEyeNumSubs);
  2173. allRegBiasEEGEye = nan(nTrials,1,eegEyeNumSubs);
  2174. allRegLRsEEGEye = nan(nTrials,1,eegEyeNumSubs);
  2175. allRejTrialsEEGEye = nan(nTrials,1,eegEyeNumSubs);
  2176. allSurpriseEEGEye = nan(nTrials,1,eegEyeNumSubs);
  2177. zMeanTrialEffectEEGEye = nan(nTrials,2,eegEyeNumSubs);
  2178. zMeanTrialEffectEEGEyeSep = nan(nTrials,size(meanTrialEffectEEGforEye,2)+size(meanTrialEffectPGoodEEG,2),eegEyeNumSubs);
  2179. %concatenate eeg and eye effects, one with clusters separated, one with them together
  2180. meanTrialEffectEEGEye = [zSumTrialEffectEEGforEye,sumTrialEffectPGoodEEG];
  2181. meanTrialEffectEEGEyeSep = [zMeanTrialEffectEEGforEye,zMeanTrialEffectPGoodEEG];
  2182. clear allDoEye allDoEEG allDoEyeEEG
  2183. for s = 1:length(behaveSubs)
  2184. subno = behaveSubs(s);
  2185. %find whether subject has eye/eeg data
  2186. doEEG = ismember(subno,EEGSubs);
  2187. allDoEEG(s) = doEEG;
  2188. doEye = ismember(subno,eyeSubs);
  2189. allDoEye(s) = doEye;
  2190. %find if subject has both eeg and eye data and increment counter if so
  2191. if doEye && doEEG
  2192. doEyeEEG = 1;
  2193. else
  2194. doEyeEEG = 0;
  2195. end
  2196. allDoEyeEEG(s) = doEyeEEG;
  2197. if doEEG == 1
  2198. %remove bad blinks with more permissive threshold to compare with combined EEG + Eye data
  2199. zMeanTrialEffectEEGEye(1:sum(allBadBlinksEEG(:,:,sum(allDoEyeEEG))==0),:,sum(allDoEyeEEG)) = nanzscore(meanTrialEffectEEGEye(find(allBadBlinksEEG(:,:,sum(allDoEyeEEG))==0),:,sum(allDoEyeEEG)));
  2200. zMeanTrialEffectEEGEyeSep(1:sum(allBadBlinksEEG(:,:,sum(allDoEyeEEG))==0),:,sum(allDoEyeEEG)) = nanzscore(meanTrialEffectEEGEyeSep(find(allBadBlinksEEG(:,:,sum(allDoEyeEEG))==0),:,sum(allDoEyeEEG)));
  2201. allContextEEGEye(1:sum(allBadBlinksEEG(:,:,sum(allDoEyeEEG))==0),:,s) = allContext(find(allBadBlinksEEG(:,:,sum(allDoEyeEEG))==0),:,s);
  2202. allRegBiasEEGEye(1:sum(allBadBlinksEEG(:,:,sum(allDoEyeEEG))==0),:,s) = allIndivRegBias(find(allBadBlinksEEG(:,:,sum(allDoEyeEEG))==0),:,s);
  2203. allRegLRsEEGEye(1:sum(allBadBlinksEEG(:,:,sum(allDoEyeEEG))==0),:,s) = allIndivRegLRs(find(allBadBlinksEEG(:,:,sum(allDoEyeEEG))==0),:,s);
  2204. allRejTrialsEEGEye(1:sum(allBadBlinksEEG(:,:,sum(allDoEyeEEG))==0),:,s) = allRejTrials(find(allBadBlinksEEG(:,:,sum(allDoEyeEEG))==0),:,s);
  2205. end
  2206. end
  2207. sumTrialEffectEEGEye = sum(zMeanTrialEffectEEGEye,2);
  2208. numQuant = 5;
  2209. %preallocate variables for loop, mostly just LR and Bias for different data lengths
  2210. meanQuantValsEEG = nan(length(EEGSubs),numQuant);
  2211. meanQuantValsEye = nan(length(eyeSubs),numQuant);
  2212. meanAllLRs = mean(allIndivRegLRs,2);
  2213. meanAllLRs(meanAllLRs>1) = 1;
  2214. meanAllLRs(meanAllLRs<0) = 0;
  2215. meanAllBias = mean(allIndivRegBias,2);
  2216. meanAllBias(meanAllBias>1) = 1;
  2217. meanAllBias(meanAllBias<0) = 0;
  2218. meanAllLRsEye = mean(allIndivRegLRsAll,2);
  2219. meanAllLRsEye(meanAllLRsEye>1) = 1;
  2220. meanAllLRsEye(meanAllLRsEye<0) = 0;
  2221. meanAllBiasEye = mean(allIndivRegBiasAll,2);
  2222. meanAllBiasEye(meanAllBiasEye>1) = 1;
  2223. meanAllBiasEye(meanAllBiasEye<0) = 0;
  2224. meanAllLRsEEGEye = mean(allRegLRsEEGEye,2);
  2225. meanAllLRsEEGEye(meanAllLRsEEGEye>1) = 1;
  2226. meanAllLRsEEGEye(meanAllLRsEEGEye<0) = 0;
  2227. meanAllBiasEEGEye = mean(allRegBiasEEGEye,2);
  2228. meanAllBiasEEGEye(meanAllBiasEEGEye>1) = 1;
  2229. meanAllBiasEEGEye(meanAllBiasEEGEye<0) = 0;
  2230. quantSubsCPEEG = nan(length(EEGSubs),nTrials/2);
  2231. quantSubsOBEEG = nan(length(EEGSubs),nTrials/2);
  2232. quantSubsCPEye = nan(length(eyeSubs),nTrials/2);
  2233. quantSubsOBEye = nan(length(eyeSubs),nTrials/2);
  2234. LRCPslopeEEG = nan(length(EEGSubs),2);
  2235. biasCPslopeEEG = nan(length(EEGSubs),2);
  2236. LROBslopeEEG = nan(length(EEGSubs),2);
  2237. biasOBslopeEEG = nan(length(EEGSubs),2);
  2238. biasAllslopeEEG = nan(length(EEGSubs),2);
  2239. LRCPslopeEye = nan(length(eyeSubs),2);
  2240. biasCPslopeEye = nan(length(eyeSubs),2);
  2241. LROBslopeEye = nan(length(eyeSubs),2);
  2242. biasOBslopeEye = nan(length(eyeSubs),2);
  2243. biasAllslopeEye = nan(length(eyeSubs),2);
  2244. LRCPslopeEEGSep = nan(length(EEGSubs),2);
  2245. biasCPslopeEEGSep = nan(length(EEGSubs),2);
  2246. LROBslopeEEGSep = nan(length(EEGSubs),2);
  2247. biasOBslopeEEGSep = nan(length(EEGSubs),2);
  2248. biasAllslopeEEGSep = nan(length(EEGSubs),2);
  2249. LRCPslopeEEGEye = nan(eegEyeNumSubs,2);
  2250. biasCPslopeEEGEye = nan(eegEyeNumSubs,2);
  2251. LROBslopeEEGEye = nan(eegEyeNumSubs,2);
  2252. biasOBslopeEEGEye = nan(eegEyeNumSubs,2);
  2253. biasAllslopeEEGEye = nan(eegEyeNumSubs,2);
  2254. biasAllSlopes = nan(size(zMeanTrialEffectEEG,2),1,length(EEGSubs));
  2255. LRAllSlopes = nan(size(zMeanTrialEffectEEG,2),1,length(EEGSubs));
  2256. biasCPAllSlopes = nan(size(zMeanTrialEffectEEG,2),1,length(EEGSubs));
  2257. LRCPAllSlopes = nan(size(zMeanTrialEffectEEG,2),1,length(EEGSubs));
  2258. biasOBAllSlopes = nan(size(zMeanTrialEffectEEG,2),1,length(EEGSubs));
  2259. LROBAllSlopes = nan(size(zMeanTrialEffectEEG,2),1,length(EEGSubs));
  2260. varSlopes = nan(size(zMeanTrialEffectEEG,2),6,length(EEGSubs));
  2261. clear allDoEye allDoEEG allDoEyeEEG
  2262. for s = [1:length(behaveSubs)]
  2263. disp(s);
  2264. subNum = num2str(behaveSubs(s));
  2265. subno = behaveSubs(s);
  2266. %find whether subject has good eeg/eye/both data, and increment counters (allDo variables) if true
  2267. doEEG = ismember(subno,EEGSubs);
  2268. allDoEEG(s) = doEEG;
  2269. doEye = ismember(subno,eyeSubs);
  2270. allDoEye(s) = doEye;
  2271. if doEye && doEEG
  2272. doEyeEEG = 1;
  2273. else
  2274. doEyeEEG = 0;
  2275. end
  2276. allDoEyeEEG(s) = doEyeEEG;
  2277. if doEEG
  2278. %quantiling and stuff for EEG data only
  2279. numTrials = length(find(isfinite(sumTrialEffectEEG(:,1,sum(allDoEEG)))));
  2280. allData=load(fullfile([behaveDir,'subCombined/', subNum, '_3and4BlockData.mat']));
  2281. allData = allData.alldata;
  2282. condition = allData.condition(1);
  2283. %calculate quantiles for sum of mean trial effects
  2284. eegTrials = allRejTrials(:,:,s)==1;
  2285. eegTrialsCP = allRejTrials(:,:,s)==1 & allContext(:,:,s)==1;
  2286. eegTrialsOB = allRejTrials(:,:,s)==1 & allContext(:,:,s)==-1;
  2287. borders = quantile(sumTrialEffectEEG(eegTrials,:,sum(allDoEEG)),numQuant-1);
  2288. bordersCP = quantile(sumTrialEffectEEG(eegTrialsCP,:,sum(allDoEEG)),numQuant-1);
  2289. bordersOB = quantile(sumTrialEffectEEG(eegTrialsOB,:,sum(allDoEEG)),numQuant-1);
  2290. quantiles = zeros(numTrials,1);
  2291. quantilesCP = [];
  2292. quantilesOB = [];
  2293. %assign each trial to a quantile (1-numQuant) based on sum (lowest = 1)
  2294. for q = numQuant:-1:1
  2295. if q<numQuant
  2296. quantilesCP(sumTrialEffectEEG(eegTrialsCP,:,sum(allDoEEG))<=bordersCP(q)) = q;
  2297. quantilesOB(sumTrialEffectEEG(eegTrialsOB,:,sum(allDoEEG))<=bordersOB(q)) = q;
  2298. quantiles(sumTrialEffectEEG(eegTrials,:,sum(allDoEEG))<=borders(q)) = q;
  2299. else
  2300. quantilesCP(sumTrialEffectEEG(eegTrialsCP,:,sum(allDoEEG))>bordersCP(q-1)) = q;
  2301. quantilesOB(sumTrialEffectEEG(eegTrialsOB,:,sum(allDoEEG))>bordersOB(q-1)) = q;
  2302. quantiles(sumTrialEffectEEG(eegTrials,:,sum(allDoEEG))>borders(q-1)) = q;
  2303. end
  2304. end
  2305. % add number of zeros of trials in first block (CP/OB) to beginning of second block (OB/CP) so everything lines up right
  2306. if allContext(1,:,s) == 1
  2307. quantilesOB = [zeros(length(quantilesCP),1);quantilesOB'];
  2308. quantilesCP = quantilesCP';
  2309. disp(1);
  2310. else
  2311. quantilesCP = [zeros(length(quantilesOB),1);quantilesCP'];
  2312. quantilesOB = quantilesOB';
  2313. disp(2);
  2314. end
  2315. for q = numQuant:-1:1
  2316. % find which CP and OB trials are within quantile
  2317. quantCP = quantilesCP==q;
  2318. quantOB = quantilesOB==q;
  2319. % find LR & bias for trials within the quantile
  2320. subLRs = meanAllLRs(eegTrials,:,s);
  2321. subBias = meanAllBias(eegTrials,:,s);
  2322. subEEG = sumTrialEffectEEG(eegTrials,:,sum(allDoEEG));
  2323. quantCPLRs = subLRs(quantCP);
  2324. quantCPBias= subBias(quantCP);
  2325. quantCPVals= subEEG(quantCP);
  2326. quantOBLRs = subLRs(quantOB);
  2327. quantOBBias= subBias(quantOB);
  2328. quantOBVals= subEEG(quantOB);
  2329. %take mean LR and Bias for each quantile
  2330. meanQuantCPLRsEEG(sum(allDoEEG),q) = nanmean(quantCPLRs);
  2331. meanQuantCPBiasEEG(sum(allDoEEG),q) = nanmean(quantCPBias);
  2332. meanQuantCPValsEEG(sum(allDoEEG),q) = mean(quantCPVals);
  2333. meanQuantOBLRsEEG(sum(allDoEEG),q) = nanmean(quantOBLRs);
  2334. meanQuantOBBiasEEG(sum(allDoEEG),q) = nanmean(quantOBBias);
  2335. meanQuantOBValsEEG(sum(allDoEEG),q) = mean(quantOBVals);
  2336. end
  2337. quantilesCP(isnan(quantilesCP)) = [];
  2338. quantilesOB(isnan(quantilesOB)) = [];
  2339. quantilesCP(quantilesCP==0) = [];
  2340. quantilesOB(quantilesOB==0) = [];
  2341. %save info of what trial is in which quantile for each subject
  2342. quantSubsCPEEG(sum(allDoEEG),1:length(quantilesCP)) = quantilesCP;
  2343. quantSubsOBEEG(sum(allDoEEG),1:length(quantilesOB)) = quantilesOB;
  2344. %testing hypothesis 5
  2345. %Rank order column 1 physio effect, col 2 LR, col3 bias
  2346. rankOrderCP = sumTrialEffectEEG(eegTrialsCP,:,sum(allDoEEG));
  2347. rankOrderCP(:,2) = meanAllLRs(eegTrialsCP,:,s);
  2348. rankOrderCP(:,3) = meanAllBias(eegTrialsCP,:,s);
  2349. %sort rank order based on physio effect
  2350. rankOrderCPSorted = sortrows(rankOrderCP,1,"ascend");
  2351. %repeat for oddball
  2352. rankOrderOB = sumTrialEffectEEG(eegTrialsOB,:,sum(allDoEEG));
  2353. rankOrderOB(:,2) = meanAllLRs(eegTrialsOB,:,s);
  2354. rankOrderOB(:,3) = meanAllBias(eegTrialsOB,:,s);
  2355. rankOrderOBSorted = sortrows(rankOrderOB,1,"ascend");
  2356. xIntCP = ones(sum(eegTrialsCP),1);
  2357. xIntOB = ones(sum(eegTrialsOB),1);
  2358. %regress bias against each trial's physiologial effect (how much eeg cluster) rank in block
  2359. LRCPslopeEEG(sum(allDoEEG),:) = regress(rankOrderCPSorted(:,2),[xIntCP,(1:length(xIntCP))']);
  2360. biasCPslopeEEG(sum(allDoEEG),:) = regress(rankOrderCPSorted(:,3),[xIntCP,(1:length(xIntCP))']);
  2361. LROBslopeEEG(sum(allDoEEG),:) = regress(rankOrderOBSorted(:,2),[xIntOB,(1:length(xIntOB))']);
  2362. biasOBslopeEEG(sum(allDoEEG),:) = regress(rankOrderOBSorted(:,3),[xIntOB,(1:length(xIntOB))']);
  2363. biasAllslopeEEG(sum(allDoEEG),:) = regress([rankOrderCPSorted(:,3);rankOrderOBSorted(:,3)],[[xIntCP;xIntOB],[(1:length(xIntCP))';(1:length(xIntOB))']]);
  2364. %OR regress against raw signal strength rather than rank order (gives better results probably because of distribution
  2365. LRCPslopeEEG(sum(allDoEEG),:) = regress((rankOrderCPSorted(:,2)),[xIntCP,(rankOrderCPSorted(:,1))]);
  2366. err = rankOrderCPSorted;
  2367. biasCPslopeEEG(sum(allDoEEG),:) = regress((rankOrderCPSorted(:,3)),[xIntCP,(rankOrderCPSorted(:,1))]);
  2368. LROBslopeEEG(sum(allDoEEG),:) = regress((rankOrderOBSorted(:,2)),[xIntOB,(rankOrderOBSorted(:,1))]);
  2369. biasOBslopeEEG(sum(allDoEEG),:) = regress((rankOrderOBSorted(:,3)),[xIntOB,(rankOrderOBSorted(:,1))]);
  2370. biasAllslopeEEG(sum(allDoEEG),:) = regress(([rankOrderCPSorted(:,3);rankOrderOBSorted(:,3)]),[[xIntCP;xIntOB],([rankOrderCPSorted(:,1);rankOrderOBSorted(:,1)])]);
  2371. for rr = 1:size(zMeanTrialEffectEEG,2)
  2372. %calculate regression results for each eeg cluster and pupil data separately
  2373. %Rank order column 1 physio effect, col 2 LR, col3 bias
  2374. rankOrderCP = zMeanTrialEffectEEG(eegTrialsCP,rr,sum(allDoEEG));
  2375. rankOrderCP(:,2) = meanAllLRs(eegTrialsCP,:,s);
  2376. rankOrderCP(:,3) = meanAllBias(eegTrialsCP,:,s);
  2377. %sort rank order based on physio effect
  2378. rankOrderCPSorted = sortrows(rankOrderCP,1,"ascend");
  2379. %repeat for oddball
  2380. rankOrderOB = zMeanTrialEffectEEG(eegTrialsOB,rr,sum(allDoEEG));
  2381. rankOrderOB(:,2) = meanAllLRs(eegTrialsOB,:,s);
  2382. rankOrderOB(:,3) = meanAllBias(eegTrialsOB,:,s);
  2383. rankOrderOBSorted = sortrows(rankOrderOB,1,"ascend");
  2384. xIntCP = ones(sum(eegTrialsCP),1);
  2385. xIntOB = ones(sum(eegTrialsOB),1);
  2386. %regress bias against each trial's physiologial effect (how much eeg cluster) rank in block
  2387. LRCPslopeEEGSep(sum(allDoEEG),:) = regress(rankOrderCPSorted(:,2),[xIntCP,(1:length(xIntCP))']);
  2388. biasCPslopeEEGSep(sum(allDoEEG),:) = regress(rankOrderCPSorted(:,3),[xIntCP,(1:length(xIntCP))']);
  2389. LROBslopeEEGSep(sum(allDoEEG),:) = regress(rankOrderOBSorted(:,2),[xIntOB,(1:length(xIntOB))']);
  2390. biasOBslopeEEGSep(sum(allDoEEG),:) = regress(rankOrderOBSorted(:,3),[xIntOB,(1:length(xIntOB))']);
  2391. biasAllslopeEEGSep(sum(allDoEEG),:) = regress([rankOrderCPSorted(:,3);rankOrderOBSorted(:,3)],[[xIntCP;xIntOB],[(1:length(xIntCP))';(1:length(xIntOB))']]);
  2392. %OR regress against raw signal strength rather than rank order (gives better results probably because of distribution
  2393. LRCPslopeEEGSep(sum(allDoEEG),:) = regress((rankOrderCPSorted(:,2)),[xIntCP,(rankOrderCPSorted(:,1))]);
  2394. biasCPslopeEEGSep(sum(allDoEEG),:) = regress((rankOrderCPSorted(:,3)),[xIntCP,(rankOrderCPSorted(:,1))]);
  2395. LROBslopeEEGSep(sum(allDoEEG),:) = regress((rankOrderOBSorted(:,2)),[xIntOB,(rankOrderOBSorted(:,1))]);
  2396. biasOBslopeEEGSep(sum(allDoEEG),:) = regress((rankOrderOBSorted(:,3)),[xIntOB,(rankOrderOBSorted(:,1))]);
  2397. biasAllslopeEEGSep(sum(allDoEEG),:) = regress(([rankOrderCPSorted(:,3);rankOrderOBSorted(:,3)]),[[xIntCP;xIntOB],([rankOrderCPSorted(:,1);rankOrderOBSorted(:,1)])]);
  2398. varSlopes(rr,:,sum(allDoEEG)) = [biasCPslopeEEGSep(sum(allDoEEG),2),biasOBslopeEEGSep(sum(allDoEEG),2),biasCPslopeEEGSep(sum(allDoEEG),2)+biasOBslopeEEGSep(sum(allDoEEG),2),LRCPslopeEEGSep(sum(allDoEEG),2),LROBslopeEEGSep(sum(allDoEEG),2),LRCPslopeEEGSep(sum(allDoEEG),2)-LROBslopeEEGSep(sum(allDoEEG),2)];
  2399. biasAllSlopes(rr,:,sum(allDoEEG)) = biasCPslopeEEGSep(sum(allDoEEG),2)+biasOBslopeEEGSep(sum(allDoEEG),2);
  2400. LRAllSlopes(rr,:,sum(allDoEEG)) = LRCPslopeEEGSep(sum(allDoEEG),2)-LROBslopeEEGSep(sum(allDoEEG),2);
  2401. biasCPAllSlopes(rr,:,sum(allDoEEG)) = biasCPslopeEEGSep(sum(allDoEEG),2);
  2402. LRCPAllSlopes(rr,:,sum(allDoEEG)) = LRCPslopeEEGSep(sum(allDoEEG),2);
  2403. biasOBAllSlopes(rr,:,sum(allDoEEG)) = biasOBslopeEEGSep(sum(allDoEEG),2);
  2404. LROBAllSlopes(rr,:,sum(allDoEEG)) = LROBslopeEEGSep(sum(allDoEEG),2);
  2405. end
  2406. end
  2407. if doEye
  2408. %quantiling and stuff for eye data only
  2409. numTrials = nTrials;
  2410. allData=load(fullfile([behaveDir,'subCombined/', subNum, '_3and4BlockData.mat']));
  2411. allData = allData.alldata;
  2412. condition = allData.condition(1);
  2413. eyeTrials = allRejTrialsAll(:,:,s)==1 & ~allBadBlinks(:,:,sum(allDoEye));
  2414. eyeTrialsCP = eyeTrials & allContextAll(:,:,s)==1;
  2415. eyeTrialsOB = eyeTrials & allContextAll(:,:,s)==-1;
  2416. %calculate quantiles for sum of mean trial effects
  2417. borders = quantile(sumTrialEffectEye(eyeTrials,:,sum(allDoEye)),numQuant-1);
  2418. bordersCP = quantile(sumTrialEffectEye(eyeTrialsCP,:,sum(allDoEye)),numQuant-1);
  2419. bordersOB = quantile(sumTrialEffectEye(eyeTrialsOB,:,sum(allDoEye)),numQuant-1);
  2420. quantiles = zeros(sum(eyeTrials),1);
  2421. quantilesCP = zeros(sum(eyeTrialsCP),1);
  2422. quantilesOB = zeros(sum(eyeTrialsOB),1);
  2423. %assign each trial to a quantile (1-numQuant) based on sum (lowest = 1)
  2424. for q = numQuant:-1:1
  2425. if q<numQuant
  2426. quantilesCP(sumTrialEffectEye(eyeTrialsCP,:,sum(allDoEye))<=bordersCP(q)) = q;
  2427. quantilesOB(sumTrialEffectEye(eyeTrialsOB,:,sum(allDoEye))<=bordersOB(q)) = q;
  2428. quantiles(sumTrialEffectEye(eyeTrials,:,sum(allDoEye))<=borders(q)) = q;
  2429. else
  2430. quantilesCP(sumTrialEffectEye(eyeTrialsCP,:,sum(allDoEye))>bordersCP(q-1)) = q;
  2431. quantilesOB(sumTrialEffectEye(eyeTrialsOB,:,sum(allDoEye))>bordersOB(q-1)) = q;
  2432. quantiles(sumTrialEffectEye(eyeTrials,:,sum(allDoEye))>borders(q-1)) = q;
  2433. end
  2434. end
  2435. % add number of zeros of trials in first block (CP/OB) to beginning of second block (OB/CP) so everything lines up right
  2436. if allContextAll(1,:,s) == 1
  2437. quantilesOB = [zeros(length(quantilesCP),1);quantilesOB];
  2438. quantilesCP = quantilesCP;
  2439. disp(1);
  2440. else
  2441. quantilesCP = [zeros(length(quantilesOB),1);quantilesCP];
  2442. quantilesOB = quantilesOB;
  2443. disp(2);
  2444. end
  2445. for q = numQuant:-1:1
  2446. % find which CP and OB trials are within quantile
  2447. quantCP = quantilesCP==q;
  2448. quantOB = quantilesOB==q;
  2449. % find LR & bias for trials within the quantile
  2450. subLRs = meanAllLRsEye(eyeTrials,:,s);
  2451. subBias = meanAllBiasEye(eyeTrials,:,s);
  2452. subEye = sumTrialEffectEye(eyeTrials,:,sum(allDoEye));
  2453. quantCPLRs = subLRs(quantCP);
  2454. quantCPBias= subBias(quantCP);
  2455. quantCPVals= subEye(quantCP);
  2456. quantOBLRs = subLRs(quantOB);
  2457. quantOBBias= subBias(quantOB);
  2458. quantOBVals= subEye(quantOB);
  2459. % quantCPLRs = meanAllLRsEye(quantCP,:,s);
  2460. % quantCPBias= meanAllBiasEye(quantCP,:,s);
  2461. % quantCPVals= sumTrialEffectEye(quantCP,:,sum(allDoEye));
  2462. % quantOBLRs = meanAllLRsEye(quantOB,:,s);
  2463. % quantOBBias= meanAllBiasEye(quantOB,:,s);
  2464. % quantOBVals= sumTrialEffectEye(quantOB,:,sum(allDoEye));
  2465. %take mean LR and Bias for each quantile
  2466. meanQuantCPLRsEye(sum(allDoEye),q) = nanmean(quantCPLRs);
  2467. meanQuantCPBiasEye(sum(allDoEye),q) = nanmean(quantCPBias);
  2468. meanQuantCPValsEye(sum(allDoEye),q) = mean(quantCPVals);
  2469. meanQuantOBLRsEye(sum(allDoEye),q) = nanmean(quantOBLRs);
  2470. meanQuantOBBiasEye(sum(allDoEye),q) = nanmean(quantOBBias);
  2471. meanQuantOBValsEye(sum(allDoEye),q) = mean(quantOBVals);
  2472. end
  2473. quantilesCP(isnan(quantilesCP)) = [];
  2474. quantilesOB(isnan(quantilesOB)) = [];
  2475. quantilesCP(quantilesCP==0) = [];
  2476. quantilesOB(quantilesOB==0) = [];
  2477. %save info of what trial is in which quantile for each subject
  2478. % if condition == 1
  2479. quantSubsCPEye(sum(allDoEye),1:length(quantilesCP)) = quantilesCP;
  2480. quantSubsOBEye(sum(allDoEye),1:length(quantilesOB)) = quantilesOB;
  2481. %testing hypothesis 5
  2482. %Rank order column 1 physio effect, col 2 LR, col3 bias
  2483. rankOrderCP = sumTrialEffectEye(eyeTrialsCP,:,sum(allDoEye));
  2484. rankOrderCP(:,2) = meanAllLRsEye(eyeTrialsCP,:,s);
  2485. rankOrderCP(:,3) = meanAllBiasEye(eyeTrialsCP,:,s);
  2486. %sort rank order based on physio effect
  2487. rankOrderCPSorted = sortrows(rankOrderCP,1,"ascend");
  2488. %repeat for oddball
  2489. rankOrderOB = sumTrialEffectEye(eyeTrialsOB,:,sum(allDoEye));
  2490. rankOrderOB(:,2) = meanAllLRsEye(eyeTrialsOB,:,s);
  2491. rankOrderOB(:,3) = meanAllBiasEye(eyeTrialsOB,:,s);
  2492. rankOrderOBSorted = sortrows(rankOrderOB,1,"ascend");
  2493. xIntCP = ones(sum(eyeTrialsCP),1);
  2494. xIntOB = ones(sum(eyeTrialsOB),1);
  2495. %regress bias against each trial's physiologial effect (how much eeg cluster) rank in block
  2496. LRCPslopeEye(sum(allDoEye),:) = regress(rankOrderCPSorted(:,2),[xIntCP,(1:length(xIntCP))']);
  2497. biasCPslopeEye(sum(allDoEye),:) = regress(rankOrderCPSorted(:,3),[xIntCP,(1:length(xIntCP))']);
  2498. LROBslopeEye(sum(allDoEye),:) = regress(rankOrderOBSorted(:,2),[xIntOB,(1:length(xIntOB))']);
  2499. biasOBslopeEye(sum(allDoEye),:) = regress(rankOrderOBSorted(:,3),[xIntOB,(1:length(xIntOB))']);
  2500. biasAllslopeEye(sum(allDoEye),:) = regress([rankOrderCPSorted(:,3);rankOrderOBSorted(:,3)],[[xIntCP;xIntOB],[(1:length(xIntCP))';(1:length(xIntOB))']]);
  2501. %OR regress against raw signal strength rather than rank order (gives better results probably because of distribution
  2502. LRCPslopeEye(sum(allDoEye),:) = regress((rankOrderCPSorted(:,2)),[xIntCP,(rankOrderCPSorted(:,1))]);
  2503. biasCPslopeEye(sum(allDoEye),:) = regress((rankOrderCPSorted(:,3)),[xIntCP,(rankOrderCPSorted(:,1))]);
  2504. LROBslopeEye(sum(allDoEye),:) = regress((rankOrderOBSorted(:,2)),[xIntOB,(rankOrderOBSorted(:,1))]);
  2505. biasOBslopeEye(sum(allDoEye),:) = regress((rankOrderOBSorted(:,3)),[xIntOB,zscore(rankOrderOBSorted(:,1))]);
  2506. biasAllslopeEye(sum(allDoEye),:) = regress(([rankOrderCPSorted(:,3);rankOrderOBSorted(:,3)]),[[xIntCP;xIntOB],([rankOrderCPSorted(:,1);rankOrderOBSorted(:,1)])]);
  2507. end
  2508. if doEyeEEG
  2509. %quantiling and stuff for eeg + eye data where eeg clusters have been summed and equally weighted with pupil
  2510. numTrials = length(find(isfinite(sumTrialEffectEEGEye(:,1,sum(allDoEyeEEG)))));
  2511. allData=load(fullfile([behaveDir,'subCombined/', subNum, '_3and4BlockData.mat']));
  2512. allData = allData.alldata;
  2513. condition = allData.condition(1);
  2514. eegEyeTrials = allRejTrialsEEGEye(:,:,s)==1;
  2515. eegEyeTrialsCP = allRejTrialsEEGEye(:,:,s)==1 & allContextEEGEye(:,:,s)==1;
  2516. eegEyeTrialsOB = allRejTrialsEEGEye(:,:,s)==1 & allContextEEGEye(:,:,s)==-1;
  2517. %calculate quantiles for sum of mean trial effects
  2518. borders = quantile(sumTrialEffectEEGEye(eegEyeTrials,:,sum(allDoEyeEEG)),numQuant-1);
  2519. bordersCP = quantile(sumTrialEffectEEGEye(eegEyeTrialsCP,:,sum(allDoEyeEEG)),numQuant-1);
  2520. bordersOB = quantile(sumTrialEffectEEGEye(eegEyeTrialsOB,:,sum(allDoEyeEEG)),numQuant-1);
  2521. quantiles = zeros(numTrials,1);
  2522. quantilesCP = [];
  2523. quantilesOB = [];
  2524. %assign each trial to a quantile (1-numQuant) based on sum (lowest = 1)
  2525. for q = numQuant:-1:1
  2526. if q<numQuant
  2527. quantilesCP(sumTrialEffectEEGEye(eegEyeTrialsCP,:,sum(allDoEyeEEG))<=bordersCP(q)) = q;
  2528. quantilesOB(sumTrialEffectEEGEye(eegEyeTrialsOB,:,sum(allDoEyeEEG))<=bordersOB(q)) = q;
  2529. quantiles(sumTrialEffectEEGEye(eegEyeTrials,:,sum(allDoEyeEEG))<=borders(q)) = q;
  2530. else
  2531. quantilesCP(sumTrialEffectEEGEye(eegEyeTrialsCP,:,sum(allDoEyeEEG))>bordersCP(q-1)) = q;
  2532. quantilesOB(sumTrialEffectEEGEye(eegEyeTrialsOB,:,sum(allDoEyeEEG))>bordersOB(q-1)) = q;
  2533. quantiles(sumTrialEffectEEGEye(eegEyeTrials,:,sum(allDoEyeEEG))>borders(q-1)) = q;
  2534. end
  2535. end
  2536. % add number of zeros of trials in first block (CP/OB) to beginning of second block (OB/CP) so everything lines up right
  2537. if allContextEEGEye(1,:,s) == 1
  2538. quantilesOB = [zeros(length(quantilesCP),1);quantilesOB'];
  2539. quantilesCP = quantilesCP';
  2540. disp(1);
  2541. else
  2542. quantilesCP = [zeros(length(quantilesOB),1);quantilesCP'];
  2543. quantilesOB = quantilesOB';
  2544. disp(2);
  2545. end
  2546. for q = numQuant:-1:1
  2547. % find which CP and OB trials are within quantile
  2548. quantCP = quantilesCP==q;
  2549. quantOB = quantilesOB==q;
  2550. % find LR & bias for trials within the quantile
  2551. subLRs = meanAllLRsEEGEye(eegEyeTrials,:,s);
  2552. subBias = meanAllBiasEEGEye(eegEyeTrials,:,s);
  2553. subEEG = sumTrialEffectEEGEye(eegEyeTrials,:,sum(allDoEyeEEG));
  2554. quantCPLRs = subLRs(quantCP);
  2555. quantCPBias= subBias(quantCP);
  2556. quantCPVals= subEEG(quantCP);
  2557. quantOBLRs = subLRs(quantOB);
  2558. quantOBBias= subBias(quantOB);
  2559. quantOBVals= subEEG(quantOB);
  2560. % quantCPLRs = meanAllLRsEEGEye(quantCP,:,s);
  2561. % quantCPBias= meanAllBiasEEGEye(quantCP,:,s);
  2562. % quantCPVals= sumTrialEffectEEGEye(quantCP,:,sum(allDoEyeEEG));
  2563. % quantOBLRs = meanAllLRsEEGEye(quantOB,:,s);
  2564. % quantOBBias= meanAllBiasEEGEye(quantOB,:,s);
  2565. % quantOBVals= sumTrialEffectEEGEye(quantOB,:,sum(allDoEyeEEG));
  2566. %take mean LR and Bias for each quantile
  2567. meanQuantCPLRsEEGEye(sum(allDoEyeEEG),q) = nanmean(quantCPLRs);
  2568. meanQuantCPBiasEEGEye(sum(allDoEyeEEG),q) = nanmean(quantCPBias);
  2569. meanQuantCPValsEEGEye(sum(allDoEyeEEG),q) = mean(quantCPVals);
  2570. meanQuantOBLRsEEGEye(sum(allDoEyeEEG),q) = nanmean(quantOBLRs);
  2571. meanQuantOBBiasEEGEye(sum(allDoEyeEEG),q) = nanmean(quantOBBias);
  2572. meanQuantOBValsEEGEye(sum(allDoEyeEEG),q) = mean(quantOBVals);
  2573. end
  2574. quantilesCP(isnan(quantilesCP)) = [];
  2575. quantilesOB(isnan(quantilesOB)) = [];
  2576. quantilesCP(quantilesCP==0) = [];
  2577. quantilesOB(quantilesOB==0) = [];
  2578. %save info of what trial is in which quantile for each subject
  2579. quantSubsCPEEGEye(sum(allDoEyeEEG),1:length(quantilesCP)) = quantilesCP;
  2580. quantSubsOBEEGEye(sum(allDoEyeEEG),1:length(quantilesOB)) = quantilesOB;
  2581. %testing hypothesis 5
  2582. %Rank order column 1 physio effect, col 2 LR, col3 bias
  2583. rankOrderCP = sumTrialEffectEEGEye(eegEyeTrialsCP,:,sum(allDoEyeEEG));
  2584. rankOrderCP(:,2) = meanAllLRsEEGEye(eegEyeTrialsCP,:,s);
  2585. rankOrderCP(:,3) = meanAllBiasEEGEye(eegEyeTrialsCP,:,s);
  2586. %sort rank order based on physio effect
  2587. rankOrderCPSorted = sortrows(rankOrderCP,1,"ascend");
  2588. %repeat for oddball
  2589. rankOrderOB = sumTrialEffectEEGEye(eegEyeTrialsOB,:,sum(allDoEyeEEG));
  2590. rankOrderOB(:,2) = meanAllLRsEEGEye(eegEyeTrialsOB,:,s);
  2591. rankOrderOB(:,3) = meanAllBiasEEGEye(eegEyeTrialsOB,:,s);
  2592. rankOrderOBSorted = sortrows(rankOrderOB,1,"ascend");
  2593. xIntCP = ones(sum(eegEyeTrialsCP),1);
  2594. xIntOB = ones(sum(eegEyeTrialsOB),1);
  2595. %regress bias against each trial's physiologial effect (how much eeg cluster) rank in block
  2596. LRCPslopeEEGEye(sum(allDoEyeEEG),:) = regress(rankOrderCPSorted(:,2),[xIntCP,(1:length(xIntCP))']);
  2597. biasCPslopeEEGEye(sum(allDoEyeEEG),:) = regress(rankOrderCPSorted(:,3),[xIntCP,(1:length(xIntCP))']);
  2598. LROBslopeEEGEye(sum(allDoEyeEEG),:) = regress(rankOrderOBSorted(:,2),[xIntOB,(1:length(xIntOB))']);
  2599. biasOBslopeEEGEye(sum(allDoEyeEEG),:) = regress(rankOrderOBSorted(:,3),[xIntOB,(1:length(xIntOB))']);
  2600. biasAllslopeEEGEye(sum(allDoEyeEEG),:) = regress([rankOrderCPSorted(:,3);rankOrderOBSorted(:,3)],[[xIntCP;xIntOB],[(1:length(xIntCP))';(1:length(xIntOB))']]);
  2601. %OR regress against raw signal strength rather than rank order (gives better results probably because of distribution
  2602. LRCPslopeEEGEye(sum(allDoEyeEEG),:) = regress((rankOrderCPSorted(:,2)),[xIntCP,(rankOrderCPSorted(:,1))]);
  2603. biasCPslopeEEGEye(sum(allDoEyeEEG),:) = regress((rankOrderCPSorted(:,3)),[xIntCP,(rankOrderCPSorted(:,1))]);
  2604. LROBslopeEEGEye(sum(allDoEyeEEG),:) = regress((rankOrderOBSorted(:,2)),[xIntOB,(rankOrderOBSorted(:,1))]);
  2605. biasOBslopeEEGEye(sum(allDoEyeEEG),:) = regress((rankOrderOBSorted(:,3)),[xIntOB,(rankOrderOBSorted(:,1))]);
  2606. biasAllslopeEEGEye(sum(allDoEyeEEG),:) = regress(([rankOrderCPSorted(:,3);rankOrderOBSorted(:,3)]),[[xIntCP;xIntOB],([rankOrderCPSorted(:,1);rankOrderOBSorted(:,1)])]);
  2607. disp(s)
  2608. end
  2609. end
  2610. % calculate p values of bias/lr cp/ob slopes for eeg ...
  2611. [~,pLRCPEEG] = ttest(LRCPslopeEEG(:,2));
  2612. [~,pLROBEEG] = ttest(LROBslopeEEG(:,2));
  2613. [~,pBiasCPEEG] = ttest(biasCPslopeEEG(:,2));
  2614. [~,pBiasOBEEG] = ttest(biasOBslopeEEG(:,2));
  2615. [~,pBiasAllEEG] = ttest(biasAllslopeEEG(:,2));
  2616. [~,pBiasSumEEG] = ttest(biasCPslopeEEG(:,2)+biasOBslopeEEG(:,2));
  2617. [~,pLRDiffEEG] = ttest(LRCPslopeEEG(:,2)-LROBslopeEEG(:,2));
  2618. [~,pBiasSumEEGSep] = ttest(squeeze(biasAllSlopes)');
  2619. [~,pLRDiffEEGSep] = ttest(squeeze(LRAllSlopes)');
  2620. [~,pBiasCPEEGSep] = ttest(squeeze(biasCPAllSlopes)');
  2621. [~,pLRCPEEGSep] = ttest(squeeze(LRCPAllSlopes)');
  2622. [~,pBiasOBEEGSep] = ttest(squeeze(biasOBAllSlopes)');
  2623. [~,pLROBEEGSep] = ttest(squeeze(LROBAllSlopes)');
  2624. meanVarSlopes = mean(varSlopes,3);
  2625. varP = [pBiasCPEEGSep',pBiasOBEEGSep',pBiasSumEEGSep',pLRCPEEGSep',pLROBEEGSep',pLRDiffEEGSep'];
  2626. % ... eye data ...
  2627. [~,pLRCPEye] = ttest(LRCPslopeEye(:,2));
  2628. [~,pLROBEye] = ttest(LROBslopeEye(:,2));
  2629. [~,pBiasCPEye] = ttest(biasCPslopeEye(:,2));
  2630. [~,pBiasOBEye] = ttest(biasOBslopeEye(:,2));
  2631. [~,pBiasAllEye] = ttest(biasAllslopeEye(:,2));
  2632. [~,pBiasSumEye] = ttest(biasCPslopeEye(:,2)+biasOBslopeEye(:,2));
  2633. [~,pLRDiffEye] = ttest(LRCPslopeEye(:,2)-LROBslopeEye(:,2));
  2634. % ... and both forms of data combined
  2635. [~,pLRCPEEGEye] = ttest(LRCPslopeEEGEye(:,2));
  2636. [~,pLROBEEGEye] = ttest(LROBslopeEEGEye(:,2));
  2637. [~,pBiasCPEEGEye] = ttest(biasCPslopeEEGEye(:,2));
  2638. [~,pBiasOBEEGEye] = ttest(biasOBslopeEEGEye(:,2));
  2639. [~,pBiasAllEEGEye] = ttest(biasAllslopeEEGEye(:,2));
  2640. [~,pBiasSumEEGEye] = ttest(biasCPslopeEEGEye(:,2)+biasOBslopeEEGEye(:,2));
  2641. [~,pLRDiffEEGEye] = ttest(LRCPslopeEEGEye(:,2)-LROBslopeEEGEye(:,2));
  2642. %set up regression for testing hypothesis 5
  2643. subContext = [ones(eegEyeNumSubs,1);-1*ones(eegEyeNumSubs,1)];
  2644. allLRSlopes = [LRCPslopeEEGEye(:,2);LROBslopeEEGEye(:,2)];
  2645. allBiasSlopes = [biasAllslopeEEGEye(:,2);biasAllslopeEEGEye(:,2)];
  2646. X = [ones(length(subContext),1),allBiasSlopes,subContext,allBiasSlopes.*subContext];
  2647. useDummy = 0;
  2648. if useDummy == 1
  2649. dummyMat = [eye(eegEyeNumSubs);eye(eegEyeNumSubs)];
  2650. zX = [X(:,1),zscore(X(:,2:end)),dummyMat];
  2651. else
  2652. zX = [X(:,1),zscore(X(:,2:end))];
  2653. end
  2654. %regressing Bias, condition, bias*condition against learning
  2655. [slopeBsStats] = regstats(allLRSlopes,zX(:,2:end));
  2656. disp(slopeBsStats.tstat.t)
  2657. disp(slopeBsStats.tstat.pval)
  2658. posClustLabels = ["1st +","2nd +","3rd +","4th +","5th +","6th +","7th +","8th +"];
  2659. negClustLabels = ["1st -","2nd -","3rd -","4th -","5th -","6th -","7th -","8th -"];
  2660. clusterLabels = [posClustLabels(1:length(gPosEEG)),negClustLabels(1:length(gNegEEG)),"Pupil"];
  2661. end
  2662. %% BONUS FIGURES
  2663. % find correlation between eeg clusters and pupil dilation
  2664. if ~isempty(gSig)
  2665. clear eegCorrs eegEyeCorrs
  2666. for s = 1:length(EEGSubs)
  2667. eegCorrs(:,:,s) = corr(meanTrialEffectEEG(:,:,s),'rows','complete');
  2668. end
  2669. meanEEGCorrs = mean(eegCorrs,3);
  2670. for s = 1:eegEyeNumSubs
  2671. eegEyeCorrs(:,:,s) = corr(meanTrialEffectEEGEyeSep(:,:,s),'rows','complete');
  2672. end
  2673. meanEEGEyeCorrs = mean(eegEyeCorrs,3);
  2674. allMeanCorrs = [[meanEEGCorrs;meanEEGEyeCorrs(end,1:end-1)],meanEEGEyeCorrs(:,end)];
  2675. allCorrsSig = [[ttest(eegCorrs,0,'dim',3);ttest(eegEyeCorrs(end,1:end-1,:),0,'dim',3)],ttest(eegEyeCorrs(:,end,:),0,'dim',3)];
  2676. allCorrsSig01 = [[ttest(eegCorrs,0,'dim',3,'alpha',0.01);ttest(eegEyeCorrs(end,1:end-1,:),0,'dim',3,'alpha',0.01)],ttest(eegEyeCorrs(:,end,:),0,'dim',3,'alpha',0.01)];
  2677. allCorrsSig001 = [[ttest(eegCorrs,0,'dim',3,'alpha',0.001);ttest(eegEyeCorrs(end,1:end-1,:),0,'dim',3,'alpha',0.001)],ttest(eegEyeCorrs(:,end,:),0,'dim',3,'alpha',0.001)];
  2678. allCorrsSig0001 = [[ttest(eegCorrs,0,'dim',3,'alpha',0.0001);ttest(eegEyeCorrs(end,1:end-1,:),0,'dim',3,'alpha',0.0001)],ttest(eegEyeCorrs(:,end,:),0,'dim',3,'alpha',0.0001)];
  2679. %image plot for correlation between eeg clusters and pupil dilation
  2680. figure
  2681. imagesc(allMeanCorrs)
  2682. yticks(1:length(allMeanCorrs))
  2683. yticklabels([clusterLabels])
  2684. xticks(1:length(allMeanCorrs))
  2685. xticklabels([clusterLabels])
  2686. colorbar
  2687. colormap parula
  2688. caxis([-1,1]);
  2689. [R, C] = ndgrid(1:size(allMeanCorrs,1), 1:size(allMeanCorrs,1));
  2690. R = R(:); C = C(:) - 1/10;
  2691. clear mask
  2692. vals = round(allMeanCorrs,2);
  2693. mask = vals <= 0;
  2694. text(C(mask), R(mask), string(vals(mask)), 'color', 'w',"FontName","Arial","FontWeight","bold","FontSize",14)
  2695. text(C(~mask), R(~mask), string(vals(~mask)), 'color', 'k',"FontName","Arial","FontWeight","bold","FontSize",14)
  2696. set(gca, 'box', 'off')
  2697. set(gca,"FontName","Arial","FontWeight","bold","FontSize",14)
  2698. if doSTPResiduals == 0
  2699. fig = gcf;
  2700. figName = append("Figure_S4_",figTime,'.eps');
  2701. figLoc = append(figDir,figName);
  2702. exportgraphics(fig,figLoc,'BackgroundColor','none','ContentType','vector')
  2703. figName = append("Figure_S4_",figTime,'.png');
  2704. figLoc = append(figDir,figName);
  2705. saveas(fig,figLoc)
  2706. else
  2707. fig = gcf;
  2708. figName = append("Figure_S4_Residual_",figTime,'.eps');
  2709. figLoc = append(figDir,figName);
  2710. exportgraphics(fig,figLoc,'BackgroundColor','none','ContentType','vector')
  2711. figName = append("Figure_S4_Residual",figTime,'.png');
  2712. figLoc = append(figDir,figName);
  2713. saveas(fig,figLoc)
  2714. end
  2715. % figure
  2716. % imagesc(allMeanCorrs)
  2717. % yticks(1:length(allMeanCorrs))
  2718. % xticks(1:length(allMeanCorrs))
  2719. % yticklabels([clusterLabels])
  2720. % xticklabels([clusterLabels])
  2721. %
  2722. % colorbar
  2723. % colormap parula
  2724. % caxis([-1,1]);
  2725. % [i,j]=find(allCorrsSig==1);
  2726. % ms=10;
  2727. % hold on
  2728. % for k=1:length(i)
  2729. % plot(i(k),j(k), 'o', 'markerFaceColor', 'k', 'markerSize', ms, 'markerEdgeColor', 'none')
  2730. % end
  2731. % set(gca, 'box', 'off')
  2732. % set(gca,"FontName","Arial","FontWeight","bold","FontSize",14)
  2733. if eegTimestepMode == 1
  2734. figure
  2735. imagesc(meanVarSlopes)
  2736. ax = gca;
  2737. ax.FontSize = 10;
  2738. [i,j]=find(varP<.05);
  2739. ms=3;
  2740. hold on
  2741. for k=1:length(i)
  2742. plot(j(k),i(k), 'o', 'markerFaceColor', 'k', 'markerSize', ms, 'markerEdgeColor', 'none')
  2743. end
  2744. ylabel("Pupil Data")
  2745. yticks(1:size(varP,1))
  2746. xlabel("Parameter")
  2747. tickLabels = [];
  2748. for i = 1:length(borderTimes)-1
  2749. tickLabels = string([tickLabels;[num2str(borderTimes(i)-timeBeforeEEG),'ms to ',num2str(borderTimes(i+1)-timeBeforeEEG),'ms']]);
  2750. end
  2751. yticklabels(tickLabels')
  2752. xticklabels(["BiasCP","BiasOB","BiasSum","LRCP","LROB","LRDiff"])
  2753. colorbar
  2754. %
  2755. figure
  2756. imagesc(log10(varP))
  2757. ax = gca;
  2758. ax.FontSize = 10;
  2759. [R, C] = ndgrid(1:size(varP,1), 1:size(varP,2));
  2760. R = R(:);
  2761. C = C(:) - 1/4;
  2762. clear mask
  2763. vals = round(varP,4);
  2764. mask = vals <= 0;
  2765. text(C(mask), R(mask), string(vals(mask)), 'color', 'w')
  2766. text(C(~mask), R(~mask), string(vals(~mask)), 'color', 'k')
  2767. ylabel("Pupil Data")
  2768. yticks(1:1:size(varP,1))
  2769. xlabel("Parameter")
  2770. yticklabels(tickLabels')
  2771. xticklabels(["BiasCP","BiasOB","BiasSum","LRCP","LROB","LRDiff"])
  2772. colorbar
  2773. %find correlation between eeg clusters and pupil dilations
  2774. stackedEEGCorrs = corr(reshape(permute(meanTrialEffectEEG,[1,3,2]),[],size(meanTrialEffectEEG,2),1),'rows','complete');
  2775. stackedEEGEyeCorrs = corr(reshape(permute(meanTrialEffectEEGEyeSep,[1,3,2]),[],size(meanTrialEffectEEGEyeSep,2),1),'rows','complete');
  2776. allStackedCorrs = [[stackedEEGCorrs;stackedEEGEyeCorrs(end,1:end-1)],stackedEEGEyeCorrs(:,end)];
  2777. %image plot for correlation between eeg clusters and pupil dilation
  2778. figure
  2779. imagesc(allStackedCorrs)
  2780. yticks(1:length(allStackedCorrs))
  2781. yticklabels([clusterLabels])
  2782. xticks(1:length(allStackedCorrs))
  2783. xticklabels([clusterLabels])
  2784. colorbar
  2785. colormap parula
  2786. caxis([-1,1]);
  2787. [R, C] = ndgrid(1:size(allStackedCorrs,1), 1:size(allStackedCorrs,1));
  2788. R = R(:); C = C(:) - 1/10;
  2789. clear mask
  2790. vals = round(allStackedCorrs,2);
  2791. mask = vals <= 0;
  2792. text(C(mask), R(mask), string(vals(mask)), 'color', 'w',"FontName","Arial","FontWeight","bold","FontSize",14)
  2793. text(C(~mask), R(~mask), string(vals(~mask)), 'color', 'k',"FontName","Arial","FontWeight","bold","FontSize",14)
  2794. set(gca, 'box', 'off')
  2795. set(gca,"FontName","Arial","FontWeight","bold","FontSize",14)
  2796. end
  2797. %%
  2798. % make figure 6 if not doing stp residuals, otherwise make figure S2
  2799. if doSTPResiduals == 1
  2800. %figure s2
  2801. %scattered subject bias CP vs OB
  2802. figure("Position",[100,100,900,900])
  2803. subplot(2,8,1:4)
  2804. scatter(biasOBslopeEEGEye(:,2),biasCPslopeEEGEye(:,2),25,[.5,.5,.5],'filled','MarkerEdgeColor','k')
  2805. hold on
  2806. xlabel("OB Bias vs Arousal Slope")
  2807. ylabel("CP Bias vs Arousal Slope")
  2808. set(gca, 'box', 'off')
  2809. set(gca,"FontName","Arial","FontWeight","bold","FontSize",14)
  2810. yline(0)
  2811. xline(0)
  2812. yticks([-0.05,0,0.05])
  2813. xticks([-0.05,0,0.05])
  2814. maxBias = max([biasOBslopeEEGEye(:,2);biasCPslopeEEGEye(:,2)])*1.05;
  2815. ylim([-maxBias,maxBias])
  2816. xlim([-maxBias,maxBias])
  2817. plot([-1,1],[1,-1],'--','Color',[0.5,0.5,0.5])
  2818. %scattered subject learning cp vs ob
  2819. subplot(2,8,5:8)
  2820. scatter(LROBslopeEEGEye(:,2),LRCPslopeEEGEye(:,2),25,[.5,.5,.5],'filled','MarkerEdgeColor','k')
  2821. hold on
  2822. xlabel("OB LR vs Arousal Slope")
  2823. ylabel("CP LR vs Arousal Slope")
  2824. set(gca, 'box', 'off')
  2825. set(gca,"FontName","Arial","FontWeight","bold","FontSize",14)
  2826. yline(0)
  2827. xline(0)
  2828. yticks([-0.05,0,0.05])
  2829. xticks([-0.05,0,0.05])
  2830. maxLR = max([LROBslopeEEGEye(:,2);LRCPslopeEEGEye(:,2)])*1.05;
  2831. ylim([-maxLR,maxLR])
  2832. xlim([-maxLR,maxLR])
  2833. plot([-1,1],[-1,1],'--','Color',[0.5,0.5,0.5])
  2834. %hypothesis 5 main plot with residuals
  2835. subplot(2,8,[9:12])
  2836. scatter(biasAllslopeEEGEye(:,2),LRCPslopeEEGEye(:,2),25,[251 200 143]./255,'filled','MarkerEdgeColor',[246 146 30]./255)
  2837. hold on
  2838. scatter(biasAllslopeEEGEye(:,2),LROBslopeEEGEye(:,2),25,[128 214 247]./255,'filled','MarkerEdgeColor',[0 173 238]./255)
  2839. mCP = polyfit(biasAllslopeEEGEye(:,2),LRCPslopeEEGEye(:,2),1);
  2840. plot((linspace(min(biasAllslopeEEGEye(:,2)),max(biasAllslopeEEGEye(:,2)),2)),mCP(1)*(linspace(min(biasAllslopeEEGEye(:,2)),max(biasAllslopeEEGEye(:,2)),2))+mCP(2),'Color',[246 146 30]./255);
  2841. mOB = polyfit(biasAllslopeEEGEye(:,2),LROBslopeEEGEye(:,2),1);
  2842. mCPOB = polyfit(biasAllslopeEEGEye(:,2),LRCPslopeEEGEye(:,2)-LROBslopeEEGEye(:,2),1);
  2843. plot((linspace(min(biasAllslopeEEGEye(:,2)),max(biasAllslopeEEGEye(:,2)),2)),mOB(1)*(linspace(min(biasAllslopeEEGEye(:,2)),max(biasAllslopeEEGEye(:,2)),2))+mOB(2),'Color',[0 173 238]./255);
  2844. hold on
  2845. axLim = 1.05*max(abs([biasAllslopeEEGEye(:,2);LRCPslopeEEGEye(:,2);LROBslopeEEGEye(:,2)]));
  2846. ylim([-axLim,axLim])
  2847. xlim([-axLim,axLim])
  2848. xline(0)
  2849. yline(0)
  2850. yticks([-0.05,0,0.05])
  2851. xticks([-0.05,0,0.05])
  2852. xlabel("Bias vs Arousal Slope")
  2853. ylabel("Learning vs Arousal Slope")
  2854. legend('Changepoint','Oddball')
  2855. set(gca, 'box', 'off')
  2856. set(gca,"FontName","Arial","FontWeight","bold","FontSize",14)
  2857. %hypotheses 5 regression result plot
  2858. subplot(2,8,14:16)
  2859. [slopeBs,slopeBsInt] = regress(allLRSlopes,zX);
  2860. %testing hypothesis 5 by regressing learning slopes against bias slopes, condition, etc
  2861. bar(slopeBs(1:4))
  2862. hold on
  2863. errorbar(slopeBs(1:4),slopeBsInt(1:4,2)-slopeBs(1:4),'.','Color','k');
  2864. xticklabels(["Intercept","Bias Slope","Cond","Bias Slope*Cond"])
  2865. ylabel("Regression Coefficient")
  2866. yticks([-0.01,0,0.01])
  2867. set(gca, 'box', 'off')
  2868. set(gca,"FontName","Arial","FontWeight","bold","FontSize",12)
  2869. %save figure S2
  2870. if doSTPResiduals == 0
  2871. fig = gcf;
  2872. figName = append("Figure_S2_",figTime,'.eps');
  2873. figLoc = append(figDir,figName);
  2874. exportgraphics(fig,figLoc,'BackgroundColor','none','ContentType','vector')
  2875. figName = append("Figure_S2_",figTime,'.png');
  2876. figLoc = append(figDir,figName);
  2877. saveas(fig,figLoc)
  2878. else
  2879. fig = gcf;
  2880. figName = append("Figure_S2_Residual_",figTime,'.eps');
  2881. figLoc = append(figDir,figName);
  2882. exportgraphics(fig,figLoc,'BackgroundColor','none','ContentType','vector')
  2883. figName = append("Figure_S2_Residual",figTime,'.png');
  2884. figLoc = append(figDir,figName);
  2885. saveas(fig,figLoc)
  2886. end
  2887. else
  2888. % make figure 6 with a panel open for illustrator creation
  2889. figure('Position',[0 250 1800 600])
  2890. %main hypothesis 5 panel
  2891. subplot(1,5,3:4)
  2892. scatter(biasAllslopeEEGEye(:,2),LRCPslopeEEGEye(:,2),25,[251 200 143]./255,'filled','MarkerEdgeColor',[246 146 30]./255)
  2893. hold on
  2894. scatter(biasAllslopeEEGEye(:,2),LROBslopeEEGEye(:,2),25,[128 214 247]./255,'filled','MarkerEdgeColor',[0 173 238]./255)
  2895. mCP = polyfit(biasAllslopeEEGEye(:,2),LRCPslopeEEGEye(:,2),1);
  2896. plot((linspace(min(biasAllslopeEEGEye(:,2)),max(biasAllslopeEEGEye(:,2)),2)),mCP(1)*(linspace(min(biasAllslopeEEGEye(:,2)),max(biasAllslopeEEGEye(:,2)),2))+mCP(2),'Color',[246 146 30]./255);
  2897. mOB = polyfit(biasAllslopeEEGEye(:,2),LROBslopeEEGEye(:,2),1);
  2898. mCPOB = polyfit(biasAllslopeEEGEye(:,2),LRCPslopeEEGEye(:,2)-LROBslopeEEGEye(:,2),1);
  2899. plot((linspace(min(biasAllslopeEEGEye(:,2)),max(biasAllslopeEEGEye(:,2)),2)),mOB(1)*(linspace(min(biasAllslopeEEGEye(:,2)),max(biasAllslopeEEGEye(:,2)),2))+mOB(2),'Color',[0 173 238]./255);
  2900. hold on
  2901. axLim = 1.05*max(abs([biasAllslopeEEGEye(:,2);LRCPslopeEEGEye(:,2);LROBslopeEEGEye(:,2)]));
  2902. ylim([-axLim,axLim])
  2903. xlim([-axLim,axLim])
  2904. xline(0)
  2905. yline(0)
  2906. yticks([-0.1,0,0.1])
  2907. xticks([-0.1,0,0.1])
  2908. xlabel("Bias vs Arousal Slope")
  2909. ylabel("Learning vs Arousal Slope")
  2910. legend('Changepoint','Oddball')
  2911. set(gca, 'box', 'off')
  2912. set(gca,"FontName","Arial","FontWeight","bold","FontSize",14)
  2913. %set up regression for testing hypothesis 5
  2914. subContext = [ones(eegEyeNumSubs,1);-1*ones(eegEyeNumSubs,1)];
  2915. allLRSlopes = [LRCPslopeEEGEye(:,2);LROBslopeEEGEye(:,2)];
  2916. allBiasSlopes = [biasAllslopeEEGEye(:,2);biasAllslopeEEGEye(:,2)];
  2917. X = [ones(length(subContext),1),allBiasSlopes,subContext,allBiasSlopes.*subContext];
  2918. useDummy = 0;
  2919. if useDummy == 1
  2920. dummyMat = [eye(eegEyeNumSubs);eye(eegEyeNumSubs)];
  2921. zX = [X(:,1),zscore(X(:,2:end)),dummyMat];
  2922. else
  2923. zX = [X(:,1),zscore(X(:,2:end))];
  2924. end
  2925. %regressing Bias, condition, bias*condition against learning
  2926. [slopeBs,slopeBsInt] = regress(allLRSlopes,zX);
  2927. %hypothesis 5 regression plot
  2928. subplot(1,5,5)
  2929. bar(slopeBs(1:4))
  2930. hold on
  2931. errorbar(slopeBs(1:4),slopeBsInt(1:4,2)-slopeBs(1:4),'.','Color','k');
  2932. xticklabels(["Intercept","Bias Slope","Condition","Bias Slope*Condition"])
  2933. ylabel("Regression Coefficient")
  2934. yticks([-0.02,0,0.02])
  2935. set(gca, 'box', 'off')
  2936. set(gca,"FontName","Arial","FontWeight","bold","FontSize",14)
  2937. %save figure 6 (hypothesis 5)
  2938. if doSTPResiduals == 0
  2939. fig = gcf;
  2940. figName = append("Figure_6_",figTime,'.eps');
  2941. figLoc = append(figDir,figName);
  2942. exportgraphics(fig,figLoc,'BackgroundColor','none','ContentType','vector')
  2943. figName = append("Figure_6_",figTime,'.png');
  2944. figLoc = append(figDir,figName);
  2945. saveas(fig,figLoc)
  2946. else
  2947. fig = gcf;
  2948. figName = append("Figure_6_Residual_",figTime,'.eps');
  2949. figLoc = append(figDir,figName);
  2950. exportgraphics(fig,figLoc,'BackgroundColor','none','ContentType','vector')
  2951. figName = append("Figure_6_Residual",figTime,'.png');
  2952. figLoc = append(figDir,figName);
  2953. saveas(fig,figLoc)
  2954. end
  2955. end
  2956. end
  2957. %% MAKE bias and learning FIGURES FOR ILLUSTRATOR
  2958. %set panels for learning/bias figures
  2959. panel1 = [1:4,15:18,29:32];
  2960. panel2 = [6:9,20:23,34:37];
  2961. panel3 = [11:14,25:28,39:42];
  2962. panel4 = [57:59,71:73,85:87];
  2963. panel5 = [61:63,75:77,89:91];
  2964. panel6 = [65:67,79:81,93:95];
  2965. panel7 = [69,70,83,84,97,98];
  2966. % Bias Figure
  2967. figure("Position",[100,100,1600,850])
  2968. set(gcf,'renderer','Painters')
  2969. subplot(7,14,panel1)
  2970. %raw estimation error quantiled
  2971. scatter(quantileAllCPxesBias,meanQuantilesCPAllErrBias,30,'o',"MarkerEdgeColor",cpColor,"MarkerFaceColor",cpLColor)
  2972. hold on
  2973. scatter(quantileAllOBxesBias,meanQuantilesOBAllErrBias,30,'o',"MarkerEdgeColor",obColor,"MarkerFaceColor",obLColor)
  2974. plot([-3,3],[-3,3],'--','Color',[0.5,0.5,0.5])
  2975. hold off
  2976. ylabel("Perceptual Error")
  2977. xlabel("Objective Prediction Error")
  2978. ylim([-.5,.5])
  2979. yline(0)
  2980. xline(0)
  2981. xlim([-3,3])
  2982. xticks([-3,3])
  2983. legend("Changepoint","Oddball","Location","northwest")
  2984. set(gca, 'box', 'off')
  2985. set(gca,"FontName","Arial","FontWeight","bold","FontSize",18)
  2986. subplot(7,14,panel2)
  2987. %raw estimation error quantiled for good subjects
  2988. scatter(quantileGoodCPxesBias,meanQuantilesCPGoodErrBias,30,'o',"MarkerEdgeColor",cpColor,"MarkerFaceColor",cpLColor)
  2989. hold on
  2990. plot([-3,3],[-3,3],'--','Color',[0.5,0.5,0.5])
  2991. scatter(quantileGoodOBxesBias,meanQuantilesOBGoodErrBias,30,'o',"MarkerEdgeColor",obColor,"MarkerFaceColor",obLColor)
  2992. hold off
  2993. ylabel("Perceptual Error")
  2994. xlabel("Objective Prediction Error")
  2995. ylim([-.5,.5])
  2996. yline(0)
  2997. xline(0)
  2998. xlim([-3,3])
  2999. xticks([-3,3])
  3000. set(gca, 'box', 'off')
  3001. set(gca,"FontName","Arial","FontWeight","bold","FontSize",18)
  3002. subplot(7,14,panel3)
  3003. %bias behavioral regression
  3004. semBias=std(paramsCircBiasAll,1)./sqrt(size(paramsCircBiasAll,2));
  3005. x=[0.01:.01:0.01*length(behaveSubs)];
  3006. stdBias=std(paramsCircBiasAll);
  3007. normalizedCoef=[];
  3008. l = 0;
  3009. cAll =[];
  3010. for c=3:6
  3011. if c==9
  3012. normalizedCoef=paramsCircBiasAll(:,end)./stdBias(end);
  3013. normalizedCoefBias(:,c-1)=normalizedCoef;
  3014. meanToPlot=mean(normalizedCoef);
  3015. semToPlot=std(normalizedCoef)./sqrt(length(normalizedCoef));
  3016. scatter(x+c,normalizedCoef,30,'o','markerEdgeColor', 'k', 'markerFaceColor', cbColors(c,:) )
  3017. hold on
  3018. errorbar(mean(x+c),meanToPlot,1.96*semToPlot,'^','markerEdgeColor', 'k', 'markerFaceColor', cbColors(c,:), 'lineWidth', .75, 'markerSize', 8 )
  3019. scatter(mean(x+c),mean(paramsCircUpdateAllModel(:,c+1))./stdUpdate(c),100,'xk','LineWidth',3);
  3020. xtickVal(c)=mean(x+c);
  3021. l = l+1;
  3022. cAll(l) = c;
  3023. else
  3024. normalizedCoef=paramsCircBiasAll(:,c)./stdBias(c);
  3025. normalizedCoefBias(:,c-1)=normalizedCoef;
  3026. meanToPlot=mean(normalizedCoef);
  3027. semToPlot=std(normalizedCoef)./sqrt(length(normalizedCoef));
  3028. scatter(x+c,normalizedCoef,30,'o','markerEdgeColor', 'k', 'markerFaceColor', cbColors(c,:))
  3029. hold on
  3030. errorbar(mean(x+c),meanToPlot,1.96*semToPlot,'^k','markerEdgeColor', 'k', 'markerFaceColor', cbColors(c,:), 'lineWidth', 1, 'markerSize', 8)
  3031. scatter(mean(x+c),mean(paramsCircBiasAllModel(:,c))./stdBias(c),100,'xk','LineWidth',2);
  3032. xtickVal(c)=mean(x+c);
  3033. l = l+1;
  3034. cAll(l) = c;
  3035. end
  3036. %plot(x+c,normalizedCoef,'o','markerEdgeColor', 'k', 'markerFaceColor', cbColors(c,:), 'lineWidth', 1, 'markerSize', 10 )
  3037. end
  3038. %xlim([0.1 0.6])
  3039. %ylim([-0.1 0.1])
  3040. set(gca, 'box', 'off')
  3041. ylabel('Normalized Coefficient')
  3042. xticks(xtickVal(cAll))
  3043. xticklabels({'PE','PE*STP*CP/OB','PE*STP','PE*entropy','PE x CP/OB','PE x uniform','Gaze attention'})
  3044. xtickangle(45)
  3045. yline(0);
  3046. xlim([min(cAll)-0.5 c+1])
  3047. yticks([-10:5:10])
  3048. %ylim([-4 4])
  3049. hold off
  3050. set(gca, 'box', 'off')
  3051. set(gca,"FontName","Arial","FontWeight","bold","FontSize",18)
  3052. if ~isempty(gSig)
  3053. subplot(7,14,panel4)
  3054. %eeg bias quantiles
  3055. semCP = std(meanQuantCPBiasEEG(:,:))/sqrt(length(EEGSubs));
  3056. semOB = std(meanQuantOBBiasEEG(:,:))/sqrt(length(EEGSubs));
  3057. errorbar(mean(meanQuantCPBiasEEG(:,:)),semCP,'LineStyle','none','LineWidth',1,'Marker','o',"MarkerFaceColor",cpColor,"CapSize",0,"Color",cpColor,"MarkerEdgeColor",cpColor)
  3058. hold on
  3059. errorbar(mean(meanQuantOBBiasEEG(:,:)),semOB,'LineStyle','none','LineWidth',1,'Marker','o',"MarkerFaceColor",obColor,"CapSize",0,"Color",obColor,"MarkerEdgeColor",obColor)
  3060. xlim([0,numQuant+1])
  3061. if realData == 1
  3062. ylim([0.2,0.35]);
  3063. yticks([0.2,0.35])
  3064. end
  3065. xticks(1:numQuant)
  3066. xlabel("EEG Quantile")
  3067. ylabel("Mean Bias")
  3068. fitCPBias = polyfit(1:numQuant,mean(meanQuantCPBiasEEG), 1);
  3069. fitOBBias = polyfit(1:numQuant,mean(meanQuantOBBiasEEG), 1);
  3070. x = 1:numQuant;
  3071. yCPBias = polyval(fitCPBias , x);
  3072. yOBBias = polyval(fitOBBias , x);
  3073. plot(x,yCPBias,'Color',cpColor)
  3074. plot(x,yOBBias,'Color',obColor)
  3075. set(gca, 'box', 'off')
  3076. set(gca,"FontName","Arial","FontWeight","bold","FontSize",18)
  3077. subplot(7,14,panel5)
  3078. %pupil bias quantiles
  3079. semCP = std(meanQuantCPBiasEye(:,:))/sqrt(length(eyeSubs));
  3080. semOB = std(meanQuantOBBiasEye(:,:))/sqrt(length(eyeSubs));
  3081. errorbar(mean(meanQuantCPBiasEye(:,:)),semCP,'LineStyle','none','LineWidth',1,'Marker','o',"MarkerFaceColor",cpColor,"CapSize",0,"Color",cpColor,"MarkerEdgeColor",cpColor)
  3082. hold on
  3083. errorbar(mean(meanQuantOBBiasEye(:,:)),semOB,'LineStyle','none','LineWidth',1,'Marker','o',"MarkerFaceColor",obColor,"CapSize",0,"Color",obColor,"MarkerEdgeColor",obColor)
  3084. xlim([0,numQuant+1])
  3085. if realData == 1
  3086. ylim([0.2,0.35]);
  3087. yticks([0.2,0.35])
  3088. end
  3089. xticks(1:numQuant)
  3090. xlabel("Pupil Quantile")
  3091. ylabel("Mean Bias")
  3092. fitCPBias = polyfit(1:numQuant,mean(meanQuantCPBiasEye), 1);
  3093. fitOBBias = polyfit(1:numQuant,mean(meanQuantOBBiasEye), 1);
  3094. x = 1:numQuant;
  3095. yCPBias = polyval(fitCPBias , x);
  3096. yOBBias = polyval(fitOBBias , x);
  3097. plot(x,yCPBias,'Color',cpColor)
  3098. plot(x,yOBBias,'Color',obColor)
  3099. set(gca, 'box', 'off')
  3100. set(gca,"FontName","Arial","FontWeight","bold","FontSize",18)
  3101. subplot(7,14,panel6)
  3102. %eeg+pupil bias quantiles
  3103. semCP = std(meanQuantCPBiasEEGEye(:,:))/sqrt(eegEyeNumSubs);
  3104. semOB = std(meanQuantOBBiasEEGEye(:,:))/sqrt(eegEyeNumSubs);
  3105. errorbar(mean(meanQuantCPBiasEEGEye(:,:)),semCP,'LineStyle','none','LineWidth',1,'Marker','o',"MarkerFaceColor",cpColor,"CapSize",0,"Color",cpColor,"MarkerEdgeColor",cpColor)
  3106. hold on
  3107. errorbar(mean(meanQuantOBBiasEEGEye(:,:)),semOB,'LineStyle','none','LineWidth',1,'Marker','o',"MarkerFaceColor",obColor,"CapSize",0,"Color",obColor,"MarkerEdgeColor",obColor)
  3108. xlim([0,numQuant+1])
  3109. if realData == 1
  3110. ylim([0.2,0.35]);
  3111. yticks([0.2,0.35])
  3112. end
  3113. xticks(1:numQuant)
  3114. xlabel("EEG + Pupil Quantile")
  3115. ylabel("Mean Bias")
  3116. fitCPBias = polyfit(1:numQuant,mean(meanQuantCPBiasEEGEye), 1);
  3117. fitOBBias = polyfit(1:numQuant,mean(meanQuantOBBiasEEGEye), 1);
  3118. x = 1:numQuant;
  3119. yCPBias = polyval(fitCPBias , x);
  3120. yOBBias = polyval(fitOBBias , x);
  3121. plot(x,yCPBias,'Color',cpColor)
  3122. plot(x,yOBBias,'Color',obColor)
  3123. legend("","","Changepoint","Oddball")
  3124. set(gca, 'box', 'off')
  3125. set(gca,"FontName","Arial","FontWeight","bold","FontSize",18)
  3126. subplot(7,14,panel7)
  3127. %separate clusters bias slopes
  3128. bar([mean(varSlopes(:,3,:),3);mean(biasCPslopeEye(:,2)'+biasOBslopeEye(:,2)')])
  3129. hold on
  3130. EEGSlopes = squeeze(varSlopes(:,3,:))';
  3131. eyeSlopes = biasCPslopeEye(:,2)'+biasOBslopeEye(:,2)';
  3132. sem = [std(EEGSlopes)./sqrt(length(EEGSubs)),std(eyeSlopes)./sqrt(length(eyeSubs))];
  3133. errorbar(1:size(varSlopes,1)+1,[mean(EEGSlopes),mean(eyeSlopes')],sem,"Color",'k','LineStyle','none');
  3134. xticklabels(clusterLabels)
  3135. %FIX XTICK LABELS
  3136. ylabel("Average Bias Slope")
  3137. yticks([-0.05,0])
  3138. set(gca, 'box', 'off')
  3139. set(gca,"FontName","Arial","FontWeight","bold","FontSize",18)
  3140. end
  3141. %save bias figure (figure 3)
  3142. if doSTPResiduals == 0
  3143. fig = gcf;
  3144. figName = append("Figure_3_",figTime,'.eps');
  3145. figLoc = append(figDir,figName);
  3146. exportgraphics(fig,figLoc,'BackgroundColor','none','ContentType','vector')
  3147. figName = append("Figure_3_",figTime,'.png');
  3148. figLoc = append(figDir,figName);
  3149. saveas(fig,figLoc)
  3150. else
  3151. fig = gcf;
  3152. figName = append("Figure_3_Residual_",figTime,'.eps');
  3153. figLoc = append(figDir,figName);
  3154. exportgraphics(fig,figLoc,'BackgroundColor','none','ContentType','vector')
  3155. figName = append("Figure_3_Residual",figTime,'.png');
  3156. figLoc = append(figDir,figName);
  3157. saveas(fig,figLoc)
  3158. end
  3159. %%
  3160. % Learning Rate Figure
  3161. if ismember(subno,4001:4099)
  3162. lLims = [0.55,0.75];
  3163. else
  3164. lLims = [0.45,0.67];
  3165. end
  3166. figure("Position",[100,100,1600,850])
  3167. set(gcf,'renderer','Painters')
  3168. subplot(7,14,panel1)
  3169. %raw prediction update quantiled
  3170. scatter(quantileAllCPxesLR,meanQuantilesCPAllErrLR,30,'o',"MarkerEdgeColor",cpColor,"MarkerFaceColor",cpLColor)
  3171. hold on
  3172. scatter(quantileAllOBxesLR,meanQuantilesOBAllErrLR,30,'o',"MarkerEdgeColor",obColor,"MarkerFaceColor",obLColor)
  3173. plot([-3,3],[-3,3],'--','Color',[0.5,0.5,0.5])
  3174. hold off
  3175. ylabel("Prediction Update")
  3176. xlabel("Subjective Prediction Error")
  3177. ylim([-3,3])
  3178. yticks([-3,3])
  3179. yline(0)
  3180. xline(0)
  3181. xlim([-3,3])
  3182. xticks([-3,3])
  3183. legend("Changepoint","Oddball","Location","northwest")
  3184. set(gca, 'box', 'off')
  3185. set(gca,"FontName","Arial","FontWeight","bold","FontSize",18)
  3186. subplot(7,14,panel2)
  3187. %raw prediction update quantiled for good subjects
  3188. scatter(quantileGoodCPxesLR,meanQuantilesCPGoodUpLR,30,'o',"MarkerEdgeColor",cpColor,"MarkerFaceColor",cpLColor)
  3189. hold on
  3190. scatter(quantileGoodOBxesLR,meanQuantilesOBGoodUpLR,30,'o',"MarkerEdgeColor",obColor,"MarkerFaceColor",obLColor)
  3191. plot([-3,3],[-3,3],'--','Color',[0.5,0.5,0.5])
  3192. hold off
  3193. ylabel("Prediction Update")
  3194. xlabel("Subjective Prediction Error")
  3195. ylim([-3,3])
  3196. yticks([-3,3])
  3197. yline(0)
  3198. xline(0)
  3199. xlim([-3,3])
  3200. xticks([-3,3])
  3201. set(gca, 'box', 'off')
  3202. set(gca,"FontName","Arial","FontWeight","bold","FontSize",18)
  3203. subplot(7,14,panel3)
  3204. %learning behavioral regression
  3205. semUpdate=std(paramsCircUpdateAll,1)./sqrt(size(paramsCircUpdateAll,2));
  3206. x=[0.01:.01:0.01*length(behaveSubs)];
  3207. %plotting 5 coefficients
  3208. stdUpdate=std(paramsCircUpdateAll);
  3209. normalizedCoef=[];
  3210. l = 0;
  3211. cAll =[];
  3212. for c=3:6
  3213. normalizedCoef=paramsCircUpdateAll(:,c)./stdUpdate(c);
  3214. normalizedCoefUpdate(:,c-1)=normalizedCoef;
  3215. meanToPlot=mean(normalizedCoef);
  3216. semToPlot=std(normalizedCoef)./sqrt(length(normalizedCoef));
  3217. %keyboard
  3218. scatter(x+c,normalizedCoef,30,'o','markerEdgeColor', 'k', 'markerFaceColor', cbColors(c,:))
  3219. hold on
  3220. errorbar(mean(x+c),meanToPlot,1.96*semToPlot,'^k','markerEdgeColor', 'k', 'markerFaceColor', cbColors(c,:), 'lineWidth', 1, 'markerSize', 8 )
  3221. scatter(mean(x+c),mean(paramsCircUpdateAllModel(:,c))./stdUpdate(c),100,'xk','LineWidth',2);
  3222. xtickVal(c)=mean(x+c);
  3223. l = l+1;
  3224. cAll(l) = c;
  3225. end
  3226. %xlim([0.1 0.6])
  3227. %ylim([-1 1])
  3228. % title('Learning Regression Circ','color',cbColors(4,:))
  3229. ylabel('Normalized Coefficient')
  3230. xticks(xtickVal(cAll))
  3231. xticklabels({'PE','PE*STP*Cond','PE*STP','PE*entropy','PE x condition','PE x uniform'})
  3232. xtickangle(45)
  3233. yline(0);
  3234. %ylim([-4,8])
  3235. xlim([min(cAll)-0.5 c+1])
  3236. yticks(-2:2:6)
  3237. %ylim([-4.5 4.5])
  3238. hold off
  3239. set(gca, 'box', 'off')
  3240. set(gca,"FontName","Arial","FontWeight","bold","FontSize",18)
  3241. if ~isempty(gSig)
  3242. subplot(7,14,panel4)
  3243. %eeg learning quantiles
  3244. semCP = std(meanQuantCPLRsEEG(:,:))/sqrt(length(EEGSubs));
  3245. semOB = std(meanQuantOBLRsEEG(:,:))/sqrt(length(EEGSubs));
  3246. errorbar(mean(meanQuantCPLRsEEG(:,:)),semCP,'LineStyle','none','LineWidth',1,'Marker','o',"MarkerFaceColor",cpColor,"CapSize",0,"Color",cpColor,"MarkerEdgeColor",cpColor)
  3247. hold on
  3248. errorbar(mean(meanQuantOBLRsEEG(:,:)),semOB,'LineStyle','none','LineWidth',1,'Marker','o',"MarkerFaceColor",obColor,"CapSize",0,"Color",obColor,"MarkerEdgeColor",obColor)
  3249. xlim([0,numQuant+1])
  3250. if realData == 1
  3251. ylim(lLims);
  3252. yticks(lLims)
  3253. end
  3254. xticks(1:numQuant)
  3255. xlabel("EEG Quantile")
  3256. ylabel("Mean LR")
  3257. fitCPLR = polyfit(1:numQuant,mean(meanQuantCPLRsEEG), 1);
  3258. fitOBLR = polyfit(1:numQuant,mean(meanQuantOBLRsEEG), 1);
  3259. x = 1:numQuant;
  3260. yCPLR = polyval(fitCPLR , x);
  3261. yOBLR = polyval(fitOBLR , x);
  3262. plot(x,yCPLR,'Color',cpColor)
  3263. plot(x,yOBLR,'Color',obColor)
  3264. set(gca, 'box', 'off')
  3265. set(gca,"FontName","Arial","FontWeight","bold","FontSize",18)
  3266. subplot(7,14,panel5)
  3267. %pupil learning quantiles
  3268. semCP = std(meanQuantCPLRsEye(:,:))/sqrt(length(eyeSubs));
  3269. semOB = std(meanQuantOBLRsEye(:,:))/sqrt(length(eyeSubs));
  3270. errorbar(mean(meanQuantCPLRsEye(:,:)),semCP,'LineStyle','none','LineWidth',1,'Marker','o',"MarkerFaceColor",cpColor,"CapSize",0,"Color",cpColor,"MarkerEdgeColor",cpColor)
  3271. hold on
  3272. errorbar(mean(meanQuantOBLRsEye(:,:)),semOB,'LineStyle','none','LineWidth',1,'Marker','o',"MarkerFaceColor",obColor,"CapSize",0,"Color",obColor,"MarkerEdgeColor",obColor)
  3273. xlim([0,numQuant+1])
  3274. if realData == 1
  3275. ylim(lLims);
  3276. yticks(lLims)
  3277. end
  3278. xticks(1:numQuant)
  3279. xlabel("Pupil Quantile")
  3280. ylabel("Mean LR")
  3281. fitCPLR = polyfit(1:numQuant,mean(meanQuantCPLRsEye), 1);
  3282. fitOBLR = polyfit(1:numQuant,mean(meanQuantOBLRsEye), 1);
  3283. x = 1:numQuant;
  3284. yCPLR = polyval(fitCPLR , x);
  3285. yOBLR = polyval(fitOBLR , x);
  3286. plot(x,yCPLR,'Color',cpColor)
  3287. plot(x,yOBLR,'Color',obColor)
  3288. set(gca, 'box', 'off')
  3289. set(gca,"FontName","Arial","FontWeight","bold","FontSize",18)
  3290. subplot(7,14,panel6)
  3291. %eeg+pupil learning quantiles
  3292. semCP = std(meanQuantCPLRsEEGEye(:,:))/sqrt(eegEyeNumSubs);
  3293. semOB = std(meanQuantOBLRsEEGEye(:,:))/sqrt(eegEyeNumSubs);
  3294. errorbar(mean(meanQuantCPLRsEEGEye(:,:)),semCP,'LineStyle','none','LineWidth',1,'Marker','o',"MarkerFaceColor",cpColor,"CapSize",0,"Color",cpColor,"MarkerEdgeColor",cpColor)
  3295. hold on
  3296. errorbar(mean(meanQuantOBLRsEEGEye(:,:)),semOB,'LineStyle','none','LineWidth',1,'Marker','o',"MarkerFaceColor",obColor,"CapSize",0,"Color",obColor,"MarkerEdgeColor",obColor)
  3297. xlim([0,numQuant+1])
  3298. if realData == 1
  3299. ylim(lLims);
  3300. yticks(lLims)
  3301. end
  3302. xticks(1:numQuant)
  3303. xlabel("EEG + Pupil Quantile")
  3304. ylabel("Mean LR")
  3305. fitCPLR = polyfit(1:numQuant,mean(meanQuantCPLRsEEGEye), 1);
  3306. fitOBLR = polyfit(1:numQuant,mean(meanQuantOBLRsEEGEye), 1);
  3307. x = 1:numQuant;
  3308. yCPLR = polyval(fitCPLR , x);
  3309. yOBLR = polyval(fitOBLR , x);
  3310. plot(x,yCPLR,'Color',cpColor)
  3311. plot(x,yOBLR,'Color',obColor)
  3312. legend("","","Changepoint","Oddball","Location","northwest")
  3313. set(gca, 'box', 'off')
  3314. set(gca,"FontName","Arial","FontWeight","bold","FontSize",18)
  3315. subplot(7,14,panel7)
  3316. %separate clusters learning slopes
  3317. bar([mean(varSlopes(:,6,:),3);mean(LRCPslopeEye(:,2)'-LROBslopeEye(:,2)')])
  3318. hold on
  3319. EEGSlopes = squeeze(varSlopes(:,6,:))';
  3320. eyeSlopes = LRCPslopeEye(:,2)'-LROBslopeEye(:,2)';
  3321. sem = [std(EEGSlopes)./sqrt(length(EEGSubs)),std(eyeSlopes)./sqrt(length(eyeSubs))];
  3322. errorbar(1:size(varSlopes,1)+1,[mean(EEGSlopes),mean(eyeSlopes')],sem,"Color",'k','LineStyle','none');
  3323. xticklabels(clusterLabels)
  3324. %FIX XTICK LABELS
  3325. ylabel("Average LR Slope")
  3326. yticks([0,0.04])
  3327. set(gca, 'box', 'off')
  3328. set(gca,"FontName","Arial","FontWeight","bold","FontSize",18)
  3329. end
  3330. %save lr figure (figure 4)
  3331. if doSTPResiduals == 0
  3332. fig = gcf;
  3333. figName = append("Figure_4_",figTime,'.eps');
  3334. figLoc = append(figDir,figName);
  3335. exportgraphics(fig,figLoc,'BackgroundColor','none','ContentType','vector')
  3336. figName = append("Figure_4_",figTime,'.png');
  3337. figLoc = append(figDir,figName);
  3338. saveas(fig,figLoc)
  3339. else
  3340. fig = gcf;
  3341. figName = append("Figure_4_Residual_",figTime,'.eps');
  3342. figLoc = append(figDir,figName);
  3343. exportgraphics(fig,figLoc,'BackgroundColor','none','ContentType','vector')
  3344. figName = append("Figure_4_Residual",figTime,'.png');
  3345. figLoc = append(figDir,figName);
  3346. saveas(fig,figLoc)
  3347. end
  3348. %%
  3349. %categorize good vs bad subject indices
  3350. if realData == 1
  3351. badSubs = behaveSubs(paramsCircUpdateAll(:,4)<0.03);
  3352. badSubsIdx = ismember(behaveSubs,badSubs);
  3353. badEEGSubs = intersect(badSubs,EEGSubs,'stable');
  3354. badEEGSubsIdx = ismember(EEGSubs,badEEGSubs);
  3355. badEyeSubs = intersect(badSubs,eyeSubs,'stable');
  3356. badEyeSubsIdx = ismember(eyeSubs,badEyeSubs);
  3357. EEGEyeSubs = intersect(EEGSubs,eyeSubs,'stable');
  3358. badEEGEyeSubs = intersect(EEGEyeSubs,badSubs);
  3359. badEEGEyeSubsIdx = ismember(EEGEyeSubs,badEEGEyeSubs);
  3360. goodSubsIdx = ~badSubsIdx;
  3361. goodEEGSubsIdx = ~badEEGSubsIdx;
  3362. goodEyeSubsIdx = ~badEyeSubsIdx;
  3363. goodEEGEyeSubsIdx = ~badEEGEyeSubsIdx;
  3364. lLims = [0.42,0.70];
  3365. figure("Position",[100,100,1200,750])
  3366. subplot(2,3,1)
  3367. %eeg learning quantiles
  3368. semCP = std(meanQuantCPLRsEEG(goodEEGSubsIdx,:))/sqrt(sum(goodEEGSubsIdx));
  3369. semOB = std(meanQuantOBLRsEEG(goodEEGSubsIdx,:))/sqrt(sum(goodEEGSubsIdx));
  3370. errorbar(mean(meanQuantCPLRsEEG(goodEEGSubsIdx,:)),semCP,'LineStyle','none','LineWidth',1,'Marker','o',"MarkerFaceColor",cpColor,"CapSize",0,"Color",cpColor,"MarkerEdgeColor",cpColor)
  3371. hold on
  3372. errorbar(mean(meanQuantOBLRsEEG(goodEEGSubsIdx,:)),semOB,'LineStyle','none','LineWidth',1,'Marker','o',"MarkerFaceColor",obColor,"CapSize",0,"Color",obColor,"MarkerEdgeColor",obColor)
  3373. xlim([0,numQuant+1])
  3374. ylim(lLims);
  3375. yticks(lLims)
  3376. xticks(1:numQuant)
  3377. xlabel("EEG Quantile")
  3378. ylabel("Good Subs Mean LR")
  3379. fitCPLR = polyfit(1:numQuant,mean(meanQuantCPLRsEEG(goodEEGSubsIdx,:)), 1);
  3380. fitOBLR = polyfit(1:numQuant,mean(meanQuantOBLRsEEG(goodEEGSubsIdx,:)), 1);
  3381. x = 1:numQuant;
  3382. yCPLR = polyval(fitCPLR , x);
  3383. yOBLR = polyval(fitOBLR , x);
  3384. plot(x,yCPLR,'Color',cpColor)
  3385. plot(x,yOBLR,'Color',obColor)
  3386. set(gca, 'box', 'off')
  3387. set(gca,"FontName","Arial","FontWeight","bold","FontSize",15)
  3388. subplot(2,3,2)
  3389. %pupil learning quantiles
  3390. semCP = std(meanQuantCPLRsEye(goodEyeSubsIdx,:))/sqrt(sum(goodEyeSubsIdx));
  3391. semOB = std(meanQuantOBLRsEye(goodEyeSubsIdx,:))/sqrt(sum(goodEyeSubsIdx));
  3392. errorbar(mean(meanQuantCPLRsEye(goodEyeSubsIdx,:)),semCP,'LineStyle','none','LineWidth',1,'Marker','o',"MarkerFaceColor",cpColor,"CapSize",0,"Color",cpColor,"MarkerEdgeColor",cpColor)
  3393. hold on
  3394. errorbar(mean(meanQuantOBLRsEye(goodEyeSubsIdx,:)),semOB,'LineStyle','none','LineWidth',1,'Marker','o',"MarkerFaceColor",obColor,"CapSize",0,"Color",obColor,"MarkerEdgeColor",obColor)
  3395. xlim([0,numQuant+1])
  3396. ylim(lLims);
  3397. yticks(lLims)
  3398. xticks(1:numQuant)
  3399. xlabel("Pupil Quantile")
  3400. ylabel("Good Subs Mean LR")
  3401. fitCPLR = polyfit(1:numQuant,mean(meanQuantCPLRsEye(goodEyeSubsIdx,:)), 1);
  3402. fitOBLR = polyfit(1:numQuant,mean(meanQuantOBLRsEye(goodEyeSubsIdx,:)), 1);
  3403. x = 1:numQuant;
  3404. yCPLR = polyval(fitCPLR , x);
  3405. yOBLR = polyval(fitOBLR , x);
  3406. plot(x,yCPLR,'Color',cpColor)
  3407. plot(x,yOBLR,'Color',obColor)
  3408. set(gca, 'box', 'off')
  3409. set(gca,"FontName","Arial","FontWeight","bold","FontSize",15)
  3410. subplot(2,3,3)
  3411. %eeg+pupil learning quantiles
  3412. semCP = std(meanQuantCPLRsEEGEye(goodEEGEyeSubsIdx,:))/sqrt(sum(goodEEGEyeSubsIdx));
  3413. semOB = std(meanQuantOBLRsEEGEye(goodEEGEyeSubsIdx,:))/sqrt(sum(goodEEGEyeSubsIdx));
  3414. errorbar(mean(meanQuantCPLRsEEGEye(goodEEGEyeSubsIdx,:)),semCP,'LineStyle','none','LineWidth',1,'Marker','o',"MarkerFaceColor",cpColor,"CapSize",0,"Color",cpColor,"MarkerEdgeColor",cpColor)
  3415. hold on
  3416. errorbar(mean(meanQuantOBLRsEEGEye(goodEEGEyeSubsIdx,:)),semOB,'LineStyle','none','LineWidth',1,'Marker','o',"MarkerFaceColor",obColor,"CapSize",0,"Color",obColor,"MarkerEdgeColor",obColor)
  3417. xlim([0,numQuant+1])
  3418. ylim(lLims);
  3419. yticks(lLims)
  3420. xticks(1:numQuant)
  3421. xlabel("EEG + Pupil Quantile")
  3422. ylabel("Good Subs Mean LR")
  3423. fitCPLR = polyfit(1:numQuant,mean(meanQuantCPLRsEEGEye(goodEEGEyeSubsIdx,:)), 1);
  3424. fitOBLR = polyfit(1:numQuant,mean(meanQuantOBLRsEEGEye(goodEEGEyeSubsIdx,:)), 1);
  3425. x = 1:numQuant;
  3426. yCPLR = polyval(fitCPLR , x);
  3427. yOBLR = polyval(fitOBLR , x);
  3428. plot(x,yCPLR,'Color',cpColor)
  3429. plot(x,yOBLR,'Color',obColor)
  3430. legend("","","Changepoint","Oddball","Location","east")
  3431. set(gca, 'box', 'off')
  3432. set(gca,"FontName","Arial","FontWeight","bold","FontSize",15)
  3433. subplot(2,3,4)
  3434. %eeg learning quantiles
  3435. semCP = std(meanQuantCPLRsEEG(badEEGSubsIdx,:))/sqrt(sum(badEEGSubsIdx));
  3436. semOB = std(meanQuantOBLRsEEG(badEEGSubsIdx,:))/sqrt(sum(badEEGSubsIdx));
  3437. errorbar(mean(meanQuantCPLRsEEG(badEEGSubsIdx,:)),semCP,'LineStyle','none','LineWidth',1,'Marker','o',"MarkerFaceColor",cpColor,"CapSize",0,"Color",cpColor,"MarkerEdgeColor",cpColor)
  3438. hold on
  3439. errorbar(mean(meanQuantOBLRsEEG(badEEGSubsIdx,:)),semOB,'LineStyle','none','LineWidth',1,'Marker','o',"MarkerFaceColor",obColor,"CapSize",0,"Color",obColor,"MarkerEdgeColor",obColor)
  3440. xlim([0,numQuant+1])
  3441. ylim(lLims);
  3442. yticks(lLims)
  3443. xticks(1:numQuant)
  3444. xlabel("EEG Quantile")
  3445. ylabel("Bad Subs Mean LR")
  3446. fitCPLR = polyfit(1:numQuant,mean(meanQuantCPLRsEEG(badEEGSubsIdx,:)), 1);
  3447. fitOBLR = polyfit(1:numQuant,mean(meanQuantOBLRsEEG(badEEGSubsIdx,:)), 1);
  3448. x = 1:numQuant;
  3449. yCPLR = polyval(fitCPLR , x);
  3450. yOBLR = polyval(fitOBLR , x);
  3451. plot(x,yCPLR,'Color',cpColor)
  3452. plot(x,yOBLR,'Color',obColor)
  3453. set(gca, 'box', 'off')
  3454. set(gca,"FontName","Arial","FontWeight","bold","FontSize",15)
  3455. subplot(2,3,5)
  3456. %pupil learning quantiles
  3457. semCP = std(meanQuantCPLRsEye(badEyeSubsIdx,:))/sqrt(sum(badEyeSubsIdx));
  3458. semOB = std(meanQuantOBLRsEye(badEyeSubsIdx,:))/sqrt(sum(badEyeSubsIdx));
  3459. errorbar(mean(meanQuantCPLRsEye(badEyeSubsIdx,:)),semCP,'LineStyle','none','LineWidth',1,'Marker','o',"MarkerFaceColor",cpColor,"CapSize",0,"Color",cpColor,"MarkerEdgeColor",cpColor)
  3460. hold on
  3461. errorbar(mean(meanQuantOBLRsEye(badEyeSubsIdx,:)),semOB,'LineStyle','none','LineWidth',1,'Marker','o',"MarkerFaceColor",obColor,"CapSize",0,"Color",obColor,"MarkerEdgeColor",obColor)
  3462. xlim([0,numQuant+1])
  3463. ylim(lLims);
  3464. yticks(lLims)
  3465. xticks(1:numQuant)
  3466. xlabel("Pupil Quantile")
  3467. ylabel("Bad Subs Mean LR")
  3468. fitCPLR = polyfit(1:numQuant,mean(meanQuantCPLRsEye(badEyeSubsIdx,:)), 1);
  3469. fitOBLR = polyfit(1:numQuant,mean(meanQuantOBLRsEye(badEyeSubsIdx,:)), 1);
  3470. x = 1:numQuant;
  3471. yCPLR = polyval(fitCPLR , x);
  3472. yOBLR = polyval(fitOBLR , x);
  3473. plot(x,yCPLR,'Color',cpColor)
  3474. plot(x,yOBLR,'Color',obColor)
  3475. set(gca, 'box', 'off')
  3476. set(gca,"FontName","Arial","FontWeight","bold","FontSize",15)
  3477. subplot(2,3,6)
  3478. %eeg+pupil learning quantiles
  3479. semCP = std(meanQuantCPLRsEEGEye(badEEGEyeSubsIdx,:))/sqrt(sum(badEEGEyeSubsIdx));
  3480. semOB = std(meanQuantOBLRsEEGEye(badEEGEyeSubsIdx,:))/sqrt(sum(badEEGEyeSubsIdx));
  3481. errorbar(mean(meanQuantCPLRsEEGEye(badEEGEyeSubsIdx,:)),semCP,'LineStyle','none','LineWidth',1,'Marker','o',"MarkerFaceColor",cpColor,"CapSize",0,"Color",cpColor,"MarkerEdgeColor",cpColor)
  3482. hold on
  3483. errorbar(mean(meanQuantOBLRsEEGEye(badEEGEyeSubsIdx,:)),semOB,'LineStyle','none','LineWidth',1,'Marker','o',"MarkerFaceColor",obColor,"CapSize",0,"Color",obColor,"MarkerEdgeColor",obColor)
  3484. xlim([0,numQuant+1])
  3485. ylim(lLims);
  3486. yticks(lLims)
  3487. xticks(1:numQuant)
  3488. xlabel("EEG + Pupil Quantile")
  3489. ylabel("Bad Subs Mean LR")
  3490. fitCPLR = polyfit(1:numQuant,mean(meanQuantCPLRsEEGEye(badEEGEyeSubsIdx,:)), 1);
  3491. fitOBLR = polyfit(1:numQuant,mean(meanQuantOBLRsEEGEye(badEEGEyeSubsIdx,:)), 1);
  3492. x = 1:numQuant;
  3493. yCPLR = polyval(fitCPLR , x);
  3494. yOBLR = polyval(fitOBLR , x);
  3495. plot(x,yCPLR,'Color',cpColor)
  3496. plot(x,yOBLR,'Color',obColor)
  3497. legend("","","Changepoint","Oddball","Location","northwest")
  3498. set(gca, 'box', 'off')
  3499. set(gca,"FontName","Arial","FontWeight","bold","FontSize",15)
  3500. %GOOD SUBJECTS
  3501. % calculate p values of bias/lr cp/ob slopes for eeg ...
  3502. [~,goodpLRCPEEG] = ttest(LRCPslopeEEG(goodEEGSubsIdx,2));
  3503. [~,goodpLROBEEG] = ttest(LROBslopeEEG(goodEEGSubsIdx,2));
  3504. [~,goodpLRDiffEEG,~,goodDiffStatsEEG] = ttest(LRCPslopeEEG(goodEEGSubsIdx,2)-LROBslopeEEG(goodEEGSubsIdx,2));
  3505. % ... eye data ...
  3506. [~,goodpLRCPEye] = ttest(LRCPslopeEye(goodEyeSubsIdx,2));
  3507. [~,goodpLROBEye] = ttest(LROBslopeEye(goodEyeSubsIdx,2));
  3508. [~,goodpLRDiffEye,~,goodDiffStatsEye] = ttest(LRCPslopeEye(goodEyeSubsIdx,2)-LROBslopeEye(goodEyeSubsIdx,2));
  3509. % ... and both forms of data combined
  3510. [~,goodpLRCPEEGEye] = ttest(LRCPslopeEEGEye(goodEEGEyeSubsIdx,2));
  3511. [~,goodpLROBEEGEye] = ttest(LROBslopeEEGEye(goodEEGEyeSubsIdx,2));
  3512. [~,goodpLRDiffEEGEye,~,goodDiffStatsEEGEye] = ttest(LRCPslopeEEGEye(goodEEGEyeSubsIdx,2)-LROBslopeEEGEye(goodEEGEyeSubsIdx,2));
  3513. %BAD SUBJECTS
  3514. % calculate p values of bias/lr cp/ob slopes for eeg ...
  3515. [~,badpLRCPEEG] = ttest(LRCPslopeEEG(badEEGSubsIdx,2));
  3516. [~,badpLROBEEG] = ttest(LROBslopeEEG(badEEGSubsIdx,2));
  3517. [~,badpLRDiffEEG,~,badDiffStatsEEG] = ttest(LRCPslopeEEG(badEEGSubsIdx,2)-LROBslopeEEG(badEEGSubsIdx,2));
  3518. % ... eye data ...
  3519. [~,badpLRCPEye] = ttest(LRCPslopeEye(badEyeSubsIdx,2));
  3520. [~,badpLROBEye] = ttest(LROBslopeEye(badEyeSubsIdx,2));
  3521. [~,badpLRDiffEye,~,badDiffStatsEye] = ttest(LRCPslopeEye(badEyeSubsIdx,2)-LROBslopeEye(badEyeSubsIdx,2));
  3522. % ... and both forms of data combined
  3523. [~,badpLRCPEEGEye] = ttest(LRCPslopeEEGEye(badEEGEyeSubsIdx,2));
  3524. [~,badpLROBEEGEye] = ttest(LROBslopeEEGEye(badEEGEyeSubsIdx,2));
  3525. [~,badpLRDiffEEGEye,~,badDiffStatsEEGEye] = ttest(LRCPslopeEEGEye(badEEGEyeSubsIdx,2)-LROBslopeEEGEye(badEEGEyeSubsIdx,2));
  3526. % Save as supp figure
  3527. if doSTPResiduals == 0
  3528. fig = gcf;
  3529. figName = append("Figure_S6_",figTime,'.eps');
  3530. figLoc = append(figDir,figName);
  3531. exportgraphics(fig,figLoc,'BackgroundColor','none','ContentType','vector')
  3532. figName = append("Figure_S6_",figTime,'.png');
  3533. figLoc = append(figDir,figName);
  3534. saveas(fig,figLoc)
  3535. else
  3536. fig = gcf;
  3537. figName = append("Figure_S6_Residual_",figTime,'.eps');
  3538. figLoc = append(figDir,figName);
  3539. exportgraphics(fig,figLoc,'BackgroundColor','none','ContentType','vector')
  3540. figName = append("Figure_S6_Residual",figTime,'.png');
  3541. figLoc = append(figDir,figName);
  3542. saveas(fig,figLoc)
  3543. end
  3544. end
  3545. %
  3546. %%
  3547. % figure("Position",[100,100,1200,400])
  3548. % subplot(1,3,1)
  3549. % % eeg bias quantiles
  3550. % semCP = std(meanQuantCPBiasEEG(:,:))/sqrt(length(EEGSubs));
  3551. % semOB = std(meanQuantOBBiasEEG(:,:))/sqrt(length(EEGSubs));
  3552. % errorbar(mean(meanQuantCPBiasEEG(:,:)),semCP,'LineStyle','none','LineWidth',1,'Marker','o',"MarkerFaceColor",cpColor,"CapSize",0,"Color",cpColor,"MarkerEdgeColor",cpColor)
  3553. % hold on
  3554. % errorbar(mean(meanQuantOBBiasEEG(:,:)),semOB,'LineStyle','none','LineWidth',1,'Marker','o',"MarkerFaceColor",obColor,"CapSize",0,"Color",obColor,"MarkerEdgeColor",obColor)
  3555. % xlim([0,numQuant+1])
  3556. % ylim([0.3,0.45]);
  3557. % yticks([0.3,0.45])
  3558. % xticks(1:numQuant)
  3559. % xlabel("EEG Quantile")
  3560. % ylabel("Mean Bias")
  3561. % fitCPBias = polyfit(1:numQuant,mean(meanQuantCPBiasEEG), 1);
  3562. % fitOBBias = polyfit(1:numQuant,mean(meanQuantOBBiasEEG), 1);
  3563. % x = 1:numQuant;
  3564. % yCPBias = polyval(fitCPBias , x);
  3565. % yOBBias = polyval(fitOBBias , x);
  3566. % plot(x,yCPBias,'Color',cpColor)
  3567. % plot(x,yOBBias,'Color',obColor)
  3568. % set(gca, 'box', 'off')
  3569. % set(gca,"FontName","Arial","FontWeight","bold","FontSize",18)
  3570. %
  3571. % subplot(1,3,2)
  3572. % % pupil bias quantiles
  3573. % semCP = std(meanQuantCPBiasEye(:,:))/sqrt(length(eyeSubs));
  3574. % semOB = std(meanQuantOBBiasEye(:,:))/sqrt(length(eyeSubs));
  3575. % errorbar(mean(meanQuantCPBiasEye(:,:)),semCP,'LineStyle','none','LineWidth',1,'Marker','o',"MarkerFaceColor",cpColor,"CapSize",0,"Color",cpColor,"MarkerEdgeColor",cpColor)
  3576. % hold on
  3577. % errorbar(mean(meanQuantOBBiasEye(:,:)),semOB,'LineStyle','none','LineWidth',1,'Marker','o',"MarkerFaceColor",obColor,"CapSize",0,"Color",obColor,"MarkerEdgeColor",obColor)
  3578. % xlim([0,numQuant+1])
  3579. % ylim([0.3,0.45]);
  3580. % yticks([0.3,0.45])
  3581. % xticks(1:numQuant)
  3582. % xlabel("Pupil Quantile")
  3583. % ylabel("Mean Bias")
  3584. % fitCPBias = polyfit(1:numQuant,mean(meanQuantCPBiasEye), 1);
  3585. % fitOBBias = polyfit(1:numQuant,mean(meanQuantOBBiasEye), 1);
  3586. % x = 1:numQuant;
  3587. % yCPBias = polyval(fitCPBias , x);
  3588. % yOBBias = polyval(fitOBBias , x);
  3589. % plot(x,yCPBias,'Color',cpColor)
  3590. % plot(x,yOBBias,'Color',obColor)
  3591. % set(gca, 'box', 'off')
  3592. % set(gca,"FontName","Arial","FontWeight","bold","FontSize",18)
  3593. %
  3594. % subplot(1,3,3)
  3595. % % eeg+pupil bias quantiles
  3596. % semCP = std(meanQuantCPBiasEEGEye(:,:))/sqrt(eegEyeNumSubs);
  3597. % semOB = std(meanQuantOBBiasEEGEye(:,:))/sqrt(eegEyeNumSubs);
  3598. % errorbar(mean(meanQuantCPBiasEEGEye(:,:)),semCP,'LineStyle','none','LineWidth',1,'Marker','o',"MarkerFaceColor",cpColor,"CapSize",0,"Color",cpColor,"MarkerEdgeColor",cpColor)
  3599. % hold on
  3600. % errorbar(mean(meanQuantOBBiasEEGEye(:,:)),semOB,'LineStyle','none','LineWidth',1,'Marker','o',"MarkerFaceColor",obColor,"CapSize",0,"Color",obColor,"MarkerEdgeColor",obColor)
  3601. % xlim([0,numQuant+1])
  3602. % ylim([0.3,0.45]);
  3603. % yticks([0.3,0.45])
  3604. % xticks(1:numQuant)
  3605. % xlabel("EEG + Pupil Quantile")
  3606. % ylabel("Mean Bias")
  3607. % fitCPBias = polyfit(1:numQuant,mean(meanQuantCPBiasEEGEye), 1);
  3608. % fitOBBias = polyfit(1:numQuant,mean(meanQuantOBBiasEEGEye), 1);
  3609. % x = 1:numQuant;
  3610. % yCPBias = polyval(fitCPBias , x);
  3611. % yOBBias = polyval(fitOBBias , x);
  3612. % plot(x,yCPBias,'Color',cpColor)
  3613. % plot(x,yOBBias,'Color',obColor)
  3614. % legend("","","Changepoint","Oddball")
  3615. % set(gca, 'box', 'off')
  3616. % set(gca,"FontName","Arial","FontWeight","bold","FontSize",18)
  3617. %%
  3618. % mat1=b_mat_eeg(:,[13],:,:); %Pz
  3619. % mat2=reshape(mean(mean(mat1,2),1),4000,[]);
  3620. % mat3 = mat2';
  3621. % mat4 = reshape(mean(mat1,2),size(b_mat_eeg,[1,3,4]));
  3622. %
  3623. % figure
  3624. % subplot(2,1,1)
  3625. % sem = std(mat4(:,:,1))./sqrt(size(b_mat_eeg,1)-1);
  3626. % shadedErrorBar(-1999:2000,mat3(1,:),[mat3(1,:)-sem;mat3(1,:)+sem])
  3627. % yline(0,'--')
  3628. % xlim([-500,2000])
  3629. % xticks([])
  3630. % ylabel("Intercept")
  3631. % title("Pz (Original Model)")
  3632. % set(gca,"FontName","Arial","FontWeight","bold","FontSize",14)
  3633. % set(gca, 'box', 'off')
  3634. %
  3635. %
  3636. % subplot(2,1,2)
  3637. % sem = std(mat4(:,:,2))./sqrt(size(b_mat_eeg,1)-1);
  3638. % shadedErrorBar(-1999:2000,mat3(2,:),[mat3(2,:)-sem;mat3(2,:)+sem])
  3639. % yline(0,'--')
  3640. % xlim([-500,2000])
  3641. % xlabel("Time (ms)")
  3642. % ylabel("STP")
  3643. % set(gca,"FontName","Arial","FontWeight","bold","FontSize",14)
  3644. % set(gca, 'box', 'off')
  3645. %
  3646. %
  3647. % mat1=b_mat_eeg(:,[63],:,:); %FCz
  3648. % mat2=reshape(mean(mean(mat1,2),1),4000,[]);
  3649. % mat3 = mat2';
  3650. % mat4 = reshape(mean(mat1,2),size(b_mat_eeg,[1,3,4]));
  3651. %
  3652. % figure
  3653. % subplot(2,1,1)
  3654. % sem = std(mat4(:,:,1))./sqrt(size(b_mat_eeg,1)-1);
  3655. % shadedErrorBar(-1999:2000,mat3(1,:),[mat3(1,:)-sem;mat3(1,:)+sem])
  3656. % yline(0,'--')
  3657. % xlim([-500,2000])
  3658. % xticks([])
  3659. % ylabel("Intercept")
  3660. % title("FCz (Original Model)")
  3661. % set(gca,"FontName","Arial","FontWeight","bold","FontSize",14)
  3662. % set(gca, 'box', 'off')
  3663. %
  3664. % subplot(2,1,2)
  3665. % sem = std(mat4(:,:,2))./sqrt(size(b_mat_eeg,1)-1);
  3666. % shadedErrorBar(-1999:2000,mat3(2,:),[mat3(2,:)-sem;mat3(2,:)+sem])
  3667. % yline(0,'--')
  3668. % xlim([-500,2000])
  3669. % xlabel("Time (ms)")
  3670. % ylabel("STP")
  3671. % set(gca,"FontName","Arial","FontWeight","bold","FontSize",14)
  3672. % set(gca, 'box', 'off')
  3673. %
  3674. % figure
  3675. % subplot(2,1,1)
  3676. % sem = std(allBsPerm(:,:,1))./sqrt(size(allBsPerm,1)-1);
  3677. % coefs = squeeze(mean(allBsPerm))';
  3678. % shadedErrorBar(-timeBeforeEye:timeAfterEye,coefs(1,:),[coefs(1,:)-sem;coefs(1,:)+sem])
  3679. % yline(0,'--')
  3680. % xlim([-1000,4000])
  3681. % xticks([])
  3682. % ylabel("Intercept")
  3683. % title("Pupil (Original Model)")
  3684. % set(gca,"FontName","Arial","FontWeight","bold","FontSize",14)
  3685. % set(gca, 'box', 'off')
  3686. % subplot(2,1,2)
  3687. % sem = std(allBsPerm(:,:,2))./sqrt(size(allBsPerm,1)-1);
  3688. % shadedErrorBar(-timeBeforeEye:timeAfterEye,coefs(2,:),[coefs(2,:)-sem;coefs(2,:)+sem])
  3689. % yline(0,'--')
  3690. % xlim([-1000,4000])
  3691. % xlabel("Time (ms)")
  3692. % ylabel("STP")
  3693. % set(gca,"FontName","Arial","FontWeight","bold","FontSize",14)
  3694. % set(gca, 'box', 'off')

master_analysis_script_all.m at commit 005805b, no license · at the source

Overview

Authors: Tiantian Li1,2, Harrison Marble1,2, Timothy Chen1,2, Niloufar Razmi1,2, Matthew R Nassar1,2
  1. Department of Neuroscience, Brown University, Providence, RI USA
  2. Robert J. & Nancy D. Carney Institute for Brain Science, Brown University, Providence, RI USA
Institutions: Brown University (United States)
Journal: Nature human behaviour, volume 10, issue 9, pages 1790-1807
Dates: received 6 February 2025; accepted 1 July 2026; published online 5 August 2026; in print 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.1038/s41562-026-02533-1 · PMID 42557479 · PMCID PMC13590411 · OpenAlex W7172535780
Open access: hybrid, a free copy (OpenAlex)
Status: code verified
Categories: EEG (modality), human (organism), cognitive (subfield)
Methods: Statistics, Smoothing, state filtering, decompositions, Preprocessing, Physiology & signal measures
Keywords: Cognitive control, Human behaviour
MeSH: Arousal*, Event-Related Potentials, P300*, Learning*, Locus Coeruleus*, Pupil*, Adult, Electroencephalography, Female, Humans, Male, Young Adult (* major topic)
Topic: Neural and Behavioral Psychology Studies (Cognitive Neuroscience, Neuroscience), according to OpenAlex
Funding: U.S. Department of Health & Human Services | NIH | National Institute of Mental Health (NIMH) (R01MH126971); NIMH NIH HHS (R01 MH126971)
Citations: cited by 1 paper (Europe PMC); 92 references in the paper

Abstract

People are often faced with surprising events that defy expectations. Such events elicit transient activity in the locus coeruleus/norepinephrine system and elevation of peripheral arousal markers including pupil dilation and a late positive peak in stimulus evoked EEG response, the P300, but the function of these signals remains unclear. We propose that they reflect latent state transitions that dynamically control the mental context governing learning and perception. We tested and confirmed five preregistered predictions of this theory using EEG and pupil measurements collected from people performing a colour prediction and reproduction task. Task-induced latent state transitions elicited pupil dilation and amplified event-related potentials including the P3a component of the P300. These EEG and pupil measures related to behavioural signatures of latent state updating, including reduced bias and bidirectional adjustment of learning, both across trials and across individuals. Our findings support the theory that locus coeruleus/norepinephrine-linked arousal systems optimize behaviour by signalling environmental transitions to facilitate rapid adjustments of mental context.

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 10 matches between paragraphs and lines of code.

OSF ahynj

License: none: the authors keep all their rights
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Size: 2 files, 0 scripts
Software Heritage: not checked
Found in: the references
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Availability: 1 check, the latest on 27 September 2026: the link answers (HTTP 200)
  • 27 September 2026: the link answers (HTTP 200)
At the source:

learning-memory-and-decision-lab/Li-Marble-2025

License: none: the authors keep all their rights
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Commit: 005805b9ae98706bf899b2c18a338e39bb2943df, 5 May 2026
Languages: MATLAB (97)
Size: 314 files, 97 scripts
Software Heritage: not archived
Found in: “Code availability”
Holds: README
Not found: license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: CircStat (43 files), Statistics and Machine Learning Toolbox (29 files), Psychtoolbox (8 files), EEGLAB (2 files), Optimization Toolbox (2 files), shadedErrorBar (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers
  • 27 September 2026: the link answers
98 files

Code availability

All scripts for data collection and analysis are publicly accessible via GitHub at https://github.com/learning-memory-and-decision-lab/Li-Marble-2025.git. Task scripts were run using MATLAB v.R2019b (ref. 89), and preprocessing and analysis scripts were run using MATLAB v.R2024b (ref. 90) and EEGLAB v.2024.2.1 (ref. 91) with an additional EYE-EEG package92.

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

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;
  • 97 scripts, each with its path and the digest of its content;
  • 10 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 Statement

EEG and pupillometric data are available via Dryad at https://doi.org/10.5061/dryad.wm37pvn36 (ref. 88). Behavioural data are available via GitHub at https://github.com/learning-memory-and-decision-lab/Li-Marble-2025.git.

All scripts for data collection and analysis are publicly accessible via GitHub at https://github.com/learning-memory-and-decision-lab/Li-Marble-2025.git. Task scripts were run using MATLAB v.R2019b (ref. 89), and preprocessing and analysis scripts were run using MATLAB v.R2024b (ref. 90) and EEGLAB v.2024.2.1 (ref. 91) with an additional EYE-EEG package92.

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

  • Publisher: n/a → Nature Portfolio

Version 1, 27 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 5 authors, 2 keywords, 11 MeSH terms, 2 funders, 87 references.

Cite

This paper

Li, T., Marble, H., Chen, T., Razmi, N., & Nassar, M. R. (2026). Fluctuations in arousal reflect latent state transitions that facilitate behavioural optimization. Nature human behaviour, 10(9), 1790-1807. https://doi.org/10.1038/s41562-026-02533-1

BibTeX

@article{li2026fluctuations,
author = {Li, Tiantian and Marble, Harrison and Chen, Timothy and Razmi, Niloufar and Nassar, Matthew R},
title = {{Fluctuations in arousal reflect latent state transitions that facilitate behavioural optimization}},
journal = {Nature human behaviour},
year = {2026},
month = aug,
volume = {10},
number = {9},
pages = {1790--1807},
publisher = {Nature Portfolio},
issn = {2397-3374},
doi = {10.1038/s41562-026-02533-1},
url = {https://doi.org/10.1038/s41562-026-02533-1},
pmid = {42557479},
pmcid = {PMC13590411}
}

RIS

TY - JOUR
AU - Li, Tiantian
AU - Marble, Harrison
AU - Chen, Timothy
AU - Razmi, Niloufar
AU - Nassar, Matthew R
TI - Fluctuations in arousal reflect latent state transitions that facilitate behavioural optimization
T2 - Nature human behaviour
J2 - Nat Hum Behav
PY - 2026
DA - 2026/08/05
VL - 10
IS - 9
SP - 1790
EP - 1807
SN - 2397-3374
PB - Nature Portfolio
DO - 10.1038/s41562-026-02533-1
UR - https://doi.org/10.1038/s41562-026-02533-1
LA - en
ER -

CSL-JSON

{
"id": "10.1038/s41562-026-02533-1",
"type": "article-journal",
"title": "Fluctuations in arousal reflect latent state transitions that facilitate behavioural optimization",
"container-title": "Nature human behaviour",
"author": [
{
"family": "Li",
"given": "Tiantian"
},
{
"family": "Marble",
"given": "Harrison"
},
{
"family": "Chen",
"given": "Timothy"
},
{
"family": "Razmi",
"given": "Niloufar"
},
{
"family": "Nassar",
"given": "Matthew R"
}
],
"container-title-short": "Nat Hum Behav",
"volume": "10",
"issue": "9",
"page": "1790-1807",
"DOI": "10.1038/s41562-026-02533-1",
"PMID": "42557479",
"PMCID": "PMC13590411",
"ISSN": "2397-3374",
"publisher": "Nature Portfolio",
"URL": "https://doi.org/10.1038/s41562-026-02533-1",
"language": "en",
"issued": {
"date-parts": [
[
2026,
8,
5
]
]
}
}

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.1371/journal.pone.0355165 [code]
Pupillary dynamics during hands-off L2 driving and transitions of control under high cognitive load.
Journal: PloS one
In common: cognitive, 13 references
[2] doi:10.1126/sciadv.adz6495
Pupil-linked arousal heterogeneously modulates cell-type-specific sensory processing.
Journal: Science advances
In common: 13 references
[3] doi:10.7554/elife.110685 [code]
Sensory adaptation and pupil-linked arousal support flexible evidence accumulation during perceptual decision making.
Journal: eLife
In common: Optimization Toolbox, Statistics and Machine Learning Toolbox, cognitive, 9 references
[4] doi:10.1038/s41467-026-70659-x [code]
Noradrenaline causes a spread of association in the hippocampal cognitive map.
Journal: Nature communications
In common: cognitive, 10 references
[5] doi:10.1126/sciadv.adv5652 [code]
The anterior cingulate cortex modulates pupil-linked arousal.
Journal: Science advances
In common: 10 references
[6] doi:10.1073/pnas.2536535123 [code]
Orbitofrontal noradrenaline supports adaptive learning-rate adjustment in probabilistic reversal learning.
Journal: Proceedings of the National Academy of Sciences of the United States of America
In common: cognitive, 8 references
[7] doi:10.1523/jneurosci.0154-26.2026 [code]
Faster but less precise: expectation enhances response speed while reducing sensory fidelity.
Journal: The Journal of neuroscience : the official journal of the Society for Neuroscience
In common: shadedErrorBar, CircStat, Optimization Toolbox, 2 other tools, EEG, cognitive, 2 references
[8] doi:10.1523/eneuro.0417-25.2026 [code]
Learning and Motivation State Fluctuations from Motoric and Neurophysiologic Metrics during a Somatosensory Task in Mice.
Journal: eNeuro
In common: CircStat, Optimization Toolbox, Statistics and Machine Learning Toolbox, 5 references
[9] doi:10.1038/s41467-026-71725-0 [code]
Interactions across hemispheres in prefrontal cortex reflect global cognitive processing.
Journal: Nature communications
In common: Psychtoolbox, Optimization Toolbox, Statistics and Machine Learning Toolbox, cognitive, 5 references
[10] doi:10.1038/s41386-026-02399-x [code]
Regulation of the decision threshold by the locus coeruleus.
Journal: Neuropsychopharmacology : official publication of the American College of Neuropsychopharmacology
In common: cognitive, 6 references

Contribute

The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.

Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.

Request its removal

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

Discussion, reproductions, activity

Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.

Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.

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