Skip to content

Commit 38710ba

Browse files
Merge pull request #84 from marcobarilari/marco_streamline-expdesign
Refactor `expDesign`
2 parents 5d82374 + 1a9573c commit 38710ba

26 files changed

+562
-323
lines changed

.github/workflows/moxunit.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: CI
1+
name: Tests
22

33
on:
44
push:

README.md

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ Wrapper function that present the dot stimulation (static or motion) per event.
110110
#### Input
111111

112112
- `cfg`: PTB/machine and experiment configurations returned by `setParameters` and `initPTB`
113+
- `logFile`: structure that stores the experiment logfile to be saved
113114
- `thisEvent`: structure that stores information about the event to present regarding the dots (static or motion, direction, etc.)
114115
- `thisFixation`: structure that stores information about the fixation cross task to present
115116
- `dots`: [...]
@@ -125,30 +126,44 @@ Wrapper function that present the dot stimulation (static or motion) per event.
125126
126127
### subfun/expDesign(MtMst)
127128

128-
These functions, one per MT+ and one per MT/MST localizer, create the sequence of blocks and the events in them. The conditions are consecutive static and motion blocks (Gives better results than randomised). It can be run as a stand alone with input `cfg` from `setParamenters.m` to display a visual example of possible design.
129+
These functions, one per MT+ and one per MT/MST localizer, create the sequence of blocks and the events in them. The conditions are consecutive static and motion blocks (Gives better results than randomised).
129130

130-
#### EVENTS
131+
It can be run as a stand alone without inputs and display a visual example of the possible design. See `getMockConfig` to set up the mock configuration.
131132

132-
The `numEventsPerBlock` should be a multiple of the number of "base" listed in the `motionDirections` and `staticDirections` (4 at the moment).
133+
It computes the directions to display and the task(s), at the moment
134+
1. detection of change in the color of the fixation target
135+
2. detection of different speed of the moving dots [ W I P - if selected as a task it will give the same null output as if not selected ie no difference in speed]
133136

134-
#### TARGETS
137+
#### Events
135138

136-
- If there are 2 targets per block we make sure that they are at least 2 events apart.
137-
- Targets cannot be on the first or last event of a block
139+
The ``nbEventsPerBlock`` should be a multiple of the number of motion directions requested in ``motionDirections`` (which should be more than 1) e.g.:
140+
- MT localizer: `cfg.design.motionDirections = [ 0 90 180 270 ]; % right down left up`
141+
- MT_MST localizer: `cfg.design.motionDirections = [666 -666]; % outward inward`
138142

139-
#### Input
143+
#### Pseudorandomization rules:
140144

141-
- `expParameters`: parameters returned by `setParameters`
142-
- `displayFigs`: a boolean to decide whether to show the basic design matrix of the design
145+
- Directions:
146+
1. Directions are all presented in random orders in `numEventsPerBlock/nDirections` consecutive chunks. This evenly distribute the directions across the block.
147+
2. No same consecutive direction
143148

144-
#### Output
149+
- Color change detection of the fixation cross:
150+
1. If there are 2 targets per block we make sure that they are at least 2 events apart.
151+
2. Targets cannot be on the first or last event of a block.
152+
3. No less than 1 target per event position in the whole run
153+
154+
#### Input:
155+
- `cfg`: parameters returned by setParameters
156+
- `displayFigs`: a boolean to decide whether to show the basic design matrix of the design
145157

146-
- `expParameters.designBlockNames` is a cell array `(nr_blocks, 1)` with the name for each block
147-
- `expParameters.designDirections` is an array `(nr_blocks, numEventsPerBlock)` with the direction to present in a given block
148-
- `0 90 180 270` indicate the angle
149-
- `-1` indicates static
150-
- `expParameters.designSpeeds` is an array `(nr_blocks, numEventsPerBlock) * speedEvent`
151-
- `expParameters.designFixationTargets` is an array `(nr_blocks, numEventsPerBlock)` showing for each event if it should be accompanied by a target
158+
#### Output:
159+
- `cfg.design.blockNames`: cell array (nbBlocks, 1) with the condition name for each block
160+
- `cfg.design.nbBlocks`: integer for th etotal number of blocks in the run
161+
- `cfg.design.directions`: array (nbBlocks, nbEventsPerBlock) with the direction to present in a given event of a block.
162+
- 0 90 180 270 indicate the angle for translational motion direction
163+
- 666 -666 indicate in/out-ward direction in radial motion
164+
- -1 indicates static
165+
- `cfg.design.speeds`: array (nbBlocks, nbEventsPerBlock) indicate the dots speed in each event, the target is represented by a higher/lower value
166+
- `cfg.design.fixationTargets`: array (nbBlocks, numEventsPerBlock) showing for each event if it should be accompanied by a target
152167

153168
## Contributors ✨
154169

subfun/assignConditions.m

