Skip to content

Commit 1142def

Browse files
committed
get expDesign from Marco's Branch
1 parent 2ad744e commit 1142def

File tree

1 file changed

+227
-92
lines changed

1 file changed

+227
-92
lines changed

subfun/expDesign.m

Lines changed: 227 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
11
function [cfg] = expDesign(cfg, displayFigs)
22
% Creates the sequence of blocks and the events in them
33
%
4-
% The conditions are consecutive static and motion blocks
5-
% Gives better results than randomised.
6-
%
7-
% It can be run as a stand alone without inputs to display a visual example of possible design.
4+
% The conditions are consecutive static and motion blocks (Gives better results than randomised).
85
%
96
% EVENTS
107
% The numEventsPerBlock should be a multiple of the number of "base"
118
% listed in the motionDirections and staticDirections (4 at the moment).
9+
% Pseudorandomization rules:
10+
% (1) Directions are all present in random orders in `numEventsPerBlock/nDirections`
11+
% consecutive chunks. This evenly distribute the directions across the
12+
% block.
13+
% (2) No same consecutive direction (TO IMPLEMENT)
1214
%
13-
%
14-
% TARGETS:
15-
% If there are 2 targets per block we make sure that they are at least 2
16-
% events apart.
17-
% Targets cannot be on the first or last event of a block
15+
% TARGETS
16+
% Pseudorandomization rules:
17+
% (1) If there are 2 targets per block we make sure that they are at least 2
18+
% events apart.
19+
% (2) Targets cannot be on the first or last event of a block.
20+
% (3) Targets can not be present more than 2 times in the same event
21+
% position across blocks.
1822
%
1923
% Input:
2024
% - ExpParameters: parameters returned by SetParameters
@@ -30,19 +34,19 @@
3034
% - 0 90 180 270 indicate the angle
3135
% - -1 indicates static
3236
%
33-
% - ExpParameters.designSpeeds = array (nr_blocks, numEventsPerBlock) * speedEvent
37+
% - ExpParameters.designSpeeds = array (nr_blocks, numEventsPerBlock) * speedEvent;
3438
%
3539
% - ExpParameters.designFixationTargets = array (nr_blocks, numEventsPerBlock)
3640
% showing for each event if it should be accompanied by a target
3741
%
3842

