Skip to content
createDotInfo_JQK_170704.m 8.39 KiB
Newer Older
Julian Kosciessa's avatar
Julian Kosciessa committed
%_______________________________________________________________________
%
% Configuration for running dotsExperiment
%_______________________________________________________________________
%
% Output
%
% dotInfo | configuration for random dots experiment (struct)
%_______________________________________________________________________
%

% 170704    - incorporated thresholds

function dotInfo = createDotInfo_JQK_170704(varargin)

    dotInfo.trialsPerAtt = 32; % should be around 22 minutes with current timing (30 with confidence)
    dotInfo.numOfAtt = 4; % number of attributes to be included
    dotInfo.totalTrials = dotInfo.trialsPerAtt*dotInfo.numOfAtt*2; % *2 as we want to have the specified amount per cued/uncued
    
    dotInfo.dirAttentionRate = .5; % ratio of directed attention vs. wholistic attention trials (same for each attribute)
    
    dotInfo.durCue = 2;         % duration of cue
    dotInfo.durPres = .5;       % duration of presentation
    dotInfo.durResp = 2.5;      % duration of question
    dotInfo.durConf = 2.5;      % duration of confidence
    
    dotInfo.confOptions = '2';      % 2 or 4 confidence options
    dotInfo.highlightChoice = 1;    % highlight choice by retaining only chosen option?
    
    dotInfo.feedback = 0;   % no feedback
    
    dotInfo.dirSet          = [180, 0];     % dots in left or right direction
    dotInfo.numDotField     = 1;            % show a single dot patches on screen
    dotInfo.apXYD           = [0 0 130];    % coordinates and diameter of aperture
    dotInfo.speed           = [50];         % speed of dot motion
    dotInfo.trialtype       = [2 1 1];      % reaction time, not relevant, keyboard
    dotInfo.dotSize         = 3;            % dot size in pixels
    dotInfo.maxDotTime      = 2;            % maximum duration of moving dots
    dotInfo.fixXY           = [0 0];        % fixation coordinates
    dotInfo.fixDiam         = 2;            % fixation diameter
    dotInfo.fixColor        = [0 150 200];  % blue fixation dot
    dotInfo.fixMinTime      = 0.75;         % minimum fixation
    dotInfo.fixMaxTime      = 1.25;         % maximum fixation
    dotInfo.maxDotsPerFrame = 300;          % depends on graphics card
    dotInfo.fixTime         = 2;            % JQK: fixed onset fixation time

    dotInfo.PauseAfterTrials = 50:50:dotInfo.totalTrials;     % pause every 50 trials
    dotInfo.breakTime = 30;                                   % pause for 30 seconds
    
    % update frequency of on-screen content
    
    dotInfo.Hz_RDM  = 60; % kinematogram
    
    % multi-attribute task

    if ~isempty(varargin)
        thresholds = varargin{1,1};
        dotInfo.MAT.percAtt1H = thresholds.color;
        dotInfo.MAT.percAtt2H = thresholds.direction;
        dotInfo.MAT.percAtt3H = thresholds.size;
        dotInfo.MAT.percAtt4H = thresholds.luminance;
    else 
        dotInfo.MAT.percAtt1H = .65;
        dotInfo.MAT.percAtt2H = .65;
        dotInfo.MAT.percAtt3H = .65;
        dotInfo.MAT.percAtt4H = .65;
    end
    dotInfo.MAT.percAtt1L = 1-dotInfo.MAT.percAtt1H;
    dotInfo.MAT.percAtt2L = 1-dotInfo.MAT.percAtt2H;
    dotInfo.MAT.percAtt3L = 1-dotInfo.MAT.percAtt3H;
    dotInfo.MAT.percAtt4L = 1-dotInfo.MAT.percAtt4H; 
    
    dotInfo.MAT.color = [255 255 255; 255 0 0];                             % define dot color
    dotInfo.MAT.coherence = 1;                                              % define dot movement (coherence)
    dotInfo.MAT.direction = [180 0];                                        % left and right
    dotInfo.MAT.size = [5 8];                                               % define dot size
    dotInfo.MAT.luminance = [.4 .8];                                        % define dot luminance
    dotInfo.MAT.attNames = {'color'; 'direction'; 'size'; 'luminance'};
    dotInfo.MAT.attNamesDE = {'Farbe'; 'Richtung'; 'Gre'; 'Helligkeit'};

    %% specify keys
    % Use OS X keyboard naming scheme across all plattforms
    % Otherwise LeftControl/RightControl are not recognized
    KbName('UnifyKeyNames');

    if ismac % Mac keyboard
        dotInfo.keyLeft = [KbName('LeftControl'), KbName('LeftAlt'), KbName('LeftArrow')];      % left response
        dotInfo.keyRight = [KbName('RightControl'), KbName('RightAlt'), KbName('RightArrow')];  % right response
        dotInfo.keyConf1 = [KbName('LeftControl'), KbName('LeftArrow')];       % lowest confidence
        dotInfo.keyConf2 = KbName('LeftAlt');                                  % intermediate confidence low
        dotInfo.keyConf3 = KbName('RightAlt');                                 % intermediate confidence high
        dotInfo.keyConf4 = [KbName('RightControl'), KbName('RightArrow')];     % highest confidence
    else % PC keyboard