Lines changed: 0 additions & 23 deletions
This file was deleted.

subfun/diplayDesign.m renamed to subfun/design/diplayDesign.m

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
% (C) Copyright 2020 CPP visual motion localizer developpers
2-
31
function diplayDesign(cfg, displayFigs)
2+
%
3+
% (C) Copyright 2020 CPP visual motion localizer developpers
44

55
%% Visualize the design matrix
66
if displayFigs
@@ -44,7 +44,7 @@ function diplayDesign(cfg, displayFigs)
4444

4545
figure(2);
4646

47-
[motionDirections] = getDirectionBaseVectors(cfg);
47+
[~, motionDirections] = getDirectionBaseVectors(cfg);
4848
motionDirections = unique(motionDirections);
4949

5050
for iMotion = 1:length(motionDirections)

subfun/design/expDesign.m

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
function [cfg] = expDesign(cfg, displayFigs)
2+
%
3+
% Creates the sequence of blocks and the events in them
4+
%
5+
% The conditions are consecutive static and motion blocks. It gives better results than
6+
% randomised.
7+
%
8+
% It can be run as a stand alone without inputs and display a visual example of the
9+
% possible design. See `getMockConfig` to set up the mock configuration.
10+
%
11+
% It computes the directions to display and the task(s), at the moment:
12+
% (1) detection of change in the color of the fixation target
13+
% (2) detection of different speed of the moving dots [ W I P - if selected as a task it will
14+
% give the same null output as if not selected ie no difference in speed ]
15+
%
16+
% EVENTS
17+
% The ``nbEventsPerBlock`` should be a multiple of the number of motion directions requested in
18+
% ``motionDirections`` (which should be more than 1) e.g.:
19+
% MT localizer: ``cfg.design.motionDirections = [ 0 90 180 270 ]; % right down left up``
20+
% MT_MST localizer: ``cfg.design.motionDirections = [666 -666]; % outward inward``
21+
%
22+
% Pseudorandomization rules:
23+
%
24+
% - Directions:
25+
% (1) Directions are all presented in random orders in `numEventsPerBlock/nDirections`
26+
% consecutive chunks. This evenly distribute the directions across the
27+
% block.
28+
% (2) No same consecutive direction
29+
%
30+
% - Color change detection of the fixation cross:
31+
% (1) If there are 2 targets per block we make sure that they are at least 2 events apart.
32+
% (2) Targets cannot be on the first or last event of a block.
33+
% (3) No less than 1 target per event position in the whole run
34+
%
35+
% Input:
36+
% - cfg: parameters returned by setParameters
37+
% - displayFigs: a boolean to decide whether to show the basic design
38+
% matrix of the design
39+
%
40+
% Output:
41+
% - cfg.design.blockNames: cell array (nbBlocks, 1) with the condition name for each block
42+
% - cfg.design.nbBlocks: integer for th etotal number of blocks in the run
43+
% - cfg.design.directions: array (nbBlocks, nbEventsPerBlock) with the direction to present in a
44+
% given event of a block.
45+
% - 0 90 180 270 indicate the angle for translational motion direction
46+
% - 666 -666 indicate in/out-ward direction in radial motion
47+
% - -1 indicates static
48+
% - cfg.design.speeds: array (nbBlocks, nbEventsPerBlock) indicate the dots speed
49+
% in each event, the target is represented by a higher/lower value
50+
% - cfg.design.fixationTargets: array (nbBlocks, numEventsPerBlock) showing for each event if it
51+
% should be accompanied by a target
52+
%
53+
% (C) Copyright 2020 CPP visual motion localizer developpers
54+
55+
%% Check inputs
56+
if nargin < 1 || isempty(cfg)
57+
58+
% ``true`` for MT+ translational localizer
59+
% ``false`` for MT/MST localizer
60+
isMT = true;
61+
62+
% Get mock inputs to run this function as a stand alone and get a flavour of how the design
63+
% looks like given certain inputs. Open this function to set different inputs.
64+
getMockConfig(isMT);
65+
66+
% Get the computed design on a visual representation
67+
displayFigs = 1;
68+
69+
end
70+
71+
% Set to 1 for a visualtion of the trials design order
72+
if nargin < 2 || isempty(displayFigs)
73+
displayFigs = 0;
74+
end
75+
76+
fprintf('\n\nComputing the design...\n\n');
77+
78+
%% Stimuli design
79+
80+
% Computer a vector [nbBlocks x 1] with the order of the conditions to present
81+
cfg.design.blockNames = setBlocksConditions(cfg);
82+
83+
% Get the nb of blocks
84+
[~, ~, ~, cfg.design.nbBlocks] = getDesignInput(cfg);
85+
86+
% Compute a matrix [nbBlocks x nbEventsPerBlock]
87+
cfg.design.directions = setDirections(cfg);
88+
89+
%% Task(s) design
90+
91+
% Compute a matrix [nbBlocks x nbEventsPerBlock] with
92+
cfg.design.fixationTargets = setFixationTargets(cfg);
93+
94+
% Compute a matrix [nbBlocks x nbEventsPerBlock] with the dots speeds (target speed will be
95+
% different form the base one)
96+
cfg.design.speeds = setSpeedTargets(cfg);
97+
98+
%% Plot a visual representation of the design
99+
diplayDesign(cfg, displayFigs);
100+
101+
fprintf('\n\n...design computed!\n\n');
102+
103+
end

