Commit 5ad83a85 authored by Julian Kosciessa's avatar Julian Kosciessa
Browse files

Commit 170707

parents
This diff is collapsed.
%_______________________________________________________________________
%
% Run random dot motion experiment defined in createDotInfo
%_______________________________________________________________________
%
% Input
%
% dotInfo | experiment configuration (struct)
% subj | identifier of subject (string)
% condSet | conditions (cell array of strings)
%_______________________________________________________________________
%
function [thresholds] = MAT_practice_170704(dotInfo, subj, DEBUG, opacity, P)
%%
%% 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');
displayIdx = displayList(1);
KbName('UnifyKeyNames'); % use portable key naming scheme
oldVerbosityLevel = Screen('Preference', 'Verbosity', 2); % show errors and warnings
arrowKeys = [dotInfo.keyLeft dotInfo.keyRight];
baseDotInfo = dotInfo; % keep for saving later
if DEBUG == 1
Screen('Preference', 'SkipSyncTests', 1);
PsychDebugWindowConfiguration(0, opacity);
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
ResultMat = [];
ExperimentProtocol = cell(0);
ExperimentProtocol = [ExperimentProtocol; {'SessionOnset'}, {GetSecs}, {[]}, {[]}, {[]}, {NaN}, {[]}];
%% Intro slide
DrawFormattedText(screenInfo.curWindow, '\nWillkommen bei der Multi-Attribut Aufgabe\n\nIm folgenden werden Sie Punktewolken sehen, die verschiedene Charakteristika aufweisen: \n\n Bewegungsrichtung \n Helligkeit \n Gre \n Farbe \n\n Im Folgenden sehen Sie ein (lngeres) Beispiel', 'center', 'center');
Screen('Flip', screenInfo.curWindow);
% wait for experimenter to resume session
while true
[exitSession, resumeSession] = checkKeys(dotInfo);
if resumeSession
break
elseif exitSession
closeExperiment;
return
end
end
%% Show first 5 second example
dotInfo.durCue = 0; % duration of cue
dotInfo.durPres = 5; % duration of presentation
dotInfo.durResp = 0; % duration of question
dotInfo.durConf = 0; % duration of confidence
dotInfo.MAT.percAtt1H = .65;
dotInfo.MAT.percAtt1L = 1-dotInfo.MAT.percAtt1H;
dotInfo.MAT.percAtt2H = .65;
dotInfo.MAT.percAtt2L = 1-dotInfo.MAT.percAtt2H;
dotInfo.MAT.percAtt3H = .65;
dotInfo.MAT.percAtt3L = 1-dotInfo.MAT.percAtt3H;
dotInfo.MAT.percAtt4H = .65;
dotInfo.MAT.percAtt4L = 1-dotInfo.MAT.percAtt4H;
dotInfo.MAT.color = [255 255 255; 255 0 0];
dotInfo.MAT.coherence = 1; % define dot movement (coherence) [useless now!]
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'};
TrialInitiation = GetSecs;
ExperimentProtocol = [ExperimentProtocol; {'TrialInitiation'}, {TrialInitiation}, {[]}, {[]}, {[]}, {0}, {[]}];
targets = makeDotTargets(screenInfo, dotInfo); % initialize fixation targets
showTargets(screenInfo, targets, 1);
DisplayInfo.CombPositionByTrial = [];
DisplayInfo.CombSamples = [];
[~, dotInfo, ExperimentProtocol,ResultMat,DisplayInfo] = dotsX_JQK_MAT_170704(screenInfo, dotInfo, targets, 1, ExperimentProtocol,ResultMat,DisplayInfo);
%% Instruction
DrawFormattedText(screenInfo.curWindow, 'Nun sehen Sie die Attribute einzeln und in der spteren Anzeigedauer. \n Bitte geben Sie an, von welcher der beiden Optionen mehr vorhanden ist.', 'center', 'center');
Screen('Flip', screenInfo.curWindow);
pause(1);
% wait for experimenter to resume session
while true
[exitSession, resumeSession] = checkKeys(dotInfo);
if resumeSession
break
elseif exitSession
closeExperiment;
return
end
end
%% Instruction
DrawFormattedText(screenInfo.curWindow, 'Wir beginnen mit der Farbe. \n\n Falls die weien Punkte dominieren, drcken Sie die linke Taste. \n Falls die roten Punkte dominieren, dcken Sie die rechte Taste. \n\n Im Anschluss an Ihre Antwort erhalten Sie eine Rckmeldung.', 'center', 'center');
Screen('Flip', screenInfo.curWindow);
pause(1);
% wait for experimenter to resume session
while true
[exitSession, resumeSession] = checkKeys(dotInfo);
if resumeSession
break
elseif exitSession
closeExperiment;
return
end
end
%% 1st dimension
% intialize psi parameters
PM = PAL_AMPM_setupPM('priorAlphaRange' , P.PM.priorAlphaRange, ...
'stimRange', P.PM.stimRange, 'numtrials', P.PM.numtrials, ...
'gamma', P.PM.gamma, 'priorLambdaRange', P.PM.priorLambdaRange, ...
'marginalize', 'slope', 'marginalize', 'lambda');
% intiate parameters
indTrial = 1;
DisplayInfo.CombPositionByTrial = [];
DisplayInfo.CombSamples = [];
ResultMat = [];
% run the staircase algorithm until criterion is reached
dotInfo = [];
dotInfo = createDotInfo_TEST_170704(PM, 1);
dotInfo.deployed = true;
dotInfo.feedback = 1;
ExperimentProtocol = [ExperimentProtocol; {'TrialInitiation'}, {GetSecs}, {[]}, {[]}, {[]}, {0}, {[]}];
while ~PM.stop
% Set the difference in amount of evidence for the target feature
% to the adaptive value. Note that for the remaining attributes,
% this is meaningless, as the different options are equal anyways.
dotInfo.MAT.percAtt1H = PM.xCurrent;
dotInfo.MAT.percAtt1L = 1-dotInfo.MAT.percAtt1H;
targets = makeDotTargets(screenInfo, dotInfo); % initialize fixation targets
showTargets(screenInfo, targets, 1);
[~, dotInfo, ExperimentProtocol,ResultMat,DisplayInfo] = dotsX_JQK_MAT_170704(screenInfo, dotInfo, targets, indTrial, ExperimentProtocol,ResultMat,DisplayInfo);
% update accuracy for the staircase code
trial.resp = ResultMat(indTrial,4);
% update PM structure
PM = PAL_AMPM_updatePM(PM, trial.resp);
indTrial = indTrial+1;
end
Results{1,1} = dotInfo;
Results{2,1} = ExperimentProtocol;
Results{3,1} = ResultMat;
Results{4,1} = PM;
Results{5,1} = DisplayInfo;
% estimate threshold
thresholds.color = PM.threshold(end);
%dotInfo.MAT.color75 = PM.PF([PM.threshold(end) 10.^PM.slope(end) PM.priorGammaRange PM.priorLambdaRange],75/100, 'Inverse');
%% Instruction
DrawFormattedText(screenInfo.curWindow, 'Als nchstes die Bewegungsrichtung. \n\n Falls die Bewegung nach links dominiert, drcken Sie die linke Taste. \n Falls die Bewegung nach rechts dominiert, dcken Sie die rechte Taste.', 'center', 'center', [255 255 255]);
Screen('Flip', screenInfo.curWindow);
pause(1);
% wait for experimenter to resume session
while true
[exitSession, resumeSession] = checkKeys(dotInfo);
if resumeSession
break
elseif exitSession
closeExperiment;
return
end
end
%% 2nd dimension
% intialize psi parameters
PM = PAL_AMPM_setupPM('priorAlphaRange' , P.PM.priorAlphaRange, ...
'stimRange', P.PM.stimRange, 'numtrials', P.PM.numtrials, ...
'gamma', P.PM.gamma, 'priorLambdaRange', P.PM.priorLambdaRange, ...
'marginalize', 'slope', 'marginalize', 'lambda');
% intiate parameters
indTrial = 1;
DisplayInfo.CombPositionByTrial = [];
DisplayInfo.CombSamples = [];
ResultMat = [];
% run the staircase algorithm until criterion is reached
dotInfo = [];
dotInfo = createDotInfo_TEST_170704(PM, 2);
dotInfo.deployed = true;
dotInfo.feedback = 1;
ExperimentProtocol = [ExperimentProtocol; {'TrialInitiation'}, {GetSecs}, {[]}, {[]}, {[]}, {0}, {[]}];
while ~PM.stop
dotInfo.MAT.percAtt2H = PM.xCurrent;
dotInfo.MAT.percAtt2L = 1-dotInfo.MAT.percAtt2H;
targets = makeDotTargets(screenInfo, dotInfo); % initialize fixation targets
showTargets(screenInfo, targets, 1);
[~, dotInfo, ExperimentProtocol,ResultMat,DisplayInfo] = dotsX_JQK_MAT_170704(screenInfo, dotInfo, targets, indTrial, ExperimentProtocol,ResultMat,DisplayInfo);
% update accuracy for the staircase code
trial.resp = ResultMat(indTrial,4);
% update PM structure
PM = PAL_AMPM_updatePM(PM, trial.resp);
indTrial = indTrial+1;
end
Results{1,2} = dotInfo;
Results{2,2} = ExperimentProtocol;
Results{3,2} = ResultMat;
Results{4,2} = PM;
Results{5,2} = DisplayInfo;
% estimate threshold
thresholds.direction = PM.threshold(end);
%% Instruction
DrawFormattedText(screenInfo.curWindow, 'Als nchstes die Punktgre. \n\n Falls die kleineren Punkte dominieren, drcken Sie die linke Taste. \n Falls die greren Punkte dominieren, dcken Sie die rechte Taste.', 'center', 'center', [255 255 255]);
Screen('Flip', screenInfo.curWindow);
pause(1);
% wait for experimenter to resume session
while true
[exitSession, resumeSession] = checkKeys(dotInfo);
if resumeSession
break
elseif exitSession
closeExperiment;
return
end
end
%% 3rd dimension
% intialize psi parameters
PM = PAL_AMPM_setupPM('priorAlphaRange' , P.PM.priorAlphaRange, ...
'stimRange', P.PM.stimRange, 'numtrials', P.PM.numtrials, ...
'gamma', P.PM.gamma, 'priorLambdaRange', P.PM.priorLambdaRange, ...
'marginalize', 'slope', 'marginalize', 'lambda');
% intiate parameters
indTrial = 1;
DisplayInfo.CombPositionByTrial = [];
DisplayInfo.CombSamples = [];
ResultMat = [];
% run the staircase algorithm until criterion is reached
dotInfo = [];
dotInfo = createDotInfo_TEST_170704(PM, 3);
dotInfo.deployed = true;
dotInfo.feedback = 1;
ExperimentProtocol = [ExperimentProtocol; {'TrialInitiation'}, {GetSecs}, {[]}, {[]}, {[]}, {0}, {[]}];
while ~PM.stop
dotInfo.MAT.percAtt3H = PM.xCurrent;
dotInfo.MAT.percAtt3L = 1-dotInfo.MAT.percAtt3H;
targets = makeDotTargets(screenInfo, dotInfo); % initialize fixation targets
showTargets(screenInfo, targets, 1);
[~, dotInfo, ExperimentProtocol,ResultMat,DisplayInfo] = dotsX_JQK_MAT_170704(screenInfo, dotInfo, targets, indTrial, ExperimentProtocol,ResultMat,DisplayInfo);
% update accuracy for the staircase code
trial.resp = ResultMat(indTrial,4);
% update PM structure
PM = PAL_AMPM_updatePM(PM, trial.resp);
indTrial = indTrial+1;
end
Results{1,3} = dotInfo;
Results{2,3} = ExperimentProtocol;
Results{3,3} = ResultMat;
Results{4,3} = PM;
Results{5,3} = DisplayInfo;
% estimate threshold
thresholds.size = PM.threshold(end);
%% Instruction
DrawFormattedText(screenInfo.curWindow, 'Als letztes die Punkthelligkeit. \n\n Falls die dunkleren Punkte dominieren, drcken Sie die linke Taste. \n Falls die helleren Punkte dominieren, dcken Sie die rechte Taste.', 'center', 'center', [255 255 255]);
Screen('Flip', screenInfo.curWindow);
pause(1);
% wait for experimenter to resume session
while true
[exitSession, resumeSession] = checkKeys(dotInfo);
if resumeSession
break
elseif exitSession
closeExperiment;
return
end
end
%% 4th dimension
% intialize psi parameters
PM = PAL_AMPM_setupPM('priorAlphaRange' , P.PM.priorAlphaRange, ...
'stimRange', P.PM.stimRange, 'numtrials', P.PM.numtrials, ...
'gamma', P.PM.gamma, 'priorLambdaRange', P.PM.priorLambdaRange, ...
'marginalize', 'slope', 'marginalize', 'lambda');
% intiate parameters
indTrial = 1;
DisplayInfo.CombPositionByTrial = [];
DisplayInfo.CombSamples = [];
ResultMat = [];
% run the staircase algorithm until criterion is reached
dotInfo = [];
dotInfo = createDotInfo_TEST_170704(PM, 4);
dotInfo.deployed = true;
dotInfo.feedback = 1;
ExperimentProtocol = [ExperimentProtocol; {'TrialInitiation'}, {GetSecs}, {[]}, {[]}, {[]}, {0}, {[]}];
while ~PM.stop
dotInfo.MAT.percAtt4H = PM.xCurrent;
dotInfo.MAT.percAtt4L = 1-dotInfo.MAT.percAtt4H;
targets = makeDotTargets(screenInfo, dotInfo); % initialize fixation targets
showTargets(screenInfo, targets, 1);
[~, dotInfo, ExperimentProtocol,ResultMat,DisplayInfo] = dotsX_JQK_MAT_170704(screenInfo, dotInfo, targets, indTrial, ExperimentProtocol,ResultMat,DisplayInfo); % update accuracy for the staircase code
trial.resp = ResultMat(indTrial,4);
% update PM structure
PM = PAL_AMPM_updatePM(PM, trial.resp);
indTrial = indTrial+1;
end
Results{1,4} = dotInfo;
Results{2,4} = ExperimentProtocol;
Results{3,4} = ResultMat;
Results{4,4} = PM;
Results{5,4} = DisplayInfo;
% estimate threshold
thresholds.luminance = PM.threshold(end);
%% Instruction
DrawFormattedText(screenInfo.curWindow, 'Nun kennen Sie alle Attribute. \n Diese werden Ihnen im Folgenden gemeinsam prsentiert. \n Bitte geben Sie wie oben immer an, welche der beiden Optionen eines Attributs den Eindruck dominiert. \n Das relevante Attribut wird Ihnen dabei nach der Prsentation prsentiert.', 'center', 'center', [255 255 255]);
Screen('Flip', screenInfo.curWindow);
pause(1);
% wait for experimenter to resume session
while true
[exitSession, resumeSession] = checkKeys(dotInfo);
if resumeSession
break
elseif exitSession
closeExperiment;
return
end
end
%% realistic without cue
dotInfo = createDotInfo_JQK_170704(thresholds); dotInfo.deployed = true;
dotInfo.totalTrials = 10;
dotInfo.durCue = 0; % duration of cue
dotInfo.feedback = 1;
dotInfo.durConf = 0;
ExperimentProtocol = [ExperimentProtocol; {'TrialInitiation'}, {GetSecs}, {[]}, {[]}, {[]}, {0}, {[]}];
for indTrial = 1:dotInfo.totalTrials
targets = makeDotTargets(screenInfo, dotInfo); % initialize fixation targets
showTargets(screenInfo, targets, 1);
[~, dotInfo, ExperimentProtocol,ResultMat,DisplayInfo] = dotsX_JQK_MAT_170704(screenInfo, dotInfo, targets, indTrial, ExperimentProtocol,ResultMat,DisplayInfo);
end
Results{1,5} = dotInfo;
Results{2,5} = ExperimentProtocol;
Results{3,5} = ResultMat;
Results{5,5} = DisplayInfo;
%% Instruction 1
DrawFormattedText(screenInfo.curWindow, 'Whrend mancher Trials werden Sie vorher erfahren, welches Attribut abgefragt wird. \n Falls ein "?" erscheint, kann wie gerade eben jedes Attribut abgefragt werden. \n Diese Information erscheint in blau. \n Sie werden nun nicht mehr erfahren, ob Ihre Antworten korrekt waren.', 'center', 'center', [255 255 255]);
Screen('Flip', screenInfo.curWindow);
pause(1);
% wait for experimenter to resume session
while true
[exitSession, resumeSession] = checkKeys(dotInfo);
if resumeSession
break
elseif exitSession
closeExperiment;
return
end
end
%% Instruction 2
DrawFormattedText(screenInfo.curWindow, 'Zudem bitten wir Sie im Anschluss um eine Einschtzung, wie sicher Sie sich bei der Entscheidung sind. \n Bitte drcken Sie dann die linke Taste, falls sie sich eher unsicher sind. \n Bitte drcken Sie dann die rechte Taste, falls sie sich eher sicher sind.', 'center', 'center', [255 255 255]);
Screen('Flip', screenInfo.curWindow);
pause(1);
% wait for experimenter to resume session
while true
[exitSession, resumeSession] = checkKeys(dotInfo);
if resumeSession
break
elseif exitSession
closeExperiment;
return
end
end
%% realistic with cue
dotInfo = createDotInfo_JQK_170704(thresholds); dotInfo.deployed = true;
dotInfo.totalTrials = 10;
ExperimentProtocol = [ExperimentProtocol; {'TrialInitiation'}, {GetSecs}, {[]}, {[]}, {[]}, {0}, {[]}];
for indTrial = 1:dotInfo.totalTrials
targets = makeDotTargets(screenInfo, dotInfo); % initialize fixation targets
showTargets(screenInfo, targets, 1);
[~, dotInfo, ExperimentProtocol,ResultMat,DisplayInfo] = dotsX_JQK_MAT_170704(screenInfo, dotInfo, targets, indTrial, ExperimentProtocol,ResultMat,DisplayInfo);
end
Results{1,6} = dotInfo;
Results{2,6} = ExperimentProtocol;
Results{3,6} = ResultMat;
Results{5,6} = DisplayInfo;
save(sessionFile, 'Results', 'thresholds');
%% inform the subject that the experiment is over
DrawFormattedText(screenInfo.curWindow, 'Sie haben das Training erfolgreich beendet!', 'center', 'center', [255 255 255]);
Screen('Flip', screenInfo.curWindow);
pause(1);
%% plot threshold data for threshold optimization of MAT task
h = figure;
subplot(3,1,1);
plot(Results{4,1}.threshold)
hold on; plot(Results{4,2}.threshold)
hold on; plot(Results{4,3}.threshold)
hold on; plot(Results{4,4}.threshold)
ylim([.5 .8]), xlim([1 Results{4,1}.numTrials])
title('Threshold estimates');
legend({'Color'; 'Direction'; 'Size'; 'Luminance'});
subplot(3,1,2);
plot(Results{4,1}.x)
hold on; plot(Results{4,2}.x)
hold on; plot(Results{4,3}.x)
hold on; plot(Results{4,4}.x)
ylim([.5 .8]), xlim([1 Results{4,1}.numTrials])
title('Presented values');
legend({'Color'; 'Direction'; 'Size'; 'Luminance'});
subplot(3,1,3);
plot(Results{4,1}.response)
hold on; plot(Results{4,2}.response)
hold on; plot(Results{4,3}.response)
hold on; plot(Results{4,4}.response)
ylim([0 1]), xlim([1 Results{4,1}.numTrials])
title('Accuracy');
legend({'Color'; 'Direction'; 'Size'; 'Luminance'});
% Maybe this should be saved as output? Then again, we can always
% reproduce it.
%% wait for experimenter to close screen
while true
[exitKeyPressed, resumeKeyPressed] = checkKeys(dotInfo);
if exitKeyPressed || resumeKeyPressed
break
end
end
catch exception
getReport(exception) % show stack trace
end
closeExperiment; % close drawing canvas
Screen('Preference', 'Verbosity', oldVerbosityLevel); % restore verbosity
end
%_______________________________________________________________________
%
% Run random dot motion experiment defined in createDotInfo
%_______________________________________________________________________
%
% Input
%
% dotInfo | experiment configuration (struct)
% subj | identifier of subject (string)
% condSet | conditions (cell array of strings)
%_______________________________________________________________________
%
function MAT_practice_CompleteOnly_170704_WIP(dotInfo, subj, test, DEBUG, opacity, P)
%%
%% 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 = ['dotsX_behav_' subj '_' datestr(now, 'dd-mm-yyyy_HH-MM')];
sessionFile = [dotInfo.dataDir, sessionFile, '_PRACTICE.mat'];
%%
%% prepare presentation
%%
displayList = Screen('screens');
displayIdx = displayList(1);
KbName('UnifyKeyNames'); % use portable key naming scheme
oldVerbosityLevel = Screen('Preference', 'Verbosity', 2); % show errors and warnings
arrowKeys = [dotInfo.keyLeft dotInfo.keyRight];
baseDotInfo = dotInfo; % keep for saving later
if DEBUG == 1