% Figure_6_Generate.m
% Script used to generate Figure 6 Barendregt et al., 2022.
clear
% Load MCMC and subject data:
load('trials.mat'); subs = 20; speeds = 2;
load('model_fit_NB.mat');
load('model_fit_Const.mat');
load('model_fit_UGM.mat');
% Define parameters for simulating models:
Nt = 15; R_i = -1; tol = 1e-5;
% Perform model selection using AICc and RMSE (Fig. 6A,D):
for speed_ind = 1:speeds
model_class = zeros(3,2);
NB_err = NaN(subs,1); Const_err = NaN(subs,1); UGM_err = NaN(subs,1);
for sub_ind = 1:subs
% Compare model AICc:
model_AICc = [model_fit_NB(sub_ind,speed_ind).AICc model_fit_Const(sub_ind,speed_ind).AICc ...
model_fit_UGM(sub_ind,speed_ind).AICc];
[~,I] = min(model_AICc);
model_class(I,1) = model_class(I,1)+1;
% Load and format stimulus data:
Sub_ID = model_fit_NB(sub_ind,speed_ind).idSubject;
speed = model_fit_NB(sub_ind,speed_ind).speed; t_d = speed/1000;
Sub_T = trials.nDecisionToken((trials.nSpeedFast == speed) & (trials.idSubject == Sub_ID));
Sub_stim = trials.sTokenDirs((trials.nSpeedFast == speed) & (trials.idSubject == Sub_ID));
stim = NaN(length(Sub_stim),Nt);
for i = 1:length(Sub_stim)
stim(i,:) = str2num(strtrim(regexprep(Sub_stim{i},'.{1}','$0 ')));
stim(i,:) = 2*(stim(i,:)-1)-1;
end
% Compute average RMSE for NB model:
Fit_response = NaN(50,length(Sub_T));
MLE_NB = model_fit_NB(sub_ind,speed_ind).MLE;
thresh_g = tok_Bellmans_g(Nt,t_d,MLE_NB(1),R_i,@(t) MLE_NB(2),tol);
for i = 1:50
for j = 1:length(Sub_T)
T = tok_sim_norm(Nt,thresh_g,MLE_NB(3),stim(j,:));
Fit_response(i,j) = round(MLE_NB(4)*randn+T);
while (Fit_response(i,j) > Nt) || (Fit_response(i,j) < 0)
Fit_response(i,j) = round(MLE_NB(4)*randn+T);
end
end
end
Fit_response = mean(Fit_response,1);
NB_err(sub_ind) = sqrt(sum((Fit_response-Sub_T).^2)/length(Sub_T));
% Compute average RMSE for Const model:
Fit_response = NaN(50,length(Sub_T));
MLE_Const = model_fit_Const(sub_ind,speed_ind).MLE;
thresh_g = MLE_Const(1)*ones(1,Nt+1);
for i = 1:50
for j = 1:length(Sub_T)
T = tok_sim_norm(Nt,thresh_g,MLE_Const(2),stim(j,:));
Fit_response(i,j) = round(MLE_Const(3)*randn+T);
while (Fit_response(i,j) > Nt) || (Fit_response(i,j) < 0)
Fit_response(i,j) = round(MLE_Const(3)*randn+T);
end
end
end
Fit_response = mean(Fit_response,1);
Const_err(sub_ind) = sqrt(sum((Fit_response-Sub_T).^2)/length(Sub_T));
% Compute average RMSE for UGM:
Fit_response = NaN(50,length(Sub_T));
MLE_UGM = model_fit_UGM(sub_ind,speed_ind).MLE;
for i = 1:50
for j = 1:length(Sub_T)
T = tok_sim_UGM(Nt,MLE_UGM(1),MLE_UGM(2),MLE_UGM(3),MLE_UGM(4),stim(j,:));
Fit_response(i,j) = round(MLE_UGM(5)*randn+T);
while (Fit_response(i,j) > Nt) || (Fit_response(i,j) < 0)
Fit_response(i,j) = round(MLE_UGM(5)*randn+T);
end
end
end
Fit_response = mean(Fit_response,1);
UGM_err(sub_ind) = sqrt(sum((Fit_response-Sub_T).^2)/length(Sub_T));
% Compare model average RMSE:
model_err = [NB_err(sub_ind) Const_err(sub_ind) UGM_err(sub_ind)];
[~,I] = min(model_err);
model_class(I,2) = model_class(I,2)+1;
end
% Plot model selection results:
figure
bar(model_class')
end
% Compare subject mean RT to predicted RT from models (Fig. 6B,E):
for speed_ind = 1:speeds
Sub_RT = NaN(subs,1); NB_RT = NaN(subs,1); Const_RT = NaN(subs,1); UGM_RT = NaN(subs,1);
model_class = zeros(3,subs);
for sub_ind = 1:subs
% Calculate subject mean RT:
Sub_ID = model_fit_NB(sub_ind,speed_ind).idSubject;
speed = model_fit_NB(sub_ind,speed_ind).speed; t_d = speed/1000;
Sub_T = trials.nDecisionToken((trials.nSpeedFast == speed) & (trials.idSubject == Sub_ID));
Sub_RT(sub_ind) = mean(Sub_T);
% Calculate model mean RT:
NB_RT(sub_ind) = sum((0:Nt).*model_fit_NB(sub_ind,speed_ind).Fit);
Const_RT(sub_ind) = sum((0:Nt).*model_fit_Const(sub_ind,speed_ind).Fit);
UGM_RT(sub_ind) = sum((0:Nt).*model_fit_UGM(sub_ind,speed_ind).Fit);
% Sort predictions by whether or not model was also selected using
% AICc:
model_AICc = [model_fit_NB(sub_ind,speed_ind).AICc model_fit_Const(sub_ind,speed_ind).AICc ...
model_fit_UGM(sub_ind,speed_ind).AICc];
[~,I] = min(model_AICc);
model_class(I,sub_ind) = 1;
end
% Compute variance in models preditions from subject data:
NB_RT_var = var(NB_RT-Sub_RT);
Const_RT_var = var(Const_RT-Sub_RT);
UGM_RT_var = var(UGM_RT-Sub_RT);
% Plot mean RT results:
figure
plot(0:Nt,0:Nt,'k--','linewidth',5)
hold on
scatter(Sub_RT(model_class(1,:) == 0),NB_RT(model_class(1,:) == 0),...
1500,'filled','MarkerEdgeColor','k','MarkerFaceColor','#1b9e77','MarkerFaceAlpha',0.25,'MarkerEdgeAlpha',0.25)
scatter(Sub_RT(model_class(2,:) == 0),Const_RT(model_class(2,:) == 0), ...
1500,'filled','MarkerEdgeColor','k','MarkerFaceColor','#d95f02','MarkerFaceAlpha',0.25,'MarkerEdgeAlpha',0.25)
scatter(Sub_RT(model_class(3,:) == 0),UGM_RT(model_class(3,:) == 0), ...
1500,'filled','MarkerEdgeColor','k','MarkerFaceColor','#7570b3','MarkerFaceAlpha',0.25,'MarkerEdgeAlpha',0.25)
scatter(Sub_RT(model_class(1,:) == 1),NB_RT(model_class(1,:) == 1),...
1500,'filled','MarkerEdgeColor','k','MarkerFaceColor','#1b9e77')
scatter(Sub_RT(model_class(2,:) == 1),Const_RT(model_class(2,:) == 1),...
1500,'filled','MarkerEdgeColor','k','MarkerFaceColor','#d95f02')
scatter(Sub_RT(model_class(3,:) == 1),UGM_RT(model_class(3,:) == 1), ...
1500,'filled','MarkerEdgeColor','k','MarkerFaceColor','#7570b3')
xlabel('Subject Mean RT')
ylabel('Model Mean RT')
% Display prediction variances:
disp([NB_RT_var Const_RT_var UGM_RT_var])
end
% Classify motif of fitted normative model for each subject (Fig. 6C,F):
for speed_ind = 1:speeds
c_MLE = NaN(subs,1); R_c_MLE = NaN(subs,1);
type = NaN(1,subs);
model_class = zeros(3,subs);
for sub_ind = 1:subs
% Load MLE parameters from fitted NB model:
c_MLE(sub_ind) = model_fit_NB(sub_ind,speed_ind).MLE(2);
R_c_MLE(sub_ind) = model_fit_NB(sub_ind,speed_ind).MLE(1);
% Construct fitted NB threshold:
speed = model_fit_NB(sub_ind,speed_ind).speed; t_d = speed/1000;
thresh_TL = tok_Bellmans_TL(Nt,t_d,R_c_MLE(sub_ind),R_i,@(t) c_MLE(sub_ind),tol);
% Classify threshold motif:
if sum(thresh_TL==0)==length(thresh_TL)
type(sub_ind) = 1; % Motif i
elseif sum(diff(thresh_TL)<=0)==(length(thresh_TL)-1)
type(sub_ind) = 2; % Motif ii
elseif sum(diff(find(sign(diff(thresh_TL))==1))==1)==0
type(sub_ind) = 3; % Motif iii
else
type(sub_ind) = 4; % Motif iv
end
% Sort classification by whether or not NB model was selected using
% AICc:
model_AICc = [model_fit_NB(sub_ind,speed_ind).AICc model_fit_Const(sub_ind,speed_ind).AICc ...
model_fit_UGM(sub_ind,speed_ind).AICc];
[~,I] = min(model_AICc);
model_class(I,sub_ind) = 1;
end
% Plot MLEs in parameter space, color-coded by threshold motif:
figure
scatter(c_MLE((type == 1) & (model_class(1,:) == 1)),R_c_MLE((type == 1) & (model_class(1,:) == 1)),1500,'filled',...
'MarkerEdgeColor','k','MarkerFaceColor','#8dd3c7')
hold on
scatter(c_MLE((type == 1) & (model_class(1,:) == 0)),R_c_MLE((type == 1) & (model_class(1,:) == 1)),1500,'filled',...
'MarkerEdgeColor','k','MarkerFaceColor','#8dd3c7','MarkerFaceAlpha',0.25,'MarkerEdgeAlpha',0.25)
scatter(c_MLE((type == 2) & (model_class(1,:) == 1)),R_c_MLE((type == 2) & (model_class(1,:) == 1)),1500,'filled',...
'MarkerEdgeColor','k','MarkerFaceColor','#fdb462')
scatter(c_MLE((type == 2) & (model_class(1,:) == 0)),R_c_MLE((type == 2) & (model_class(1,:) == 0)),1500,'filled',...
'MarkerEdgeColor','k','MarkerFaceColor','#fdb462','MarkerFaceAlpha',0.25,'MarkerEdgeAlpha',0.25)
scatter(c_MLE((type == 3) & (model_class(1,:) == 1)),R_c_MLE((type == 3) & (model_class(1,:) == 1)),1500,'filled',...
'MarkerEdgeColor','k','MarkerFaceColor','#bebada')
scatter(c_MLE((type == 3) & (model_class(1,:) == 0)),R_c_MLE((type == 3) & (model_class(1,:) == 0)),1500,'filled',...
'MarkerEdgeColor','k','MarkerFaceColor','#bebada','MarkerFaceAlpha',0.25,'MarkerEdgeAlpha',0.25)
scatter(c_MLE((type == 4) & (model_class(1,:) == 1)),R_c_MLE((type == 4) & (model_class(1,:) == 1)),1500,'filled',...
'MarkerEdgeColor','k','MarkerFaceColor','#fb8072')
scatter(c_MLE((type == 4) & (model_class(1,:) == 0)),R_c_MLE((type == 4) & (model_class(1,:) == 0)),1500,'filled',...
'MarkerEdgeColor','k','MarkerFaceColor','#fb8072')
end