Skip to content
MAT_experiment_170809.m 8.66 KiB
Newer Older
Julian Kosciessa's avatar
Julian Kosciessa committed
%_______________________________________________________________________
%
% Run random dot motion experiment defined in createDotInfo
%_______________________________________________________________________
%
% Input
%
% dotInfo | experiment configuration (struct)
%    subj | identifier of subject (string)
% condSet | conditions (cell array of strings)
%_______________________________________________________________________
%

% adapted from dotsExperiment_JQK_170327
% 170704    | cleanup, adapted
% 170707    | removed saving for each trial; instead save in catch part
%           | now saves DisplayInfo
Julian Kosciessa's avatar
Julian Kosciessa committed
% 170809    | adapted to state space version
Julian Kosciessa's avatar
Julian Kosciessa committed

Julian Kosciessa's avatar
Julian Kosciessa committed
function MAT_experiment_170809(dotInfo, subj, setup)
Julian Kosciessa's avatar
Julian Kosciessa committed

  %%
  %% sanitize function parameters
  %%
  if nargin == 0
    eval('help dotsExperiment')
    return
  end

  if not(exist('dotInfo','var'))
    error('Missing input: dotInfo')
  elseif isempty(dotInfo) || not(isstruct(dotInfo))
    error('Invalid input: dotInfo (requires non-empty struct)')
  end

  if not(exist('subj','var'))
    error('Missing input: subj')
  elseif not(isempty(subj)) && ischar(subj)
    dotInfo.subj = subj;
  else
    error('Invalid input: subj (requires non-empty string)')
  end

  if not(isfield(dotInfo,'deployed'))
    dotInfo.deployed = true;
  end

  %%
  %% for saving behavioural data
  %%
  
  sessionFile = [dotInfo.dataDir, subj '_' datestr(now, 'yymmdd_HHMM'), '.mat'];
    
  %%
  %% prepare presentation
  %%
  displayList = Screen('screens');
Julian Kosciessa's avatar
Julian Kosciessa committed
  displayIdx = displayList(2);
Julian Kosciessa's avatar
Julian Kosciessa committed
  KbName('UnifyKeyNames'); % use portable key naming scheme
  oldVerbosityLevel = Screen('Preference', 'Verbosity', 2); % show errors and warnings
  
Julian Kosciessa's avatar
Julian Kosciessa committed
    if setup.DEBUG == 1
Julian Kosciessa's avatar
Julian Kosciessa committed
        Screen('Preference', 'SkipSyncTests', 1);
Julian Kosciessa's avatar
Julian Kosciessa committed
        PsychDebugWindowConfiguration(0, setup.opacity);
Julian Kosciessa's avatar
Julian Kosciessa committed
    else
        clear Screen; %PsychDebugWindowConfiguration([], 1);
    end;

  try

    %%
    %% prepare canvas
    %%
    screenInfo = openExperiment(50,50,displayIdx); clc; % open drawing canvas
    if numel(Screen('screens')) == 1 || dotInfo.deployed
      HideCursor(screenInfo.curWindow);
    end
    Screen('TextFont', screenInfo.curWindow, 'Helvetica');
    Screen('TextSize', screenInfo.curWindow, 20);
    Screen('TextStyle', screenInfo.curWindow, 0); % regular
    Screen('TextColor', screenInfo.curWindow, 255); % white

Julian Kosciessa's avatar
Julian Kosciessa committed
    % get experimenter and subject keyboards
    keyboardIndices = GetKeyboardIndices;
    if setup.keyB == 1 % use primary keyboard for subject and experimenter
        screenInfo.keyboard_sub = keyboardIndices(1);
        screenInfo.keyboard_exp = keyboardIndices(1);
    elseif setup.keyB == 2
        screenInfo.keyboard_sub = min(keyboardIndices);
        screenInfo.keyboard_exp = max(keyboardIndices);
    else disp('Check setup: only 1 or 2 keyboards supported.');
    end
    
