Skip to content
Merged
33 changes: 13 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,35 +8,27 @@ For instructions see the following links:

| Requirements | Used version |
|----------------------------------------------------------|--------------|
| [CPP_BIDS](https://github.com/cpp-lln-lab/CPP_BIDS) | ? |
| [CPP_PTB](https://github.com/cpp-lln-lab/CPP_PTB) | ? |
| [PsychToolBox](http://psychtoolbox.org/) | >=3.0.14 |
| [Matlab](https://www.mathworks.com/products/matlab.html) | >=2017 |
| [Matlab](https://www.mathworks.com/products/matlab.html) | >=2017b |
| or [octave](https://www.gnu.org/software/octave/) | >=4.? |

## Installing dependencies
## Installation

All the dependencies needed to run this are listed in the [mpm-requirements.txt file](.mpm-requirements.txt). If those functions are not in the matlab path the scripts in this repository will not work.
The CPP_BIDS and CPP_PTB dependencies are already set up as submodule to this repository.
You can install it all with git by doing.

If you are using the [matlab package manager](https://github.com/mobeets/mpm), you can simply download the appropriate version of those dependencies and add them to your path by running the `getDependencies` function.

```matlab
getDependencies('update')
```bash
git clone --recurse-submodules https://github.com/cpp-lln-lab/localizer_auditory_motion.git
```

If you already have the appropriate version but just want to add them to the matlab path, then run.

```matlab
getDependencies()
```
## Structure and function details


### visualLocTranslational
### audioLocTranslational

Running this script will play blocks of motion static sounds. Motion blocks will play sounds moving in one of four directions (up-, down-, left-, and right-ward)
Running this script will play blocks of motion/static sounds. Motion blocks will play sounds moving in one of four directions (up-, down-, left-, and right-ward)

By default it is run in `Debug mode` meaning that it does not run care about subjID, run n., fMRI triggers, Eye Tracker, etc..
By default it is run in `Debug mode` meaning that it does not care about subjID, run n., fMRI triggers, Eye Tracker, etc..

Any details of the experiment can be changed in `setParameters.m` (e.g., experiment mode, motion stimuli details, exp. design, etc.)

Expand All @@ -45,12 +37,13 @@ Any details of the experiment can be changed in `setParameters.m` (e.g., experim
`setParameters.m` is the core engine of the experiment. It contains the following tweakable sections:

- Debug mode setting
- MRI settings
- Engine parameters:
- Devices parameters
- Monitor parameters
- Monitor parameters for PsychToolBox
- Keyboards
- Keyboard parameters
- MRI parameters
- Experiment Design
- Timing
- Auditory Stimulation
- Task(s)
- Instructions
Expand Down
8 changes: 4 additions & 4 deletions audioLocTranslational.m
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@

getResponse('start', cfg.keyboard.responseBox);

WaitSecs(cfg.onsetDelay);
WaitSecs(cfg.timing.onsetDelay);

%% For Each Block

Expand Down Expand Up @@ -110,18 +110,18 @@
saveResponsesAndTriggers(responseEvents, cfg, logFile, triggerString);

% wait for the inter-stimulus interval
WaitSecs(cfg.ISI);
WaitSecs(cfg.timing.ISI);

end

eyeTracker('StopRecordings', cfg);

WaitSecs(cfg.IBI);
WaitSecs(cfg.timing.IBI);

end

% End of the run for the BOLD to go down
WaitSecs(cfg.endDelay);
WaitSecs(cfg.timing.endDelay);

% Close the logfiles
saveEventsFile('close', cfg, logFile);
Expand Down
80 changes: 44 additions & 36 deletions setParameters.m
Original file line number Diff line number Diff line change
Expand Up @@ -32,30 +32,38 @@
% MRI settings
cfg = setMRI(cfg);

cfg.audio.channels = 2;

%% Experiment Design
cfg.names = {'static', 'motion'};
cfg.possibleDirections = [-1 1]; % 1 motion , -1 static
cfg.numBlocks = size(cfg.possibleDirections, 2);
cfg.numRepetitions = 1; % AT THE MOMENT IT IS NOT SET IN THE MAIN SCRIPT

cfg.design.names = {'static', 'motion'};
cfg.design.possibleDirections = [-1 1]; % 1 motion , -1 static %NOT IN USE AT THE MOMENT
cfg.design.nbBlocks = size(cfg.design.names, 2); % TO CHECK
cfg.design.nbRepetitions = 1; % AT THE MOMENT IT IS NOT SET IN THE MAIN SCRIPT
cfg.design.nbEventsPerBlock = 12;

%% Timing
cfg.IBI = 0; % 8;
cfg.ISI = 0.1; % Time between events in secs
cfg.onsetDelay = 1; % Number of seconds before the motion stimuli are presented
cfg.endDelay = 1; % Number of seconds after the end all the stimuli before ending the run

% FOR 7T: if you want to create localizers on the fly, the following must be
% multiples of the scanneryour sequence TR
%
% IBI
% block length = (cfg.eventDuration + cfg.ISI) * cfg.design.nbEventsPerBlock

% Time between blocs in secs
cfg.timing.IBI = 1.8 * 3; % 8;
% Time between events in secs
cfg.timing.ISI = 0.1;
% Number of seconds before the motion stimuli are presented
cfg.timing.onsetDelay = .1;
% Number of seconds after the end all the stimuli before ending the run
cfg.timing.endDelay = .1;

%% Auditory Stimulation

% expParameters.experimentType = 'Gratings'; %Dots/Gratings % Visual modality is in RDKs %NOT USED IN THE MAIN SCIPT
cfg.speedEvent = 8; % speed in visual angles
cfg.numEventsPerBlock = 12; % Number of events per block (should not be changed)
cfg.eventDuration = 10;
cfg.audio.channels = 2;

%% Task
%% Task(s)

cfg.task.name = 'visual localizer';
cfg.task.name = 'auditory localizer';

% Instruction
cfg.task.instruction = '1-Detect the RED fixation cross\n \n\n';
Expand All @@ -76,6 +84,26 @@

end

function cfg = setMonitor(cfg)

% Monitor parameters for PTB
cfg.color.white = [255 255 255];
cfg.color.black = [0 0 0];
cfg.color.red = [255 0 0];
cfg.color.grey = mean([cfg.color.black; cfg.color.white]);
cfg.color.background = cfg.color.black;
cfg.text.color = cfg.color.white;

% Monitor parameters
cfg.screen.monitorWidth = 50; % in cm
cfg.screen.monitorDistance = 40; % distance from the screen in cm

if strcmpi(cfg.testingDevice, 'mri')
cfg.screen.monitorWidth = 50;
cfg.screen.monitorDistance = 40;
end
end

function cfg = setKeyboards(cfg)
cfg.keyboard.escapeKey = 'ESCAPE';
cfg.keyboard.responseKey = {'space', 't'};
Expand All @@ -99,23 +127,3 @@
cfg.bids.MRI.TaskDescription = [];

end

function cfg = setMonitor(cfg)

% Monitor parameters for PTB
cfg.color.white = [255 255 255];
cfg.color.black = [0 0 0];
cfg.color.red = [255 0 0];
cfg.color.grey = mean([cfg.color.black; cfg.color.white]);
cfg.color.background = cfg.color.black;
cfg.text.color = cfg.color.white;

% Monitor parameters
cfg.screen.monitorWidth = 50; % in cm
cfg.screen.monitorDistance = 40; % distance from the screen in cm

if strcmpi(cfg.testingDevice, 'mri')
cfg.screen.monitorWidth = 50;
cfg.screen.monitorDistance = 40;
end
end
61 changes: 29 additions & 32 deletions subfun/expDesign.m
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
function [cfg] = expDesign(cfg, displayFigs)
% Creates the sequence of blocks and the events in them
%
% The conditions are consecutive static and motion blocks (Gives better results than randomised).
% The conditions are consecutive static and motion blocks (Gives better results
% than randomised).
%
% It can be run as a stand alone without inputs to display a visual example of possible design.
%
Expand All @@ -24,14 +25,13 @@
% - ExpParameters.designBlockNames = cell array (nr_blocks, 1) with the
% name for each block
%
% - ExpParameters.designDirections = array (nr_blocks, numEventsPerBlock)
% - ExpParameters.designDirections = array (nr_blocks, nbEventsPerBlock)
% with the direction to present in a given block
% - 0 90 180 270 indicate the angle
% - -1 indicates static
%
% - ExpParameters.designSpeeds = array (nr_blocks, numEventsPerBlock) * speedEvent
%
% - ExpParameters.designFixationTargets = array (nr_blocks, numEventsPerBlock)
% - ExpParameters.designFixationTargets = array (nr_blocks, nbEventsPerBlock)
% showing for each event if it should be accompanied by a target
%

Expand All @@ -48,11 +48,10 @@

% Set variables here for a dummy test of this function
if nargin < 1 || isempty(cfg)
cfg.names = {'static', 'motion'};
cfg.numRepetitions = 4;
cfg.speedEvent = 4;
cfg.numEventsPerBlock = 12;
cfg.maxNumFixationTargetPerBlock = 2;
cfg.design.names = {'static', 'motion'};
cfg.design.nbRepetitions = 4;
cfg.design.nbEventsPerBlock = 12;
cfg.target.maxNbPerBlock = 2;
end

% Set to 1 for a visualtion of the trials design order
Expand All @@ -61,46 +60,44 @@
end

% Get the parameters
names = cfg.names;
numRepetitions = cfg.numRepetitions;
speedEvent = cfg.speedEvent;
numEventsPerBlock = cfg.numEventsPerBlock;
maxNumFixTargPerBlock = cfg.target.maxNbPerBlock;

if mod(numEventsPerBlock, length(motionDirections)) ~= 0
warning('the number of events per block is not a multiple of the number of motion/static diection');
names = cfg.design.names;
nbRepetitions = cfg.design.nbRepetitions;
nbEventsPerBlock = cfg.design.nbEventsPerBlock;
maxNbFixTargPerBlock = cfg.target.maxNbPerBlock;

if mod(nbEventsPerBlock, length(motionDirections)) ~= 0
warning('the n. of events per block is not a multiple of experimental conditions');
end

%% Adapt some variables according to input

% Set directions for static and motion condition
motionDirections = repmat(motionDirections, 1, numEventsPerBlock / length(motionDirections));
staticDirections = repmat(staticDirections, 1, numEventsPerBlock / length(staticDirections));
motionDirections = repmat(motionDirections, 1, nbEventsPerBlock / length(motionDirections));
staticDirections = repmat(staticDirections, 1, nbEventsPerBlock / length(staticDirections));

% Assign the conditions
condition = repmat(names, 1, numRepetitions);
condition = repmat(names, 1, nbRepetitions);
nrBlocks = length(condition);
% Get the index of each condition
staticIndex = find(strcmp(condition, 'static'));
motionIndex = find(strcmp(condition, 'motion'));

% Assign the targets for each condition
rangeTargets = [1 maxNumFixTargPerBlock];
rangeTargets = [1 maxnbFixTargPerBlock];
% Get random number of targets for one condition
targetPerCondition = randi(rangeTargets, 1, numRepetitions);
targetPerCondition = randi(rangeTargets, 1, nbRepetitions);
% Assign the number of targets for each condition after shuffling
numTargets = zeros(1, nrBlocks);
numTargets(staticIndex) = Shuffle(targetPerCondition);
numTargets(motionIndex) = Shuffle(targetPerCondition);
nbTargets = zeros(1, nrBlocks);
nbTargets(staticIndex) = Shuffle(targetPerCondition);
nbTargets(motionIndex) = Shuffle(targetPerCondition);

%% Give the blocks the names with condition

cfg.designBlockNames = cell(nrBlocks, 1);
cfg.designDirections = zeros(nrBlocks, numEventsPerBlock);
cfg.designSpeeds = ones(nrBlocks, numEventsPerBlock) * speedEvent;
cfg.designFixationTargets = zeros(nrBlocks, numEventsPerBlock);
cfg.designDirections = zeros(nrBlocks, nbEventsPerBlock);
cfg.designFixationTargets = zeros(nrBlocks, nbEventsPerBlock);

for iMotionBlock = 1:numRepetitions
for iMotionBlock = 1:nbRepetitions

cfg.designDirections(motionIndex(iMotionBlock), :) = Shuffle(motionDirections);
cfg.designDirections(staticIndex(iMotionBlock), :) = Shuffle(staticDirections);
Expand All @@ -125,20 +122,20 @@

chosenTarget = [];

tmpTarget = numTargets(iBlock);
tmpTarget = nbTargets(iBlock);

switch tmpTarget

case 1

chosenTarget = randsample(2:numEventsPerBlock - 1, tmpTarget, false);
chosenTarget = randsample(2:nbEventsPerBlock - 1, tmpTarget, false);

case 2

targetDifference = 0;

while targetDifference <= 2
chosenTarget = randsample(2:numEventsPerBlock - 1, tmpTarget, false);
chosenTarget = randsample(2:nbEventsPerBlock - 1, tmpTarget, false);
targetDifference = (max(chosenTarget) - min(chosenTarget));
end

Expand Down