%         dotInfo.keyLeft = KbName('LeftControl');
%         dotInfo.keyRight = KbName('RightControl');
        dotInfo.keyLeft = [KbName('LeftControl'), KbName('LeftAlt'), KbName('LeftArrow')];
        dotInfo.keyRight = [KbName('RightControl'), KbName('RightAlt'), KbName('RightArrow')];
        dotInfo.keyConf1 = [KbName('LeftControl'), KbName('LeftArrow')];
        dotInfo.keyConf2 = KbName('LeftAlt');
        dotInfo.keyConf3 = KbName('RightAlt');
        dotInfo.keyConf4 = [KbName('RightControl'), KbName('RightArrow')];
    end

    dotInfo.keyModifier = KbName('LeftAlt'); % to prevent accidental input
    dotInfo.keyEscape = KbName('Escape'); %
    dotInfo.keyReturn = KbName('Return'); % continue experiment
    dotInfo.keyPause = KbName('p');

    %% randomize stimuli and non-target duration
    
    % set random seed

    rseed = sum(100*clock);
    rng(rseed,'twister');
    [dotInfo.rngSetting] = rng;

    % pseudo-randomize target attribute (max. of 2 repetitions)
    
    distrib = repmat([1:dotInfo.numOfAtt],1,dotInfo.trialsPerAtt*2); % double amount of requested trials, so that trialsPerAtt is available within both cued and uncued condition
    tmp_rand = randperm(numel(distrib));
    tmp.random = distrib(tmp_rand);
    rep = diff(find(diff([-Inf tmp.random Inf])));
    while max(rep) > 3 % randomly switch numbers until criterion is reached
        tmp.switchInds = randi(length(tmp.random),1, 2);
        tmp.switch1 = tmp.random(tmp.switchInds(1));
        tmp.switch2 = tmp.random(tmp.switchInds(2));
        tmp.random(tmp.switchInds(1)) = tmp.switch2;
        tmp.random(tmp.switchInds(2)) = tmp.switch1;
        rep = diff(find(diff([-Inf tmp.random Inf])));
    end
    dotInfo.targetAtt = tmp.random;
    
    %% randomize directed attention trials & higher probability choice (within attribute)
    
    dotInfo.DirAttn = NaN(size(dotInfo.targetAtt));
    dotInfo.HighProbAtt = NaN(size(dotInfo.targetAtt));
    numSelAttn = ceil(dotInfo.dirAttentionRate*dotInfo.trialsPerAtt*2);
    for indAtt = 1:dotInfo.numOfAtt % retain relationships for each attribute
        tmp_trials = find(dotInfo.targetAtt == indAtt);
        tmp_rand = randperm(numel(tmp_trials));
        tmp_choice1 = tmp_trials(tmp_rand(1:numSelAttn));
        tmp_choice2 = tmp_trials(tmp_rand(numSelAttn+1:end));
        dotInfo.DirAttn(tmp_choice1) = 1;
        dotInfo.DirAttn(tmp_choice2) = 2;
        dotInfo.HighProbAtt(tmp_choice1(1:numel(tmp_choice1)/2)) = 1; % First half is designated highProb = 1;
        dotInfo.HighProbAtt(tmp_choice1((numel(tmp_choice1)/2)+1:end)) = 2; % Second half is deignated highProb = 2;
        dotInfo.HighProbAtt(tmp_choice2(1:numel(tmp_choice2)/2)) = 1;
        dotInfo.HighProbAtt(tmp_choice2((numel(tmp_choice2)/2)+1:end)) = 2;
    end
        
    % Note that within attribute high probability choice and directed attention are orthogonal.
    % They both depend on the same randomization step.
    
    % The high probability choices only refer to the target attribute. The
    % high probability options for the other attributes are randomly drawn
    % below.
    
    % Note that there is no check that the conjunction of different
    % attributes appears equally often. 
    
    %% get random choices for remaining attributes on each trial
    
    dotInfo.HighProbChoice = NaN(4,size(dotInfo.targetAtt,2));
    
    for indTrial = 1:dotInfo.totalTrials
        for indAtt = 1:dotInfo.numOfAtt
            if dotInfo.targetAtt(indTrial) == indAtt % for target attribute, select the previously identified option
                dotInfo.HighProbChoice(indAtt,indTrial) = dotInfo.HighProbAtt(1,indTrial);
            else 
                tmp_rand = randperm(2);
                dotInfo.HighProbChoice(indAtt,indTrial) = tmp_rand(1);
            end
        end
    end
    
end