Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
%_______________________________________________________________________
%
% Configuration for running dotsExperiment
%_______________________________________________________________________
%
% Output
%
% dotInfo | configuration for random dots experiment (struct)
%_______________________________________________________________________
%
% 170704 - incorporated thresholds
function dotInfo = createDotInfo_JQK_170704(varargin)
dotInfo.trialsPerAtt = 32; % should be around 22 minutes with current timing (30 with confidence)
dotInfo.numOfAtt = 4; % number of attributes to be included
dotInfo.totalTrials = dotInfo.trialsPerAtt*dotInfo.numOfAtt*2; % *2 as we want to have the specified amount per cued/uncued
dotInfo.dirAttentionRate = .5; % ratio of directed attention vs. wholistic attention trials (same for each attribute)
dotInfo.durCue = 2; % duration of cue
dotInfo.durPres = .5; % duration of presentation
dotInfo.durResp = 2.5; % duration of question
dotInfo.durConf = 2.5; % duration of confidence
dotInfo.confOptions = '2'; % 2 or 4 confidence options
dotInfo.highlightChoice = 1; % highlight choice by retaining only chosen option?
dotInfo.feedback = 0; % no feedback
dotInfo.dirSet = [180, 0]; % dots in left or right direction
dotInfo.numDotField = 1; % show a single dot patches on screen
dotInfo.apXYD = [0 0 130]; % coordinates and diameter of aperture
dotInfo.speed = [50]; % speed of dot motion
dotInfo.trialtype = [2 1 1]; % reaction time, not relevant, keyboard
dotInfo.dotSize = 3; % dot size in pixels
dotInfo.maxDotTime = 2; % maximum duration of moving dots
dotInfo.fixXY = [0 0]; % fixation coordinates
dotInfo.fixDiam = 2; % fixation diameter
dotInfo.fixColor = [0 150 200]; % blue fixation dot
dotInfo.fixMinTime = 0.75; % minimum fixation
dotInfo.fixMaxTime = 1.25; % maximum fixation
dotInfo.maxDotsPerFrame = 300; % depends on graphics card
dotInfo.fixTime = 2; % JQK: fixed onset fixation time
dotInfo.PauseAfterTrials = 50:50:dotInfo.totalTrials; % pause every 50 trials
dotInfo.breakTime = 30; % pause for 30 seconds
% update frequency of on-screen content
dotInfo.Hz_RDM = 60; % kinematogram
% multi-attribute task
if ~isempty(varargin)
thresholds = varargin{1,1};
dotInfo.MAT.percAtt1H = thresholds.color;
dotInfo.MAT.percAtt2H = thresholds.direction;
dotInfo.MAT.percAtt3H = thresholds.size;
dotInfo.MAT.percAtt4H = thresholds.luminance;
else
dotInfo.MAT.percAtt1H = .65;
dotInfo.MAT.percAtt2H = .65;
dotInfo.MAT.percAtt3H = .65;
dotInfo.MAT.percAtt4H = .65;
end
dotInfo.MAT.percAtt1L = 1-dotInfo.MAT.percAtt1H;
dotInfo.MAT.percAtt2L = 1-dotInfo.MAT.percAtt2H;
dotInfo.MAT.percAtt3L = 1-dotInfo.MAT.percAtt3H;
dotInfo.MAT.percAtt4L = 1-dotInfo.MAT.percAtt4H;
dotInfo.MAT.color = [255 255 255; 255 0 0]; % define dot color
dotInfo.MAT.coherence = 1; % define dot movement (coherence)
dotInfo.MAT.direction = [180 0]; % left and right
dotInfo.MAT.size = [5 8]; % define dot size
dotInfo.MAT.luminance = [.4 .8]; % define dot luminance
dotInfo.MAT.attNames = {'color'; 'direction'; 'size'; 'luminance'};
dotInfo.MAT.attNamesDE = {'Farbe'; 'Richtung'; 'Gre'; 'Helligkeit'};
%% specify keys
% Use OS X keyboard naming scheme across all plattforms
% Otherwise LeftControl/RightControl are not recognized
KbName('UnifyKeyNames');
if ismac % Mac keyboard
dotInfo.keyLeft = [KbName('LeftControl'), KbName('LeftAlt'), KbName('LeftArrow')]; % left response
dotInfo.keyRight = [KbName('RightControl'), KbName('RightAlt'), KbName('RightArrow')]; % right response
dotInfo.keyConf1 = [KbName('LeftControl'), KbName('LeftArrow')]; % lowest confidence
dotInfo.keyConf2 = KbName('LeftAlt'); % intermediate confidence low
dotInfo.keyConf3 = KbName('RightAlt'); % intermediate confidence high
dotInfo.keyConf4 = [KbName('RightControl'), KbName('RightArrow')]; % highest confidence
else % PC keyboard
% dotInfo.keyLeft = KbName('LeftControl');
% dotInfo.keyRight = KbName('RightControl');
dotInfo.keyLeft = [KbName('LeftControl'), KbName('LeftAlt'), KbName('LeftArrow')];
dotInfo.keyRight = [KbName('RightControl'), KbName('RightAlt'), KbName('RightArrow')];
dotInfo.keyConf1 = [KbName('LeftControl'), KbName('LeftArrow')];
dotInfo.keyConf2 = KbName('LeftAlt');
dotInfo.keyConf3 = KbName('RightAlt');
dotInfo.keyConf4 = [KbName('RightControl'), KbName('RightArrow')];
end
dotInfo.keyModifier = KbName('LeftAlt'); % to prevent accidental input
dotInfo.keyEscape = KbName('Escape'); %
dotInfo.keyReturn = KbName('Return'); % continue experiment
dotInfo.keyPause = KbName('p');
%% randomize stimuli and non-target duration
% set random seed
rseed = sum(100*clock);
rng(rseed,'twister');
[dotInfo.rngSetting] = rng;
% pseudo-randomize target attribute (max. of 2 repetitions)
distrib = repmat([1:dotInfo.numOfAtt],1,dotInfo.trialsPerAtt*2); % double amount of requested trials, so that trialsPerAtt is available within both cued and uncued condition
tmp_rand = randperm(numel(distrib));
tmp.random = distrib(tmp_rand);
rep = diff(find(diff([-Inf tmp.random Inf])));
while max(rep) > 3 % randomly switch numbers until criterion is reached
tmp.switchInds = randi(length(tmp.random),1, 2);
tmp.switch1 = tmp.random(tmp.switchInds(1));
tmp.switch2 = tmp.random(tmp.switchInds(2));
tmp.random(tmp.switchInds(1)) = tmp.switch2;
tmp.random(tmp.switchInds(2)) = tmp.switch1;
rep = diff(find(diff([-Inf tmp.random Inf])));
end
dotInfo.targetAtt = tmp.random;
%% randomize directed attention trials & higher probability choice (within attribute)
dotInfo.DirAttn = NaN(size(dotInfo.targetAtt));
dotInfo.HighProbAtt = NaN(size(dotInfo.targetAtt));
numSelAttn = ceil(dotInfo.dirAttentionRate*dotInfo.trialsPerAtt*2);
for indAtt = 1:dotInfo.numOfAtt % retain relationships for each attribute
tmp_trials = find(dotInfo.targetAtt == indAtt);
tmp_rand = randperm(numel(tmp_trials));
tmp_choice1 = tmp_trials(tmp_rand(1:numSelAttn));
tmp_choice2 = tmp_trials(tmp_rand(numSelAttn+1:end));
dotInfo.DirAttn(tmp_choice1) = 1;
dotInfo.DirAttn(tmp_choice2) = 2;
dotInfo.HighProbAtt(tmp_choice1(1:numel(tmp_choice1)/2)) = 1; % First half is designated highProb = 1;
dotInfo.HighProbAtt(tmp_choice1((numel(tmp_choice1)/2)+1:end)) = 2; % Second half is deignated highProb = 2;
dotInfo.HighProbAtt(tmp_choice2(1:numel(tmp_choice2)/2)) = 1;
dotInfo.HighProbAtt(tmp_choice2((numel(tmp_choice2)/2)+1:end)) = 2;
end
% Note that within attribute high probability choice and directed attention are orthogonal.
% They both depend on the same randomization step.
% The high probability choices only refer to the target attribute. The
% high probability options for the other attributes are randomly drawn
% below.
% Note that there is no check that the conjunction of different
% attributes appears equally often.
%% get random choices for remaining attributes on each trial
dotInfo.HighProbChoice = NaN(4,size(dotInfo.targetAtt,2));
for indTrial = 1:dotInfo.totalTrials
for indAtt = 1:dotInfo.numOfAtt
if dotInfo.targetAtt(indTrial) == indAtt % for target attribute, select the previously identified option
dotInfo.HighProbChoice(indAtt,indTrial) = dotInfo.HighProbAtt(1,indTrial);
else
tmp_rand = randperm(2);
dotInfo.HighProbChoice(indAtt,indTrial) = tmp_rand(1);
end
end
end
end