Experimental parameters

Basics

For your experiment you can choose what parameters you have and what values they can take on. You do this by adding parameters (of your choosing) into the parameter part of a task variable:

task.parameter.myParameter1 = [1 3 5 10];
task.parameter.myParameter2 = [-1 1];

You can add any number of parameters that you want. updateTask will chose a value on each trial and put those values into the thistrial structure:

task.thistrial.myParameter1
task.thistrial.myParameter2

would equal the setting on that particular trial. In each block every combination of parameters will be presented. You can randomize the order of the parameters by setting:

task.random = 1;

Note that parameter should really just be used for the parameters over which you want to randomize your experiment. For example, you may be testing several contrasts in your experiment, that should be coded as a parameter. You may also have some random variables, things like which segment that target should be presented in for example–things that need to be randomized, but are not a crucial parameter you are testing. For these types of variables, you should use randVars instead of parameter (see below).

What if I have parameters that are not single numbers

You may have a parameter that is an array rather than a single number, for example a string:

task.parameter.strings = {'string1','string2','string3'};

The variable strings will be set in task.thistrial:

task.thistrial.strings

What if I have a group of parameters

You may have stimuli in which the parameters are grouped into different sets. For example you might want to show two types of grating patches. One tilted to the left with a high contrast and low spatial frequency and the other tilted to the right with low contrast and high spatial frequency.

Then you could do

task.parameter.groupNum = [1 2];
task.private.group{1}.orientation = -10;
task.private.group{1}.contrast = 1;
task.private.group{1}.sf = 0.2;
task.private.group{2}.orientation = 10;
task.private.group{2}.contrast = 0.1;
task.private.group{2}.sf = 4;

On each trial, you get the parameters by doing

task.thistrial.thisgroup = task.private.group{task.thistrial.groupNum};

randVars

For variables that you just want to have some randomization over, you can declare them as randVars. For example, you might want to specify a target interval which should be either 1 or 2 on any given trial, but you don't want that to be block randomized. Then you can declare that variable as a uniform randomization:

task.randVars.uniform.targetInterval = [1 2];

This variable will then be available in task.thistrial.targetInterval.

You may also want to have the variable block randomized, like a parameter, but the blocks should be independent of the main parameter:

task.randVars.block.blockedVar = [-1 0 1];

This will guarantee that on every three trials, blockedVar will be set to each one of the possible values -1,0 and 1.

Note that with randVars the randomization is chosen at the beginning of the experiment and by default 250 trials are randomized after which you will cycle back through the variables. If you need more than 250 trials, you can set:

task.randVars.len_ = 500;

Storing variables calculated during a trial

If you want to store a value calculated during a trial (e.g. a user entered value or a calculated value) you can use the 'calculated' type of randVar. The variables defined in the calculated struct array are initialized to the value(s) specified. The variables are then made available in the 'task.thistrial' as with other parameters and randVars. However, the all variables that were defined as 'calculated' are saved back to the randVars variable array at the end of the trial. These calculated values will then be available when you extract the parameters using getTaskParameters. For example, you can declare in your task variable:

task{1}.randVars.calculated.myVar = nan;

Note that the default value (if you don't set it in a callback, will be the one set above, i.e. nan). Next in any callback, you can set that variable. For example in the response callback:

task.thistrial.myVar = 15;

After the experiment is done that variable can be accessed through getTaskParameters just like any other parameter or randVar. Note that if you set the variable to something other than a scalar, the calculated variable will be stored as a cell array and you should set the default argument to {nan} instead of nan.

You may also (optionally) specify all the values that your calculated variable may take on. This is useful if during any given run you won't necessarily encounter all possible values. To do this set the variable name with an underscore after it:

task{1}.randVars.calculated.myVar_ = 1:15;

Using your own random sequence

You might have your own randomization routine and want to use that to randomize parameters. You can do that with randVars:

task.randVars.myRandomParameter = [...];

Then myRandomParameter will be available in task.thistrial.myRandomParameter in the order you specify in the array. “myRandomParameter” can be any name you choose. Note in this example there is no type definition before the variable name (e.g., block or uniform). Variables declared this way will be treated by MGL as a real sequence, whereas the normal usage (with block/uniform field) is treated as declaration of the levels of a variable, which is used to generate a sequence by MGL.

Creating a parameter sequence after running the stimulus program

Sometimes you may want to compute a parameter sequence after you have run the stimulus program. For example, if you want to compute a new variable sequence to do event-related processing based on the existing data within your stim file. To do so, you can use the function addCalculatedVar. You run this on a stimfile. For example, say you have a stimfile with 5 trials, and you wanted to add the variable 'myCalcVar' with values [0 3 2 4 1] for those trials:

addCalculatedVar('myCalcVar',[0 3 2 4 1],'100727_stim01');

After running this, the variable myCalcVar will appear when you run getTaskParameters and you can use it to do event-related analysis from the mrLoadRet GUI. Note that addCalculatedVar will overwrite the stimfile 100727_stim01.mat, but will save an original copy called 100727_stim01_original.mat.

You may also (optionally) specify all the values that your calculated variable may take on. This is useful if during any given run you won't necessarily encounter all possible values. To do this set the variable name with an underscore after it:

addCalculatedVar('myCalcVar',[0 3 2 4 1],'100727_stim01','allval',0:5);

See also this how-to.