Julian Kosciessa's avatar
Julian Kosciessa committed
    sessStartTime = GetSecs;

    ResultMat = NaN(dotInfo.totalTrials,4);
    DisplayInfo = [];
    ExperimentProtocol = cell(0);
Julian Kosciessa's avatar
Julian Kosciessa committed
    ExperimentProtocol = [ExperimentProtocol; {'SessionOnset'}, {sessStartTime}, {[]}, {[]},{[]} {[]},{NaN}, {[]}];
Julian Kosciessa's avatar
Julian Kosciessa committed
    
      %%
      %% block start
      %%
      
        % have the subject get ready for the next condition
        DrawFormattedText(screenInfo.curWindow, 'Bereit?', 'center', 'center');
        Screen('Flip', screenInfo.curWindow);
Julian Kosciessa's avatar
Julian Kosciessa committed
        disp('Experimenter input required: ready for presentation? --> MAT start');
Julian Kosciessa's avatar
Julian Kosciessa committed

        % wait for experimenter to resume session
        while true
Julian Kosciessa's avatar
Julian Kosciessa committed
            [exitSession, resumeSession] = checkKeys_byKeyB(dotInfo, screenInfo.keyboard_exp);
Julian Kosciessa's avatar
Julian Kosciessa committed
        if resumeSession
            break
        elseif exitSession
            closeExperiment;
            return
        end
        end
      
Julian Kosciessa's avatar
Julian Kosciessa committed
      for indBlock = 1:dotInfo.blockAmount
        
          % present state cues
            for indAtt = 1:4
                CueImg = ['img/', dotInfo.MAT.attNames{indAtt},'?.png'];
                [cueLoad,~,~] = imread(CueImg);
                cue2Disp = Screen('MakeTexture',screenInfo.curWindow,cueLoad);
                smallIm = [0 0 floor(size(cueLoad,2)/1.5) floor(size(cueLoad,1)/1.5)];
                switch indAtt 
                    case 1
                        smallIm = CenterRect([0 0 floor(size(cueLoad,2)/1.5) floor(size(cueLoad,1)/1.5)], [0 0 screenInfo.screenRect(3)/2 screenInfo.screenRect(4)/2]);
                    case 2
                        smallIm = CenterRect([0 0 floor(size(cueLoad,2)/1.5) floor(size(cueLoad,1)/1.5)], [screenInfo.screenRect(3)/2 0 screenInfo.screenRect(3) screenInfo.screenRect(4)/2]);
                    case 3
                        smallIm = CenterRect([0 0 floor(size(cueLoad,2)/1.5) floor(size(cueLoad,1)/1.5)], [0 screenInfo.screenRect(4)/2 screenInfo.screenRect(3)/2 screenInfo.screenRect(4)]);
                    case 4
                        smallIm = CenterRect([0 0 floor(size(cueLoad,2)/1.5) floor(size(cueLoad,1)/1.5)], [screenInfo.screenRect(3)/2 screenInfo.screenRect(4)/2 screenInfo.screenRect(3) screenInfo.screenRect(4)]);
                end
                if ismember(indAtt, dotInfo.AttCues{indBlock,1})
                    Screen('DrawTexture', screenInfo.curWindow, cue2Disp, [], smallIm); % draw the object
                end;
            end
            oldTextSize = Screen('TextSize', screenInfo.curWindow, 30);
            DrawFormattedText(screenInfo.curWindow, ['relevante Attribute: ', num2str(dotInfo.StateOrder(indBlock,1))], 'center', 'center');
            Screen('TextSize', screenInfo.curWindow, oldTextSize); clear oldTextSize;
            BlockInitiation = Screen('Flip', screenInfo.curWindow);
            ExperimentProtocol = [ExperimentProtocol; {'BlockInitiation'}, {BlockInitiation}, {[]}, {[]}, {[]}, {indBlock}, {[]}, {[]}];
            pause(dotInfo.durBlockOnset);
          
          for indTrial = 1:dotInfo.blockLengthDim
                fprintf('Block %i of %i; Trial %i of %i\n', [indBlock, dotInfo.blockAmount, indTrial, dotInfo.blockLengthDim])
                TrialInitiation = GetSecs;
                ExperimentProtocol = [ExperimentProtocol; {'TrialInitiation'}, {TrialInitiation}, {[]}, {[]}, {[]}, {indBlock}, {indTrial}, {[]}];
                % create fixation
                targets = makeDotTargets(screenInfo, dotInfo); % initialize targets
                %showTargets(screenInfo, targets, 1);
                [~, dotInfo, ExperimentProtocol,ResultMat,DisplayInfo] = dotsX_JQK_MAT_170809(screenInfo, dotInfo, targets, indBlock, indTrial, ExperimentProtocol,ResultMat,DisplayInfo);
          end % trial presentation
      
          % take a break when specified
            if ismember(indTrial, dotInfo.PauseAfterBlocks)