3943
% Set directions for static and motion condition
4044
motionDirections = [0 90 180 270];
41-
% staticDirections = [0 90 180 270];
42-
staticDirections = [-1 -1 -1 -1];
43-
45+
staticDirections = [-1 -1 -1 -1];
46+
47+
4448
%% Check inputs
45-
49+
4650
% Set variables here for a dummy test of this function
4751
if nargin < 1 || isempty(cfg)
4852
cfg.names = {'static', 'motion'};
@@ -67,101 +71,232 @@
6771
if mod(numEventsPerBlock, length(motionDirections)) ~= 0
6872
warning('Number of events/block not a multiple of number of motion/static direction');
6973
end
70-
74+
75+
7176
%% Adapt some variables according to input
72-
73-
% Set directions for static and motion condition
74-
motionDirections = repmat(motionDirections, 1, numEventsPerBlock / length(motionDirections));
75-
staticDirections = repmat(staticDirections, 1, numEventsPerBlock / length(staticDirections));
76-
77+
7778
% Assign the conditions
7879
condition = repmat(names, 1, numRepetitions);
7980
nrBlocks = length(condition);
81+
82+
% Assigne design parameters to be exported
83+
cfg.designBlockNames = cell(nrBlocks, 1);
84+
cfg.designDirections = zeros(nrBlocks, numEventsPerBlock);
85+
cfg.designSpeeds = ones(nrBlocks, numEventsPerBlock) * speedEvent;
86+
cfg.designFixationTargets = zeros(nrBlocks, numEventsPerBlock);
87+
88+
% Create a vector for the static condition
89+
staticDirections = repmat(staticDirections, 1, numEventsPerBlock/length(staticDirections));
90+
8091
% Get the index of each condition
81-
staticIndex = find(strcmp(condition, 'static'));
82-
motionIndex = find(strcmp(condition, 'motion'));
83-
92+
staticIndex = find( strcmp(condition, 'static') );
93+
motionIndex = find( strcmp(condition, 'motion') );
94+
95+
for iMotionBlock = 1:numRepetitions
96+
97+
% Shuffle and set motion direction order
98+
cfg.designDirections(motionIndex(iMotionBlock),:) = ...
99+
[ Shuffle(motionDirections), Shuffle(motionDirections), Shuffle(motionDirections)];
100+
101+
% Set static condition
102+
cfg.designDirections(staticIndex(iMotionBlock),:) = staticDirections;
103+
104+
end
105+
84106
% Assign the targets for each condition
85107
rangeTargets = [1 maxNumFixTargPerBlock];
108+
109+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
110+
111+
% % % IT COULD BE A PROBLEM IF WE SET THE N OF TARGETS RANDOMLY (TOO CHOOSE
112+
% % % RANDOMLY B/W 1 AND 2 FOR N TIMES) BECAUSE AT THE END EACH PARTICIPANT
113+
% % % HAS A DIFFERENET NUMBER OF TARKETS TO GET, LMK
114+
86115
% Get random number of targets for one condition
87116
targetPerCondition = randi(rangeTargets, 1, numRepetitions);
88117
% Assign the number of targets for each condition after shuffling
89118
numTargets = zeros(1, nrBlocks);
90119
numTargets(staticIndex) = Shuffle(targetPerCondition);
91120
numTargets(motionIndex) = Shuffle(targetPerCondition);
92-
93-
%% Give the blocks the names with condition
94-
95-
cfg.design.blockNames = cell(nrBlocks, 1);
96-
cfg.design.directions = zeros(nrBlocks, numEventsPerBlock);
97-
cfg.design.speeds = ones(nrBlocks, numEventsPerBlock) * dotsSpeed;
98-
cfg.design.fixationTargets = zeros(nrBlocks, numEventsPerBlock);
99-
100-
for iMotionBlock = 1:numRepetitions
101-
102-
cfg.design.directions(motionIndex(iMotionBlock), :) = Shuffle(motionDirections);
103-
cfg.design.directions(staticIndex(iMotionBlock), :) = Shuffle(staticDirections);
104-
105-
end
106-
107-
for iBlock = 1:nrBlocks
108-
109-
% Set block name
110-
switch condition{iBlock}
111-
case 'static'
112-
thisBlockName = {'static'};
113-
case 'motion'
114-
thisBlockName = {'motion'};
121+
122+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
123+
124+
%% Give the blocks the names with condition and design the task in each event
125+
126+
while 1
127+
128+
for iBlock = 1:nrBlocks
129+
130+
131+
% Set block name
132+
switch condition{iBlock}
133+
case 'static'
134+
thisBlockName = {'static'};
135+
case 'motion'
136+
thisBlockName = {'motion'};
137+
end
138+
139+
cfg.designBlockNames(iBlock) = thisBlockName;
140+
141+
% Set target
142+
% - if there are 2 targets per block we make sure that they are at least
143+
% 2 events apart
144+
% - targets cannot be on the first or last event of a block
145+
% - no more than 2 target in the same event order
146+
147+
chosenTarget = [];
148+
149+
tmpTarget = numTargets(iBlock);
150+
151+
switch tmpTarget
152+
153+
case 1
154+
155+
chosenTarget = randsample(2:numEventsPerBlock-1, tmpTarget, false);
156+
157+
case 2
158+
159+
targetDifference = 0;
160+
161+
162+
while targetDifference <= 2
163+
chosenTarget = randsample(2:numEventsPerBlock-1, tmpTarget, false);
164+
targetDifference = (max(chosenTarget) - min(chosenTarget));
165+
end
166+
167+
end
168+
169+
cfg.designFixationTargets(iBlock, chosenTarget) = 1;
170+
115171
end
116-
cfg.design.blockNames(iBlock) = thisBlockName;
117-
118-
% set target
119-
% if there are 2 targets per block we make sure that they are at least
120-
% 2 events apart
121-
% targets cannot be on the first or last event of a block
122-
123-
chosenTarget = [];
124-
125-
tmpTarget = numTargets(iBlock);
126-
127-
switch tmpTarget
128-
129-
case 1
130-
131-
chosenTarget = randsample(2:numEventsPerBlock - 1, tmpTarget, false);
132-
133-
case 2
134-
135-
targetDifference = 0;
136-
137-
while targetDifference <= 2
138-
chosenTarget = randsample(2:numEventsPerBlock - 1, tmpTarget, false);
139-
targetDifference = (max(chosenTarget) - min(chosenTarget));
140-
end
141-
172+
173+
% Check rule 3
174+
if max(sum(cfg.designFixationTargets)) < 3
175+
break
176+
else
177+
cfg.designBlockNames = cell(nrBlocks, 1);
178+
cfg.designFixationTargets = zeros(nrBlocks, numEventsPerBlock);
142179
end
143-
144-
cfg.design.fixationTargets(iBlock, chosenTarget) = 1;
145-
180+
146181
end
147-
182+
183+
184+
designSpeeds = cfg.designSpeeds';
185+
designDirections = cfg.designDirections';
186+
designFixationTargets = cfg.designFixationTargets';
187+
188+
cfg.trialList = [designDirections(:) designSpeeds(:) designFixationTargets(:)];
189+
190+
191+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
192+
148193
%% Visualize the design matrix
149194
if displayFigs
150-
151-
uniqueNames = unique(cfg.design.blockNames) ;
152-
153-
Ind = zeros(length(cfg.design.blockNames), length(uniqueNames)) ;
154-
155-
for i = 1:length(uniqueNames)
156-
CondInd(:, i) = find( ...
157-
strcmp(cfg.design.blockNames, uniqueNames{i})) ; %#ok<*AGROW>
158-
Ind(CondInd(:, i), i) = 1 ;
195+
196+
figure(1);
197+
198+
199+
% Shows blocks (static and motion) and events (motion direction) order
200+
subplot(3,3,1)
201+
202+
designDirection = cfg.designDirections;
203+
designDirection(designDirection==-1) = -90;
204+
205+
imagesc(designDirection)
206+
207+
labelAxesBlock()
208+
209+
caxis([-90-37, 270+37])
210+
myColorMap = lines(5);
211+
colormap(myColorMap);
212+
213+
title('Block (static and motion) & Events (motion direction)')
214+
215+
216+
% Shows the direction position distribution in the motion blocks
217+
% across the experiment
218+
subplot(3,3,2)
219+
220+
leftPosition = [];
221+
for i=1:nrBlocks
222+
leftPosition = [ leftPosition find(cfg.designDirections(i,:)==0) ];
159223
end
160-
161-
imagesc(Ind);
162-
163-
set(gca, ...
164-
'XTick', 1:length(uniqueNames), ...
165-
'XTickLabel', uniqueNames);
166-
224+
hist(leftPosition)
225+
scaleAxes()
226+
labelAxesFreq()
227+
title('0')
228+
229+
subplot(3,3,3)
230+
231+
rightPosition = [];
232+
for i=1:nrBlocks
233+
rightPosition = [ rightPosition find(cfg.designDirections(i,:)==90) ];
234+
end
235+
hist(rightPosition)
236+
scaleAxes()
237+
labelAxesFreq()
238+
title('90')
239+
240+
subplot(3,3,5)
241+
242+
upPosition = [];
243+
for i=1:nrBlocks
244+
upPosition = [ upPosition find(cfg.designDirections(i,:)==180) ];
245+
end
246+
hist(upPosition)
247+
scaleAxes()
248+
labelAxesFreq()
249+
title('180')
250+
251+
subplot(3,3,6)
252+
253+
downPosition = [];
254+
for i=1:nrBlocks
255+
downPosition = [ downPosition find(cfg.designDirections(i,:)==270) ];
256+
end
257+
hist(downPosition)
258+
scaleAxes()
259+
labelAxesFreq()
260+
title('270')
261+
262+
263+
% Shows the fixation targets design in each event (1 or 0)
264+
subplot(3,3,7)
265+
266+
imagesc(cfg.designFixationTargets)
267+
labelAxesBlock()
268+
title('Fixation Targets design')
269+
270+
271+
% Shows the fixation targets position distribution in the block across
272+
% the experimet
273+
subplot(3,3,8)
274+
275+
itargetPosition = [];
276+
for i=1:nrBlocks
277+
itargetPosition = [ itargetPosition find(cfg.designFixationTargets(i,:)==1) ];
278+
end
279+
hist(itargetPosition)
280+
labelAxesFreq()
281+
title('Fixation Targets position distribution')
282+
167283
end
284+
285+
end
286+
287+
function labelAxesBlock()
288+
% an old viking saying because they really cared about their axes
289+
ylabel('Block seq.', 'Fontsize', 8);
290+
xlabel('Events', 'Fontsize', 8);
291+
end
292+
293+
function labelAxesFreq()
294+
% an old viking saying because they really cared about their axes
295+
ylabel('freq.', 'Fontsize', 8);
296+
xlabel('Events', 'Fontsize', 8);
297+
end
298+
299+
function scaleAxes()
300+
xlim([1 12])
301+
ylim([0 5])
302+
end

0 commit comments

Comments
 (0)