subfun/expDesignMtMst.m renamed to subfun/design/expDesignMtMst.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
% (C) Copyright 2021 CPP visual motion localizer developpers
2-
31
function [cfg] = expDesignMtMst(cfg, displayFigs)
2+
%
3+
% (C) Copyright 2020 CPP visual motion localizer developpers
44

55
%% Check inputs
66

subfun/design/getDesignInput.m

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
function [nbRepetitions, nbEventsPerBlock, maxNbPerBlock, nbBlocks] = getDesignInput(cfg)
2+
%
3+
% (C) Copyright 2020 CPP visual motion localizer developpers
4+
5+
nbRepetitions = cfg.design.nbRepetitions;
6+
nbEventsPerBlock = cfg.design.nbEventsPerBlock;
7+
maxNbPerBlock = cfg.target.maxNbPerBlock;
8+
nbBlocks = length(cfg.design.names) * nbRepetitions;
9+
end
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
function [directionsCondition1, directionsCondition2] = getDirectionBaseVectors(cfg)
2+
%
3+
% (C) Copyright 2020 CPP visual motion localizer developpers
4+
5+
% Set directions for static and motion condition
6+
7+
% condition1 = 'static';
8+
% condition2 = 'motion';
9+
10+
directionsCondition1 = repmat(-1, size(cfg.design.motionDirections));
11+
12+
directionsCondition2 = cfg.design.motionDirections;
13+
14+
end
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
function [conditionNamesVector, idxCondition1, idxCondition2] = setBlocksConditions(cfg)
2+
%
3+
% (C) Copyright 2020 CPP visual motion localizer developpers
4+
5+
nbRepetitions = getDesignInput(cfg);
6+
7+
conditionNamesVector = repmat(cfg.design.names, nbRepetitions, 1);
8+
9+
% Get the index of each condition
10+
nameCondition1 = 'static';
11+
nameCondition2 = 'motion';
12+
13+
idxCondition1 = find(strcmp(conditionNamesVector, nameCondition1));
14+
idxCondition2 = find(strcmp(conditionNamesVector, nameCondition2));
15+
16+
end

subfun/design/setDirections.m

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
function directions = setDirections(cfg)
2+
%
3+
% Compute the directions to be displayed
4+
% in a matrix of size ``nbBlocks`` by ``nbEventsPerBlock``
5+
%
6+
% condition1 = 'static';
7+
% condition2 = 'motion';
8+
%
9+
% (C) Copyright 2020 CPP visual motion localizer developpers
10+
11+
% Get the directions we should work with
12+
[directionsCondition1, directionsCondition2] = getDirectionBaseVectors(cfg);
13+
14+
% Get the inputs to compute the experiment design
15+
[nbRepetitions, nbEventsPerBlock, ~, nbBlocks] = getDesignInput(cfg);
16+
17+
% Get the index of the conditions form the conditions vector
18+
[~, idxCondition1, idxCondition2] = setBlocksConditions(cfg);
19+
20+
if mod(nbEventsPerBlock, length(directionsCondition2)) ~= 0
21+
error('Number of events/block not a multiple of number of motion/static direction');
22+
end
23+
24+
% Initialize and pre allocate the directions matrix
25+
directions = zeros(nbBlocks, nbEventsPerBlock);
26+
27+
% Create a vector for the static condition 1 by ``nbEventsPerBlock``
28+
nbRepeatsDirectionBaseVector = nbEventsPerBlock / length(directionsCondition1);
29+
30+
staticDirections = repmat( ...
31+
directionsCondition1, ...
32+
1, nbRepeatsDirectionBaseVector);
33+
34+
% Compute the the directions matrix, setting the motion direction orders
35+
for iMotionBlock = 1:nbRepetitions
36+
37+
% Set motion directions
38+
directions(idxCondition2(iMotionBlock), :) = ...
39+
repeatShuffleConditions(directionsCondition2, nbRepeatsDirectionBaseVector);
40+
41+
if strcmp(cfg.design.localizer, 'MT') || ...
42+
strcmp(cfg.design.localizer, 'MT_MST') && length(cfg.design.names) == 2
43+
44+
directions(idxCondition1(iMotionBlock), :) = staticDirections;
45+
46+
end
47+
48+
end
49+
50+
end

0 commit comments

Comments
 (0)