Julian Kosciessa's avatar
Julian Kosciessa committed
                PauseStart = GetSecs();
Julian Kosciessa's avatar
Julian Kosciessa committed
                ExperimentProtocol = [ExperimentProtocol; {'PauseStart'}, {PauseStart}, {[]}, {[]}, {[]}, {indBlock}, {indTrial}, {[]}];
Julian Kosciessa's avatar
Julian Kosciessa committed
                while (GetSecs()-PauseStart) < dotInfo.breakTime
                    % have the subject get ready for the next condition
                    pause(.1);
                    remain = dotInfo.breakTime-round(GetSecs - PauseStart,0);
                    DrawFormattedText(screenInfo.curWindow, ['Pause: continue in ',num2str(remain),' s'], 'center', 'center');
                    Screen('Flip', screenInfo.curWindow);
                end
            end
Julian Kosciessa's avatar
Julian Kosciessa committed
          
      end % block presentation
          
Julian Kosciessa's avatar
Julian Kosciessa committed
      sessEndTime = GetSecs;
Julian Kosciessa's avatar
Julian Kosciessa committed
      ExperimentProtocol = [ExperimentProtocol; {'SessionEnd'}, {sessEndTime}, {[]}, {[]}, {[]}, {[]}, {[]}, {[]}];
Julian Kosciessa's avatar
Julian Kosciessa committed

      save(sessionFile, 'ExperimentProtocol', 'dotInfo', 'ResultMat', 'DisplayInfo');
Julian Kosciessa's avatar
Julian Kosciessa committed

    % inform the subject that the experiment is over
    DrawFormattedText(screenInfo.curWindow, 'task complete!', 'center', 'center');
    Screen('Flip', screenInfo.curWindow);
Julian Kosciessa's avatar
Julian Kosciessa committed
    disp('Experimenter input required: MAT complete --> presentation offset');
Julian Kosciessa's avatar
Julian Kosciessa committed

%     sessTime = GetSecs - sessStartTime;
%     meanFixTime = mean([trialData.fixTime]);
%     numCorrect = numel(find([trialData.correct]));
%     numTrial = numel([trialData.correct]);
%     numResponded = numel(find(~isnan([trialData.rxtime])));
%   
%     fprintf('\nTotal Time: %.2f\n', sessTime) % incl. block startup waits
%     fprintf('Average fixation: %.2fs\n', meanFixTime)
%     fprintf('Responded: %i/%i\n', numResponded, numTrial)
%     fprintf('Correct: %i/%i\n', numCorrect, numTrial)
%     fprintf('Accuracy: %.1f\n', 100*numCorrect/numResponded)

    % wait for experimenter to close screen
    while true
Julian Kosciessa's avatar
Julian Kosciessa committed
      [exitKeyPressed, resumeKeyPressed] = checkKeys_byKeyB(dotInfo, screenInfo.keyboard_exp);
Julian Kosciessa's avatar
Julian Kosciessa committed
      if exitKeyPressed || resumeKeyPressed
        break
      end
    end

  catch exception
    getReport(exception) % show stack trace
    save(sessionFile);
Julian Kosciessa's avatar
Julian Kosciessa committed
  end

  closeExperiment; % close drawing canvas
  Screen('Preference', 'Verbosity', oldVerbosityLevel); % restore verbosity

end