forked from cpp-lln-lab/localizer_visual_motion
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvisualMotionLocalizer.m
More file actions
executable file
·211 lines (145 loc) · 5.97 KB
/
visualMotionLocalizer.m
File metadata and controls
executable file
·211 lines (145 loc) · 5.97 KB
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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
% (C) Copyright 2018 Mohamed Rezk
% (C) Copyright 2020 CPP visual motion localizer developpers
%% Visual motion localizer
getOnlyPress = 1;
more off;
% Clear all the previous stuff
clc;
if ~ismac
close all;
clear Screen;
end
% make sure we got access to all the required functions and inputs
initEnv();
% set and load all the parameters to run the experiment
cfg = setParameters;
cfg = userInputs(cfg);
cfg = createFilename(cfg);
%% Experiment
% Safety loop: close the screen if code crashes
try
%% Init the experiment
[cfg] = initPTB(cfg);
cfg = postInitializationSetup(cfg);
[el] = eyeTracker('Calibration', cfg);
[cfg] = expDesign(cfg);
% Prepare for the output logfiles with all
logFile.extraColumns = cfg.extraColumns;
logFile = saveEventsFile('init', cfg, logFile);
logFile = saveEventsFile('open', cfg, logFile);
% prepare textures
cfg = apertureTexture('init', cfg);
cfg = dotTexture('init', cfg);
disp(cfg);
% Show experiment instruction
standByScreen(cfg);
% prepare the KbQueue to collect responses
getResponse('init', cfg.keyboard.responseBox, cfg);
% Wait for Trigger from Scanner
waitForTrigger(cfg);
%% Experiment Start
eyeTracker('StartRecording', cfg);
cfg = getExperimentStart(cfg);
getResponse('start', cfg.keyboard.responseBox);
waitFor(cfg, cfg.timing.onsetDelay);
%% For Each Block
for iBlock = 1:cfg.design.nbBlocks
fprintf('\n - Running Block %.0f \n', iBlock);
eyeTracker('Message', cfg, ['start_block-', num2str(iBlock)]);
dots = [];
previousEvent.target = 0;
% For each event in the block
for iEvent = 1:cfg.design.nbEventsPerBlock
% Check for experiment abortion from operator
checkAbort(cfg, cfg.keyboard.keyboard);
[thisEvent, thisFixation, cfg] = preTrialSetup(cfg, iBlock, iEvent);
% we wait for a trigger every 2 events
if cfg.pacedByTriggers.do && mod(iEvent, 2) == 1
waitForTrigger( ...
cfg, ...
cfg.keyboard.responseBox, ...
cfg.pacedByTriggers.quietMode, ...
cfg.pacedByTriggers.nbTriggers);
end
eyeTracker('Message', cfg, ...
['start_trial-', num2str(iEvent), '_', thisEvent.trial_type]);
% we only reuse the dots position for targets that consists of
% presenting static dots with the same position as those of the
% previous trial
%
% TODO does not take into account what to do if 3 or more targets in a row
if strcmp(cfg.target.type, 'static_repeat') && ...
strcmp(thisEvent.trial_type, 'static') && ...
thisEvent.target == 1 && ...
thisEvent.target == previousEvent.target
else
dots = [];
end
% play the dots and collect onset and duraton of the event
[onset, duration, dots] = doDotMo(cfg, thisEvent, thisFixation, dots, iEvent);
thisEvent = preSaveSetup( ...
thisEvent, ...
thisFixation, ...
iBlock, iEvent, ...
duration, onset, ...
cfg, ...
logFile);
saveEventsFile('save', cfg, thisEvent);
% collect the responses and appends to the event structure for
% saving in the tsv file
responseEvents = getResponse('check', cfg.keyboard.responseBox, cfg, ...
getOnlyPress);
triggerString = ['trigger_' cfg.design.blockNames{iBlock}];
saveResponsesAndTriggers(responseEvents, cfg, logFile, triggerString);
eyeTracker('Message', cfg, ...
['end_trial-', num2str(iEvent), '_', thisEvent.trial_type]);
previousEvent = thisEvent;
waitFor(cfg, cfg.timing.ISI);
end
% "prepare" cross for the baseline block
% if MT / MST this allows us to set the cross at the position of the next block
if iBlock < cfg.design.nbBlocks
nextBlock = iBlock + 1;
else
nextBlock = cfg.design.nbBlocks;
end
[~, thisFixation] = preTrialSetup(cfg, nextBlock, 1);
drawFixation(thisFixation);
Screen('Flip', cfg.screen.win);
eyeTracker('Message', cfg, ['end_block-', num2str(iBlock)]);
waitFor(cfg, cfg.timing.IBI);
% IBI trigger paced
if cfg.pacedByTriggers.do
waitForTrigger( ...
cfg, ...
cfg.keyboard.responseBox, ...
cfg.pacedByTriggers.quietMode, ...
cfg.timing.triggerIBI);
end
if isfield(cfg.design, 'localizer') && ...
strcmpi(cfg.design.localizer, 'MT_MST') && ...
iBlock == cfg.design.nbBlocks / 2
waitFor(cfg, cfg.timing.changeFixationPosition);
end
% trigger monitoring
triggerEvents = getResponse('check', cfg.keyboard.responseBox, cfg, ...
getOnlyPress);
triggerString = 'trigger_baseline';
saveResponsesAndTriggers(triggerEvents, cfg, logFile, triggerString);
end
% End of the run for the BOLD to go down
waitFor(cfg, cfg.timing.endDelay);
cfg = getExperimentEnd(cfg);
eyeTracker('StopRecordings', cfg);
% Close the logfiles
saveEventsFile('close', cfg, logFile);
getResponse('stop', cfg.keyboard.responseBox);
getResponse('release', cfg.keyboard.responseBox);
eyeTracker('Shutdown', cfg);
createJson(cfg, cfg);
farewellScreen(cfg);
cleanUp();
catch
cleanUp();
psychrethrow(psychlasterror);
end