diff --git a/FearGen_BDNF_eyelab.m b/FearGen_BDNF_eyelab.m deleted file mode 100644 index c109935..0000000 --- a/FearGen_BDNF_eyelab.m +++ /dev/null @@ -1,1111 +0,0 @@ -function [p]=FearGen_BDNF_eyelab(subject,phase,csp,PainThreshold) -%[p]=Conditioning(subject,NthSeq,CSpface,phase,PainThreshold) -% -%Used for the last recording (3rd Scan Request) sessions of the Feargen -%project. Mainly different in loading the precomputed sequences... -% -% - -if nargin ~= 4 - fprintf('Wrong number of inputs\n'); - keyboard; -end - -csn = mod( csp + 8/2-1, 8)+1; -ListenChar(2);%disable pressed keys to be spitted around -commandwindow; -%clear everything -clear mex global functions -cgshut; -global cogent; -%%%%%%%%%%%load the GETSECS mex files so call them at least once -GetSecs; -WaitSecs(0.001); -% -el = []; -p = []; -SetParams; -fprintf('length: %d',length(p.presentation.cond_id)) -[p.presentation.cond_id'; p.presentation.stim_id'; p.presentation.ucs';p.presentation.oddball'] -unique(p.presentation.stim_id) -pause(5); -debug = 0;%debug mode -SetPTB; -% -%init all the variables -t = []; -nTrial = 0; -%% -%Time Storage -TimePulse1 = []; -TimePulse2 = []; -TimeStimOnset = []; -TimeCrossJumpTime = []; -TimeEndStim = []; -TimeStartShock = []; -TimeTrackerOff = []; -TimeTrackerOn = []; -TimeCrossOn = []; -p_var_ExpPhase = []; -p_var_event_count = 0; - - - -%% -InitEyeLink; -WaitSecs(2); -%calibrate if we are at the scanner computer. -%need to exclude 2, because there the ConfirmIntensity will come first. -if ( (strcmp(p.hostname,'triostim1') || strcmp(p.hostname,'etpc'))); - CalibrateEL; -end -%save again the parameter file -save(p.path.path_param,'p'); -if phase == 1 - - ShowInstruction(1,1); - -elseif phase == 2 - - - % - p_var_ExpPhase = phase; - ShowInstruction(4,1); - ConfirmIntensity; - ShowInstruction(101,1); - ShowInstruction(2,1); - ShowInstruction(3,1); - - %calibrate if we are at the scanner or ET computer. - if (phase~=2 && (strcmp(p.hostname,'triostim1') || strcmp(p.hostname,'etpc'))); - CalibrateEL; - end - - ShowInstruction(5,1);%will wait for keypresses - PresentStimuli; - AskStimRating;%make sure that scanner doesnt stop prematurely asa the stim offset - -elseif phase == 3 - % - p_mrt_on = 0; - p_var_ExpPhase = phase; - % - ShowInstruction(6,1);%will not wait for keypresses - % - PresentStimuli; - % - %makee sure that scanner doesnt stop prematurely asa the stim offset - AskStimRating; -elseif phase == 4 - p_mrt_on = 0; - p_var_ExpPhase = phase; - % - ShowInstruction(6,1);%will not wait for keypresses - PresentStimuli; - %makee sure that scanner doesnt stop prematurely asa the stim offset - AskStimRating; - %makee sure that scanner doesnt stop prematurely asa the stim offset - fprintf('Finished with the rating\n'); - %AskWhichFace; -end - -%get the eyelink file back to this computer -StopEyelink(p.path.edf); -%trim the log file and save -p.out.log = p.out.log(sum(isnan(p.out.log),2) ~= size(p.out.log,2),:); -%shift the time so that the first timestamp is equal to zero -p.out.log(:,1) = p.out.log(:,1) - p.out.log(1); -p.out.log = p.out.log;%copy it to the output variable. -save(p.path.path_param,'p'); -% -%move the file to its final location. -movefile(p.path.subject,p.path.finalsubject); -%close everything down -cleanup; - - function ConfirmIntensity - %Compute the intensity we want to deliver to the subject. - - p.var.ShockIntensity = p.out.PainThreshold*p.out.ShockFactor; - - % - ShowInstruction(9,1); - % - fprintf([repmat('=',1,50) '\n']); - fprintf('TEST SHOCK:\n'); - fprintf('!!! ADJUST THE SHOCK INTENSITY ON THE DIGITIMER !!!\n'); - fprintf(' The intensity is now: %g mA\n',p.var.ShockIntensity); - fprintf(' Experimenter: Press any key to deliver a shock.\n'); - fprintf([repmat('=',1,50) '\n']); - % - [secs, keyCode, deltaSecs] = KbStrokeWait; - ShowInstruction(10,0);%shock is coming message... - t = GetSecs + p.duration.shock; - MarkCED( p.com.lpt.address, p.com.lpt.shock ); - while GetSecs < t; - Buzz; - end - % - message = 'Bewege den "Zeiger" mit der rechten und linken Pfeiltaste\n und bestätige deine Einschätzung mit der mit der oberen Pfeiltaste.'; - rect = [p.ptb.width*0.2 p.ptb.midpoint(2) p.ptb.width*0.6 100]; - response = RatingSlider(rect,2,1,p.keys.increase,p.keys.decrease,p.keys.confirm,{ 'nicht\nerträglich' 'erträglich'},message,0); - if response == 2 - fprintf('All is fine :)\n'); - fprintf('Subject confirmed the shock intensity inside the scanner...\n') - fprintf('INTENSITY TO BE USED FOR THE MAIN EXPERIMENT: %g mA\n',p.var.ShockIntensity); - p.out.ShockIntensity = p.var.ShockIntensity; - return; - elseif response == 1 - fprintf('Shit... :(, %g is too much for the subject\n',p.var.ShockIntensity); - fprintf('We will try a little milder intensity.\n'); - p.out.ShockFactor = p.out.ShockFactor - 0.05; - ConfirmIntensity; - end - - - end - function PresentStimuli - %Enter the presentation loop and wait for the first pulse to - %arrive. - - - - - - % - - TimeEndStim = GetSecs; - for nTrial = 1:p.presentation.tTrial; - % - %Get the variables that Trial function needs. - stim_id = p.presentation.stim_id(nTrial); - % - fix = p.presentation.CrossPosition(nTrial,:); - - ISI = p.presentation.isi(nTrial); - ucs = p.presentation.ucs(nTrial); - oddball = p.presentation.oddball(nTrial); - prestimdur = p.duration.prestim+rand(1)*.25; - dist = p.presentation.dist(nTrial); - %prestimdur = p_presentation_prestim_dur(nTrial); - - - fprintf('%d of %d, S: %d, ISI: %d, UCS: %d, ODD: %d.\n',nTrial,p.presentation.tTrial,stim_id,ISI,ucs,oddball); - % - - OnsetTime = TimeEndStim + ISI-p.duration.stim ; - - % jetz = GetSecs; - % if mod(nTrial,100) == 0 - % ShowInstruction(14,1); - % OnsetTime = OnsetTime + GetSecs - jetz; - % end - - KbQueueStart(p.ptb.device);%monitor keypresses... - - %Start with the trial, here is time-wise sensitive must be - %optimal - [TimeEndStim]= Trial(nTrial,OnsetTime, prestimdur, stim_id , ucs , fix , oddball,dist); - % - [keypressed, firstPress]=KbQueueCheck(p.ptb.device); - %if the press was after stimulus onset and before stimulus - %offset - if keypressed && (firstPress(p.keys.confirm) > OnsetTime) && (firstPress(p.keys.confirm) < TimeEndStim) - p.out.response(nTrial) = 1; - Log(firstPress(p.keys.confirm),7,NaN);%log the key press for hit detection. - fprintf('Subject Pressed the Hit Key!!\n'); - end - %break loop - if (phase == 4 && (nTrial == 120 || nTrial == 240)) - ShowInstruction(14,1) - CalibrateEL; - end - p_var_ExpPhase = phase; - end - end - function [TimeEndStim]=Trial(nTrial,TimeStimOnset , prestimdur, stim_id , ucs , fix , oddball, dist ) - %get all the times - TimeCrossOnset = TimeStimOnset - prestimdur; - TimeEndStim = TimeStimOnset + p.duration.stim; - TimeStartShock = TimeStimOnset + p.duration.onset2shock; - TimeTrackerOff = TimeStimOnset + p.duration.keep_recording; - - %% Fixation Onset - FixCross = [fix(1)-1,fix(2)-20,fix(1)+1,fix(2)+20;fix(1)-20,fix(2)-1,fix(1)+20,fix(2)+1]; - Screen('FillRect', p.ptb.w, [255,255,255], FixCross'); - TimeCrossOn = Screen('Flip',p.ptb.w,TimeCrossOnset,0); - MarkCED( p.com.lpt.address, p.com.lpt.FixOnset ); - Eyelink('Message', 'FX Onset at %d %d',fix(1),fix(2)); - Log(TimeCrossOn,1,stim_id);%cross onset. - %turn the eye tracker on - StartEyelinkRecording(nTrial,stim_id,p_var_ExpPhase,dist,oddball,ucs,fix); - - - - %% Draw the stimulus to the buffer - if ~stim_id==0 - Screen('DrawTexture', p.ptb.w, p.ptb.stim_sprites(stim_id)); - end - %Screen('DrawText' , p.ptb.w, double('+'), p.ptb.CrossPosition_x,fix, p.stim.white); -% if oddball%add freckles to the face -% x = randn(1,100)*35; -% y = randn(1,100)*10; -% s = rand(1,100);%[0 1] -% Screen('DrawDots',p.ptb.w,[x;y],1+s.*1.5,[100 100 100 160],p.ptb.midpoint,1); -% %the dots size -% end - Screen('DrawingFinished',p.ptb.w,0); - - %% STIMULUS ONSET - %Here we wait only for the next pulse. - %The proper amount is obtained with the second call of WaitPulse - %below, before the onset of the fixation cross. - %fprintf('Will Wait for the pulse to Stim Onset\n'); - TimeStimOnset = Screen('Flip',p.ptb.w,TimeStimOnset,0);%asap and dont clear - %send eyelink and ced a marker asap - Eyelink('Message', 'Stim Onset'); - Eyelink('Message', 'SYNCTIME'); - MarkCED( p.com.lpt.address, p.com.lpt.StimOnset ); - if oddball - MarkCED( p.com.lpt.address, p.com.lpt.oddball ); - end - Log(TimeStimOnset,2,stim_id);%log the stimulus onset - - - if ucs == 1 - %%%%%%%%%%%%%%%%%%%%%%% - %Deliver shock and stim off immediately - TimeStartShock = WaitSecs('UntilTime',TimeStartShock); - MarkCED( p.com.lpt.address, p.com.lpt.shock ); - Eyelink('Message', 'UCS Onset'); - - while GetSecs < TimeEndStim; - Buzz;%this is anyway sent to CED. - end - Eyelink('Message', 'UCS Offset'); - end - - %% STIM OFF immediately - TimeEndStim = Screen('Flip',p.ptb.w,TimeEndStim,0); - %send eyelink and ced a marker - Eyelink('Message', 'Stim Offset'); - Eyelink('Message', 'BLANK_SCREEN'); - Screen('Textsize', p.ptb.w,p.text.fontsize); - Log(TimeEndStim,-2,stim_id);%log the stimulus offset - % - %% record some more eye data after stimulus offset. - WaitSecs('UntilTime',TimeTrackerOff); - TimeTrackerOff = StopEyelinkRecording; - - - if oddball == 1 - fprintf('This was an oddball trial!\n'); - end - if ucs == 1 - fprintf('This was a UCS trial!\n'); - Log(TimeStartShock,4,NaN);%UCS delivery...This is done here to not waste time there - end - - end - - function SetParams - - % - p.var.timings = zeros(1,10); - p_var_event_count = 0; - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %relative path to stim and experiments - %Path Business. - [~, hostname] = system('hostname'); - p.hostname = deblank(hostname); - if strcmp(p.hostname,'triostim1') - p.path.baselocation = 'C:\USER\onat\Experiments\'; - elseif strcmp(p.hostname,'etpc') - p.path.baselocation = 'C:\Users\onat\Documents\Experiments\'; - else - p.path.baselocation = 'C:\Users\Lea\Documents\Experiments\'; - end - - p.path.experiment = [p.path.baselocation 'BDNF' filesep]; - p.path.stim = 'C:\Users\Lea\Documents\Experiments\BDNF\stim\'; - p.path.stim24 = [p.path.stim '24bit8' '\']; - % - p.subID = sprintf('sub%02d',subject); - p.path.edf = sprintf([p.subID 'p%02d' ],phase); - timestamp = datestr(now,30); - p.path.subject = [p.path.experiment 'data\tmp\' p.subID '_' timestamp '\']; - p.path.finalsubject = [p.path.experiment 'data\' p.subID '_' timestamp '\' ]; - %create folder hierarchy - mkdir(p.path.subject); - mkdir([p.path.subject 'scr']); - mkdir([p.path.subject 'eye']); - mkdir([p.path.subject 'stimulation']); - mkdir([p.path.subject 'midlevel']); - p.path.path_param = sprintf([regexprep(p.path.subject,'\\','\\\') 'stimulation\\param_phase_%02d'],phase); - - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %get stim files - [p.stim.files p.stim.label] = FileMatrix([p.path.stim '*.bmp']); - p.stim.tFile = size(p.stim.files,1);%number of different files (including the UCS symbol) - p.stim.tFace = p.stim.tFile - 1;%number of faces. - % - display([mat2str(p.stim.tFile) ' found in the destination.']); - %set the background gray according to the background of the stimuli - for i = 1:p.stim.tFile; - im = imread(p.stim.files(i,:)); - bg(i) = im(1,1,1); - end - %is all the captured bg values the same? - if sum(diff(bg))==0; - %if so take it as the bg color - p.stim.bg = double([bg(1) bg(1) bg(1)]); - else - fprintf('background luminance was not successfully detected...\n') - keyboard; - end - %bg of the rating screen. - p.stim.bg_rating = [0 128 0]; - % - %font size and background gray level - p.text.fontname = 'Times New Roman'; - p.text.fontsize = 18;%30; - p.text.fixsize = 60; - %rating business - p.rating.division = 10;%number of divisions for the rating slider - p.rating.repetition = 2;%how many times a given face has to be repeated... - % - p.stim.white = [255 255 255]; - %get the actual stim size (assumes all the same) - info = imfinfo(p.stim.files(1,:)); - p.stim.width = info.Width; - p.stim.height = info.Height; - - if strcmp(p.hostname,'triostim1') - p.keys.confirm = KbName('7'); - p.keys.increase = KbName('8'); - p.keys.decrease = KbName('6'); - p.keys.space = KbName('space'); - p.keys.esc = KbName('esc'); - else - %All settings for laptop computer. - p.keys.confirm = KbName('up'); - p.keys.increase = KbName('right'); - p.keys.decrease = KbName('left'); - p.keys.space = KbName('space'); - p.keys.esc = KbName('esc'); - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %Communication business - %parallel port - p.com.lpt.address = 888; - %codes for different events - p.com.lpt.InitExperiment = 64;%which is all channels without digitimer - p.com.lpt.FixOnset = 4; - p.com.lpt.StimOnset = 8; - p.com.lpt.shock = 16; - p.com.lpt.oddball = 32; - p.com.lpt.keypress = 2; - p.com.lpt.digitimer = 128; - % - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %timing business - %these are the intervals of importance - %time2fixationcross->cross2onset->onset2shock->shock2offset - %these (duration.BLA) are average duration values: - p.duration.stim = 1.5;%2;%s - p.duration.shock = 0.1;%s;x - p.duration.shockpulse = 0.005;%ms; duration of each individual pulses - p.duration.intershockpulse = 0.01;%ms; and the time between each pulse - p.duration.onset2shock = p.duration.stim - p.duration.shock; - p.duration.crossmoves = p.duration.stim./2; - p.duration.keep_recording = 0.25;%this is the time we will keep recording (eye data) after stim offset. - p.duration.prestim_ori = .95; - %p.duration.prestim = 2-p.duration.prestim_ori;%that is 0.95 seconds - p.duration.prestim = .85; - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %stimulus sequence - seqpool = load('C:\Users\onat\Documents\Experiments\BDNF\seq\seq.mat'); - seq = seqpool.s(phase,csp,RandSample(1:size(seqpool.s,3),[1 1])); - clear seqpool -% if phase == 2 -% seq = seq_feargen_cloudseq(csp,'baseline');%only 1 short seq -% elseif phase == 3%conditioning -% seq = seq_feargen_cloudseq(csp,'cond');%gets 1 short seq -% elseif phase == 4 -% seq = seq_feargen_cloudseq(csp,'test');%gets 2 short seqs -% end - %create the randomized design - p.stim.cs_plus = csp;%index of cs stimulus, this is the one paired to shock - p.stim.cs_neg = csn; - %Record which Phase are we going to run in this run. - p.stim.phase = phase; - %this will deal all the presentation sequence related information - p.presentation = seq; - - p.out.rating = []; - p.out.log = zeros(1000000,4).*NaN; - p.out.response = zeros(p.presentation.tTrial,1); - p.out.PainThreshold = PainThreshold; - p.out.ShockFactor = 2; - %Save the stuff - save(p.path.path_param,'p'); - % - function [FM labels] = FileMatrix(path) - %Takes a path with file extension associated to regexp (e.g. - %C:\blabl\bla\*.bmp) returns the file matrix - dummy = dir(path); - FM = [repmat([fileparts(path) filesep],length(dummy),1) vertcat(dummy(:).name)]; - labels = {dummy(:).name}; - end - end - function AskStimRating - - MarkCED( p.com.lpt.address, p.com.lpt.InitExperiment); - % - p_var_ExpPhase = 5; - BG = p.stim.bg;% - p.stim.bg = p.stim.bg_rating; - nseq = 0; - rating_seq = []; - pos1_seq = []; - % - while nseq < p.rating.repetition - nseq = nseq + 1; - rating_seq = [ rating_seq Shuffle(1:p.stim.tFile-2)']; - end - message = GetText(11); - SliderTextL = GetText(13); - SliderTextR = GetText(12); - % - Screen('FillRect', p.ptb.w , p.stim.bg); - Screen('Flip',p.ptb.w); - WaitSecs(2); - % - ShowInstruction(7,1); - rect = [p.ptb.width*0.2 p.ptb.midpoint(2) p.ptb.width*0.6 100]; - tRatend = length(rating_seq); - %save the rating sequence just for security - p.out.rating_seq = rating_seq; - - for nRatend = 1:tRatend; - % - %the variable that are used by Trial function - stim_id = rating_seq(nRatend); - - fix = p.presentation.CrossPosition(nRatend,:); - % - next_stim_id = [];%this is a trick, otherwise a fixation cross appears right before the rating :( - next_pos1 = []; - - %to send know the distance here, little dummy setup: - dummy = -135:45:180; - dist = dummy(stim_id); - %We will turn on the fixation cross and start the tracker - %for the first trial. These have to be done before the main - %for loop. - FixCross = [fix(1)-1,fix(2)-20,fix(1)+1,fix(2)+20;fix(1)-20,fix(2)-1,fix(1)+20,fix(2)+1]; - Screen('FillRect', p.ptb.w, [255,255,255], FixCross'); - t = Screen('Flip',p.ptb.w); - Screen('Textsize', p.ptb.w,p.text.fontsize); - % - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %Mark the onset - Eyelink('Message', 'FX Onset at %d %d',fix(1),fix(2)); - Log(t,1,fix(1));%log the mark onset... - Log(t,1,fix(2)) - - % - Trial(1000+nRatend,GetSecs+1,0.5,stim_id,0,fix,0,dist); - rate(nRatend,1) = RatingSlider(rect, p.rating.division, Shuffle(1:p.rating.division,1), p.keys.increase, p.keys.decrease, p.keys.confirm, {SliderTextL{1} SliderTextR{1}},message,1); - - %%%%%%%%%%%%%%%%%%%%%%%%%%%% - %Verbose the rating of the subject - fprintf('============\nRating Results %d (%d/%d):\n', stim_id, nRatend, tRatend); - dummy = rating_seq(1:nRatend);%trials shown so far - for iii = 1:p.stim.tFile-2 - r = round(mean(rate(dummy == iii))); - if isnan(r) - r = 0; - end - if iii == p.stim.cs_plus - fprintf('Stimulus %02d: * %s \n',iii,repmat('+',1,1+r)); - else - fprintf('Stimulus %02d: %s \n',iii,repmat('+',1,1+r)); - end - end - end - %sort the stim_ids and then sort the same the rates and make a - %matrix out of that to store - [~, i] = sort(rating_seq); - rate = reshape(rate(i),p.rating.repetition,p.stim.tFile-2)'; - p.out.rating = rate; - save(p.path.path_param,'p'); - Screen('FillRect',p.ptb.w,p.stim.bg); - p.stim.bg = BG; - % - save(p.path.path_param,'p'); - end - function [rating] = RatingSlider(rect,tSection,position,up,down,confirm,labels,message,numbersOn) - % - %Detect the bounding boxes of the labels. - for nlab = 1:2 - [~ , ~, bb(nlab,:)]=DrawFormattedText(p.ptb.w,labels{nlab}, 'center', 'center', p.stim.white,[],[],[],2); - Screen('FillRect',p.ptb.w,p.stim.bg); - end - bb = max(bb); - bb_size = bb(3)-bb(1);%vertical size of the bb. - % - DrawSkala; - ok = 1; - while ok == 1 - [secs, keyCode, ~] = KbStrokeWait; - keyCode = find(keyCode); - Log(secs,7,keyCode); - if length(keyCode) == 1%this loop avoids crashes to accidential presses of meta keys - if (keyCode == up) || (keyCode == down) - next = position + increment(keyCode); - if next < (tSection+1) && next > 0 - position = position + increment(keyCode); - %rating = tSection - position + 1; - end - DrawSkala; - elseif keyCode == confirm - MarkCED( p.com.lpt.address, p.com.lpt.keypress); - WaitSecs(0.1); - ok = 0; - Screen('FillRect',p.ptb.w,p.stim.bg); - t=Screen('Flip',p.ptb.w); - end - end - end - - function DrawSkala - %rating = tSection - position + 1; - rating = position ; - increment([up down]) = [1 -1];%delta - tick_x = linspace(rect(1),rect(1)+rect(3),tSection+1);%tick positions - tick_size = rect(3)./tSection; - ss = tick_size/5*0.9;%slider size. - % - for tick = 1:length(tick_x)%draw ticks - Screen('DrawLine', p.ptb.w, [255 0 0], tick_x(tick), rect(2), tick_x(tick), rect(2)+rect(4) , 3); - if tick <= tSection && numbersOn - Screen('TextSize', p.ptb.w,p.text.fontsize./2); - DrawFormattedText(p.ptb.w, mat2str(tick) , tick_x(tick)+ss/2, rect(2)+rect(4), p.stim.white); - Screen('TextSize', p.ptb.w,p.text.fontsize); - end - if tick == 1 - DrawFormattedText(p.ptb.w, labels{1},tick_x(tick)-bb_size*1.4,rect(2), p.stim.white); - elseif tick == tSection+1 - DrawFormattedText(p.ptb.w, labels{2},tick_x(tick)+bb_size*0.4,rect(2), p.stim.white); - end - end - %slider coordinates - slider = [ tick_x(position)+tick_size*0.1 rect(2) tick_x(position)+tick_size*0.9 rect(2)+rect(4)]; - %draw the slider - Screen('FillRect',p.ptb.w, p.stim.white, round(slider)); - Screen('TextSize', p.ptb.w,p.text.fontsize./2); - DrawFormattedText(p.ptb.w,message, 'center', p.ptb.midpoint(2)*0.2, p.stim.white,[],[],[],2); - Screen('TextSize', p.ptb.w,p.text.fontsize); - t = Screen('Flip',p.ptb.w); - Log(t,6,NaN); - end - end - function ShowInstruction(nInstruct,waitforkeypress) - %ShowInstruction(nInstruct,waitforkeypress) - %if waitforkeypress is 1, then subject has to press a button to - %make the instruction text dissappear. Otherwise you have to take - %care of it later - - [text]= GetText(nInstruct); - ShowText(text); - %let subject read it and ask confirmation to proceed. But we don't - %need that in the case of INSTRUCT = 5; - if waitforkeypress - if nInstruct ~= 10%this is for the Reiz kommnt - KbStrokeWait; - else - WaitSecs(2.5+rand(1)); - end - Screen('FillRect',p.ptb.w,p.stim.bg); - t = Screen('Flip',p.ptb.w); - Log(t,-5,nInstruct); - else - if nInstruct ~= 10%this is for the Reiz kommnt - KbStrokeWait; - else - WaitSecs(1+rand(1)); - end - end - - - function ShowText(text) - - Screen('FillRect',p.ptb.w,p.stim.bg); - %DrawFormattedText(p.ptb.w, text, p.text.start_x, 'center',p.stim.white,[],[],[],2,[]); - DrawFormattedText(p.ptb.w, text, 'center', 'center',p.stim.white,[],[],[],2,[]); - t=Screen('Flip',p.ptb.w); - Log(t,5,nInstruct); - %show the messages at the experimenter screen - fprintf('=========================================================\n'); - fprintf('Text shown to the subject:\n'); - fprintf('=========================================================\n'); - fprintf(text); - fprintf('=========================================================\n'); - - end - end - function [text]=GetText(nInstruct) - if nInstruct == 0%Eyetracking calibration - - text = ['Um Ihre Augenbewegungen zu messen, \n' ... - 'müssen wir jetzt den Eye-Tracker kalibrieren.\n' ... - 'Dazu zeigen wir Ihnen einige Punkte auf dem Bildschirm, \n' ... - 'bei denen Sie sich wie folgt verhalten:\n' ... - 'Bitte fixieren Sie den kleinen weißen Kreis und \n' ... - 'bleiben so lange darauf, wie es zu sehen ist.\n' ... - 'Bitte drücken Sie jetzt den oberen Knopf, \n' ... - 'um mit der Kalibrierung weiterzumachen.\n' ... - ]; - - elseif nInstruct == 1%first Instr. of the training phase. - text = ['Wir werden nun als erstes einen Übungsdurchgang machen,\n' ... - 'damit Sie sich an Ihre Aufgabe gewöhnen können.\n' ... - 'In diesem Durchgang können Sie sich vollkommen sicher fühlen,\n' ... - 'es werden keine elektrischen Reize verabreicht.\n' ... - 'Eine wichtige grundsätzliche Regel ist, dass Sie das Fixationskreuz (das „+“)\n' ... - 'wenn es zu sehen ist, mit Ihren Augen fixieren. \n' ... - 'Drücken Sie die obere Taste um fortzufahren.\n' ... - ]; - elseif nInstruct == 101%first Instr. of the training phase. - text = ['Eine wichtige grundsätzliche Regel ist,\n'... - 'dass Sie das Fixationskreuz (das „+“)\n' ... - 'immer wenn es zu sehen ist, mit Ihren Augen fixieren. \n' ... - 'Drücken Sie die obere Taste um fortzufahren.\n' ... - ]; - elseif nInstruct == 2%second Instr. of the training phase. - text = ['Ein paar Bemerkungen zu den Zielreizen: \n' ... - 'Zur Erinnerung: Zielreize sind die verschwommenen Gesichter.\n' ... - 'Sobald ein solcher Zielreiz erscheint, \n' ... - 'sollen Sie schnellstmöglich die obere Taste drücken, \n' ... - 'und zwar bevor der Reiz wieder verschwunden ist \n' ... - '(Sie müssen also sehr schnell und aufmerksam sein).' ... - ]; - elseif nInstruct == 3%third Instr. of the training phase. - text = ['Es ist sehr wichtig, dass Sie Ihren Kopf während \n' ... - 'des Experiments nicht bewegen. \n' ... - 'Das ist besonders wichtig für die Qualität der Messung.\n' ... - ]; - elseif nInstruct == 4%third Instr. of the training phase. - text = ['Willkommen zum Experiment. \n'... - 'Vor dem Experiment legen wir nun \n' ... - 'die Schockintensität für den Rest des Experiments fest. \n' ... - 'Drücken Sie die obere Taste um fortzufahren.' ... - ]; - - elseif nInstruct == 5%Baseline Phase - % - % - %=================================================================================================================% - text = ['Jetzt geht es mit dem Experiment los.\n' ... - 'Ihre Aufgabe ist es jetzt, die Gesichter, \n' ... - 'die Ihnen gezeigt werden aufmerksam zu betrachten und \n' ... - 'den oberen Knopf zu drücken, sobald Sie einen Zielreiz sehen.\n' ... - '\n'... - 'Hin und wieder erscheint ein Symbol (ein Blitzpfeil, der vor Strom warnt), \n' ... - 'das einen elektrischen Reiz ankündigt. \n' ... - 'Die Reize erfolgen aber nur bei diesem Symbol, nicht bei den Gesichtern! \n' ... - 'Bei Gesichtern können Sie sich also sicher fühlen.\n' ... - 'Bitte denken Sie daran: 1. Fixationskreuz fixieren und 2. nicht bewegen!\n\n' ... - 'Sie können das Experiment nun durch Drücken der oberen Taste starten. \n' ... - ]; - - elseif nInstruct == 6%Test and Conditioning Phase - %=================================================================================================================% - text = ['Auch im nun folgenden Teil des Experiments \n' ... - 'sollen Sie die Gesichter aufmerksam betrachten und \n' ... - 'den oberen Knopf drücken, sobald Sie einen Zielreiz sehen. \n' ... - 'Wie im ersten Teil des Experiments sollen Sie \n' ... - 'das Fixationskreuz immer fixieren. \n' ... - 'In dieser Phase des Experiments werden Sie\n' ... - 'gelegentlich elektrische Reize bekommen.\n\n' ... - 'Die elektrischen Reize folgen jetzt auf bestimmte Gesichter. \n' ... - - ]; - - - elseif nInstruct == 7;%rating - text = ['In dieser Phase hätten wir gerne, dass Sie die Gesichter\n'... - 'im Hinblick auf folgende Frage bewerten:\n'... - '„Wie wahrscheinlich ist es, bei dem gerade gesehenen Gesicht \n'... - 'einen elektrischen Schock zu erhalten?“\n'... - 'Bewegen Sie den Zeiger mit der rechten und linken Pfeiltaste \n'... - 'und bestätigen Sie Ihre Einschätzung mit der oberen Pfeiltaste.\n'... - ]; - - elseif nInstruct == 8 %CS+ detection - text = ['Du bekommen nun eine Reihe von Gesichtern gezeigt.\n' ... - 'Bitte wählen Sie das Gesicht aus bei dem der Schock verabreicht wurde.\n'... - 'Drücken Sie die obere Taste um fortzufahren.\n'... - ]; - elseif nInstruct == 9% - %=================================================================================================================% - text = ['Bitte geben Sie an, ob die Reizstärke des folgenden Schocks\n für Sie erträglich ist.\n'... - '\n'... - 'Drücken Sie bitte die obere Taste um den Reiz zu bekommen.\n'... - ]; - - elseif nInstruct == 10%just before the shock - text = ['Reiz kommt...\n']; - elseif nInstruct == 11%this is the rating question - text = ['Wie wahrscheinlich ist es, bei dem gerade gesehenen Gesicht \n'... - 'einen elektrischen Schock zu erhalten?“\n' ... - 'Bewegen Sie den "Zeiger" mit der rechten und linken Pfeiltaste\n' ... - 'und bestätigen Sie Ihre Einschätzung mit der mit der oberen Pfeiltaste'... - ]; - elseif nInstruct == 12 %These two below are the possible responses to the question in 11 - text = {'Sehr\nwahrscheinlich'}; - elseif nInstruct == 13 - text = {'Überhaupt\nnicht\nwahrscheinlich'}; - elseif nInstruct == 14 - text = ['Bitte machen Sie eine kurze Pause.\n' ... - 'Sie können hierbei gern die Augen einen Moment schließen.\n'... - 'Drücken Sie anschließend die obere Taste um fortzufahren.\n'... - 'Wir werden dann den Eyetracker noch einmal kalibrieren.\n'... - ]; - else - text = {''}; - end - end - function SetPTB - %Sets the parameters related to the PTB toolbox. Including - %fontsizes, font names. - %Find the number of the screen to be opened - screens = Screen('Screens'); - p.ptb.screenNumber = 1;%the maximum is the second monitor - %Make everything transparent for debugging purposes. - if debug - commandwindow; - PsychDebugWindowConfiguration; - end - %Default parameters - Screen('Preference', 'SkipSyncTests', 1); - Screen('Preference', 'DefaultFontSize', p.text.fontsize); - Screen('Preference', 'DefaultFontName', p.text.fontname); - Screen('Preference', 'TextAntiAliasing',2);%enable textantialiasing high quality - Screen('Preference', 'VisualDebuglevel', 0); - Screen('Preference', 'SkipSyncTests', 1); - Screen('Preference', 'SuppressAllWarnings', 1); - %set the resolution correctly - if strcmp(p.hostname,'triostim1') - p.ptb.oldres = Screen('resolution',p.ptb.screenNumber,1280,960); - %hide the cursor - HideCursor(p.ptb.screenNumber); - elseif strcmp(p.hostname,'etpc') - p.ptb.oldres = Screen('resolution',p.ptb.screenNumber,1600,1200); - %hide the cursor - HideCursor(p.ptb.screenNumber); - end - - %Open a graphics window using PTB - p.ptb.w = Screen('OpenWindow', p.ptb.screenNumber, p.stim.bg); - Screen('BlendFunction', p.ptb.w, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - Screen('Flip',p.ptb.w);%make the bg - p.ptb.slack = Screen('GetFlipInterval',p.ptb.w)./2; - [p.ptb.width, p.ptb.height] = Screen('WindowSize', p.ptb.screenNumber); - if sum([p.ptb.width p.ptb.height] - [1280 960]) ~= 0 - fprintf('SET THE CORRECT SCREEN RESOLUTION\n'); - end - %find the mid position on the screen. - p.ptb.midpoint = [ p.ptb.width./2 p.ptb.height./2]; - p.ptb.imrect = [ p.ptb.midpoint(1)-p.stim.width/2 p.ptb.midpoint(2)-p.stim.height/2 p.stim.width p.stim.height]; - % %compute the cross position. - % [~, ny bb] = DrawFormattedText(p.ptb.w,'+','center','center'); - % p.ptb.cross_shift = [45 60];%incremental upper and lower cross positions - % p.ptb.CrossPosition_y = p.ptb.midpoint(2)%[ny-p.ptb.cross_shift(1) ny+p.ptb.cross_shift(2) ]; - p.ptb.CrossPosition_x = p.ptb.midpoint(1);%bb(1);%always the same - % %cross position for the eyetracker screen. - % p.ptb.CrossPositionET_x = [p.ptb.midpoint(1) p.ptb.midpoint(1)]; - % p.ptb.CrossPositionET_y = [p.ptb.midpoint(2)-p.ptb.cross_shift(2) p.ptb.midpoint(2)+p.ptb.cross_shift(2)]; - % %% - [nx, ny bb] = DrawFormattedText(p.ptb.w,'+','center','center'); - - - %cross position for the eyetracker screen. -% p.ptb.CrossPositionET_x = [p.ptb.midpoint(1) p.ptb.midpoint(1)]; -% p.ptb.CrossPositionET_y = [p.ptb.midpoint(2)-p.ptb.cross_shift(2) p.ptb.midpoint(2)+p.ptb.cross_shift(2)]; - %% - %priorityLevel=MaxPriority(['GetSecs'],['KbCheck'],['KbWait'],['GetClicks']); - Priority(MaxPriority(p.ptb.w)); - %this is necessary for the Eyelink calibration - InitializePsychSound(0) - %sound('Open') - Beeper(5000) - - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %set serial communication channels - IOPort('CloseAll'); - p.com.serial = IOPort('OpenSerialPort', 'COM1', 'InputBufferSize=51840000 HardwareBufferSizes=32768,32768 Terminator=0 ReceiveLatency=0.0001 BaudRate=9600 ReceiveTimeout=7'); - IOPort('ConfigureSerialPort', p.com.serial, 'BlockingBackgroundRead=1'); - %because of the BlockingBackgroundRead=1, the flush and close all - %command will wait for the next byte to arrive... - IOPort('ConfigureSerialPort', p.com.serial, 'StartBackgroundRead=2'); - IOPort('Flush', p.com.serial); - %2 is the granularity of the data, cogent box sends 2 bytes. - %IOPort('ConfigureSerialPort', p.com.serial, 'ReadTimeout=5'); - - %%%%%%%%%%%%%%%%%%%%%%%%%%%Prepare the keypress queue listening. - p.ptb.device = -1; - p.ptb.keysOfInterest=zeros(1,256); - p.ptb.keysOfInterest(p.keys.confirm) = 1; - KbQueueCreate(p.ptb.device,p.ptb.keysOfInterest);%default device. - - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %prepare parallel port communication. This relies on cogent i - %think. We could do it with PTB as well. - config_io; - outp(p.com.lpt.address,0); - if( cogent.io.status ~= 0 ) - error('inp/outp installation failed'); - end - %test whether CED receives the triggers correctly... - k = 0; - while k ~= 49; - outp(p.com.lpt.address,p.com.lpt.InitExperiment);pause(0.1);outp(p.com.lpt.address,0);%247 means all but the UCS channel (so that we dont shock the subject during initialization). - fprintf('=================\nDid the trigger test work?\nPress 0 to send it again, 1 to continue...\n') - [~, k] = KbStrokeWait; - k = find(k); - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %load the pictures to the memory. - p.ptb.stim_sprites = CreateStimSprites(p.stim.files);% - - function [out]=CreateStimSprites(files) - %loads all the stims to video memory - for nStim = 1:p.stim.tFile - filename = files(nStim,:); - [im , ~, ~] = imread(filename); - out(nStim) = Screen('MakeTexture', p.ptb.w, im ); - end - end - end - function [t]=StopEyelinkRecording - Eyelink('StopRecording'); - t = GetSecs; - %this is the end of the trial scope. - WaitSecs(0.01); - Eyelink('Message', 'TRIAL_RESULT 0'); - % - WaitSecs(0.01); - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('Command', 'clear_screen %d', 0); - Screen('Textsize', p.ptb.w,p.text.fontsize); - Log(t,-8,NaN); - end - - function [t]=StartEyelinkRecording(nTrial,nStim,phase,dist,oddball,ucs,fix) - t = []; - if isnan(dist) - dist=3000; - end - nStim = double(nStim); - Eyelink('Message', 'TRIALID: %04d, PHASE: %04d, FILE: %04d, DELTACSP: %04d, ODDBALL: %04d, UCS: %04d, FIXX: %04d, FIXY %04d', nTrial, phase, nStim, dist, double(oddball), double(ucs),fix(1),fix(2)); - % an integration message so that an image can be loaded as - % overlay background when performing Data Viewer analysis. - WaitSecs(0.01); - %return - if nStim~=0 - Eyelink('Message', '!V IMGLOAD CENTER %s %d %d', p.stim.files(nStim,:), p.ptb.midpoint(1), p.ptb.midpoint(2)); - end - % This supplies the title at the bottom of the eyetracker display - Eyelink('Command', 'record_status_message "Stim: %02d, Phase: %d"', nStim, phase); - % - %Put the tracker offline and draw the stimuli. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - % clear tracker display and draw box at center - Eyelink('Command', 'clear_screen %d', 0); - %draw the image on the screen but also the two crosses - if (nStim <= 16 && nStim>0) - Eyelink('ImageTransfer',p.stim.files24(nStim,:),p.ptb.imrect(1),p.ptb.imrect(2),p.ptb.imrect(3),p.ptb.imrect(4),p.ptb.imrect(1),p.ptb.imrect(2)); - - end -% Eyelink('Command', 'draw_cross %d %d 15',p_ptb_CrossPositionET_x(1),p_ptb_CrossPositionET_y(1) ); -% Eyelink('Command', 'draw_cross %d %d 15',p_ptb_CrossPositionET_x(2),p_ptb_CrossPositionET_y(2) ); - Eyelink('Command', 'draw_cross %d %d 15',fix(1),fix(2)); - - % - %drift correction - %EyelinkDoDriftCorrection(el,crosspositionx,crosspositiony,0,0); - %start recording following mode transition and a short pause. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('StartRecording'); - t = GetSecs; - Log(t,8,NaN); - end - function shuffled = Shuffle(vector,N) - %takes first N from the SHUFFLED before outputting. This function - %could be used as a replacement for randsample - if nargin < 2;N = length(vector);end - [~, idx] = sort(rand([1 length(vector)])); - shuffled = vector(idx(1:N)); - shuffled = shuffled(:); - end - function Buzz - outp(p.com.lpt.address, p.com.lpt.digitimer ); - WaitSecs(p.duration.shockpulse); - outp(p.com.lpt.address, 0); - WaitSecs(p.duration.intershockpulse); - end - function MarkCED(socket,port) - %send pulse to SCR# - outp(socket,port); - WaitSecs(0.01); - outp(socket,0); - end - function InitEyeLink - % - if EyelinkInit(0)%use 0 to init normaly - fprintf('=================\nEyelink initialized correctly...\n') - else - fprintf('=================\nThere is problem in Eyelink initialization\n') - keyboard; - end - % - WaitSecs(0.5); - [~, vs] = Eyelink('GetTrackerVersion'); - fprintf('=================\nRunning experiment on a ''%s'' tracker.\n', vs ); - - %load 24bits pictures for eyelink... - dummy = dir([p.path.stim24 '*.bmp']); - p.stim.files24 = [repmat([fileparts(p.path.stim24) filesep],length(dummy),1) vertcat(dummy(:).name)]; - % - el = EyelinkInitDefaults(p.ptb.w); - %update the defaults of the eyelink tracker - el.backgroundcolour = p.stim.bg; - el.msgfontcolour = WhiteIndex(el.window); - el.imgtitlecolour = WhiteIndex(el.window); - el.targetbeep = 0; - el.calibrationtargetcolour = WhiteIndex(el.window); - el.calibrationtargetsize = 1.5; - el.calibrationtargetwidth = 0.5; - el.displayCalResults = 1; - el.eyeimgsize = 50; - el.waitformodereadytime = 25;%ms - el.msgfont = 'Times New Roman'; - el.cal_target_beep = [0 0 0];%[1250 0.6 0.05]; - %shut all sounds off - el.drift_correction_target_beep = [0 0 0]; - el.calibration_failed_beep = [0 0 0]; - el.calibration_success_beep = [0 0 0]; - el.drift_correction_failed_beep = [0 0 0]; - el.drift_correction_success_beep= [0 0 0]; - EyelinkUpdateDefaults(el); - %PsychEyelinkDispatchCallback(el) - - % open file. - res = Eyelink('Openfile', p.path.edf); - % - Eyelink('command', 'add_file_preamble_text ''Recorded by EyelinkToolbox FearCloud Experiment'''); - Eyelink('command', 'screen_pixel_coords = %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - Eyelink('message', 'DISPLAY_COORDS %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - % set calibration type. - Eyelink('command','auto_calibration_messages = YES'); - Eyelink('command', 'calibration_type = HV13'); - Eyelink('command', 'select_parser_configuration = 1'); - %what do we want to record - Eyelink('command', 'file_sample_data = LEFT,RIGHT,GAZE,HREF,AREA,GAZERES,STATUS,INPUT,HTARGET'); - Eyelink('command', 'file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON,INPUT'); - Eyelink('command', 'use_ellipse_fitter = no'); - % set sample rate in camera setup screen - Eyelink('command', 'sample_rate = %d',1000); - end - function StopEyelink(filename) - try - fprintf('Trying to stop the Eyelink system with StopEyelink\n'); - Eyelink('StopRecording'); - WaitSecs(0.5); - Eyelink('Closefile'); - display('receiving the EDF file...'); - Eyelink('ReceiveFile',filename,[p.path.subject '\eye\'],1); - display('...finished!') - % Shutdown Eyelink: - Eyelink('Shutdown'); - catch - display('StopEyeLink routine didn''t really run well'); - end - end - function cleanup - - % Close window: - sca; - %set back the old resolution - if strcmp(p.hostname,'triostim1') - Screen('Resolution',p.ptb.screenNumber, p.ptb.oldres.width, p.ptb.oldres.height ); - %show the cursor - ShowCursor(p.ptb.screenNumber); - end - % - IOPort('ConfigureSerialPort', p.com.serial,' StopBackgroundRead'); - IOPort('Close',p.com.serial); - commandwindow; - ListenChar(0); - KbQueueRelease(p.ptb.device); - end - function CalibrateEL - fprintf('=================\n=================\nEntering Eyelink Calibration\n') - p_var_ExpPhase = 0; - ShowInstruction(0,1); - EyelinkDoTrackerSetup(el); - %Returns 'messageString' text associated with result of last calibration - [~, messageString] = Eyelink('CalMessage'); - Eyelink('Message','%s',messageString);% - WaitSecs(0.05); - fprintf('=================\n=================\nNow we are done with the calibration\n') - end - function Log(ptb_time, event_type, event_info) - %Phases: - %Instruction : 1 - %Baseline : 2 - %Conditioning : 3 - %Test : 4 - %Rating : 5 - %Calibration : 0 - % - %event types are as follows: - % - %Scan Detection : 0 info: NaN; - %Cross Onset : 1 info: position - %Stimulus Onset/Offset: 2/-2 info: stim_id - %Cross Movement : 3 info: NaN; - %Stimulus Offset : -2 info: NaN; - %UCS Delivery : 4 info: NaN; - %Key Presses : 7 info: NaN; - %Tracker Onset/Offset : 8 info: NaN; - % - %Text on the screen : 5 info: Which Text? - %RatingScreen Onset : 6 info: NaN; - - p_var_event_count = p_var_event_count + 1; - %% - % - % for x = 1:10 - % disp(x) - % end - % - p.out.log(p_var_event_count,:) = [ptb_time event_type event_info p_var_ExpPhase]; - % % p.out.log(p.out.event_counter,:) - %logstring([ 'Logged: ' mat2str(p.out.log(p.out.event_counter,:)) ' - Type: ' p.verbose.eventtype{abs(event_type)} ' - Phase: ' p.verbose.eventphase{CurrentExperimentalPhase}]) - %for i = 1:3;subplot(3,1,i);plot(p.out.log(1:p.out.event_counter ,i),'o-');drawnow;end - % - - end - - -end diff --git a/FearGen_eyelab.m b/FearGen_eyelab.m deleted file mode 100644 index 838e4fe..0000000 --- a/FearGen_eyelab.m +++ /dev/null @@ -1,1099 +0,0 @@ -function [p]=FearGen_eyelab(subject,phase,csp,PainThreshold) -%[p]=Conditioning(subject,NthSeq,CSpface,phase,PainThreshold) -% -%Used for the last recording (3rd Scan Request) sessions of the Feargen -%project. Mainly different in loading the precomputed sequences... -% -% - -if nargin ~= 4 - fprintf('Wrong number of inputs\n'); - keyboard; -end - -csn = mod( csp + 8/2-1, 8)+1; -ListenChar(2);%disable pressed keys to be spitted around -commandwindow; -%clear everything -clear mex global functions -cgshut; -global cogent; -%%%%%%%%%%%load the GETSECS mex files so call them at least once -GetSecs; -WaitSecs(0.001); -% -el = []; -p = []; -SetParams; -fprintf('length: %d',length(p.presentation.cond_id)) -[p.presentation.cond_id'; p.presentation.stim_id'; p.presentation.ucs';p.presentation.oddball'] -unique(p.presentation.stim_id) -pause(5); -debug = 0;%debug mode -SetPTB; -% -%init all the variables -t = []; -nTrial = 0; -%% -%Time Storage -TimePulse1 = []; -TimePulse2 = []; -TimeStimOnset = []; -TimeCrossJumpTime = []; -TimeEndStim = []; -TimeStartShock = []; -TimeTrackerOff = []; -TimeTrackerOn = []; -TimeCrossOn = []; -p_var_ExpPhase = []; -p_var_event_count = 0; - - - -%% -InitEyeLink; -WaitSecs(2); -%calibrate if we are at the scanner computer. -if strcmp(p.hostname,'triostim1') || strcmp(p.hostname,'etpc'); - CalibrateEL; -end -%save again the parameter file -save(p.path.path_param,'p'); -if phase == 1 - ShowInstruction(1,1); - -elseif phase == 2 - % - p_var_ExpPhase = phase; - ShowInstruction(101,1); - ShowInstruction(2,1); - ShowInstruction(3,1); - ShowInstruction(4,1); - ConfirmIntensity; - ShowInstruction(5,1);%will wait for keypresses - PresentStimuli; - AskStimRating;%make sure that scanner doesnt stop prematurely asa the stim offset - -elseif phase == 3 - % - p_mrt_on = 0; - p_var_ExpPhase = phase; - % - ShowInstruction(6,1);%will not wait for keypresses - % - PresentStimuli; - % - %makee sure that scanner doesnt stop prematurely asa the stim offset - AskStimRating; -elseif phase == 4 - p_mrt_on = 0; - p_var_ExpPhase = phase; - % - ShowInstruction(6,1);%will not wait for keypresses - PresentStimuli; - %makee sure that scanner doesnt stop prematurely asa the stim offset - AskStimRating; - %makee sure that scanner doesnt stop prematurely asa the stim offset - fprintf('Finished with the rating\n'); - %AskWhichFace; -end - -%get the eyelink file back to this computer -StopEyelink(p.path.edf); -%trim the log file and save -p.out.log = p.out.log(sum(isnan(p.out.log),2) ~= size(p.out.log,2),:); -%shift the time so that the first timestamp is equal to zero -p.out.log(:,1) = p.out.log(:,1) - p.out.log(1); -p.out.log = p.out.log;%copy it to the output variable. -save(p.path.path_param,'p'); -% -%move the file to its final location. -movefile(p.path.subject,p.path.finalsubject); -%close everything down -cleanup; - - function ConfirmIntensity - %Compute the intensity we want to deliver to the subject. - - p.var.ShockIntensity = p.out.PainThreshold*p.out.ShockFactor; - - % - ShowInstruction(9,1); - % - fprintf([repmat('=',1,50) '\n']); - fprintf('TEST SHOCK:\n'); - fprintf('!!! ADJUST THE SHOCK INTENSITY ON THE DIGITIMER !!!\n'); - fprintf(' The intensity is now: %g mA\n',p.var.ShockIntensity); - fprintf(' Experimenter: Press any key to deliver a shock.\n'); - fprintf([repmat('=',1,50) '\n']); - % - [secs, keyCode, deltaSecs] = KbStrokeWait; - ShowInstruction(10,0);%shock is coming message... - t = GetSecs + p.duration.shock; - MarkCED( p.com.lpt.address, p.com.lpt.shock ); - while GetSecs < t; - Buzz; - end - % - message = 'Bewege den "Zeiger" mit der rechten und linken Pfeiltaste\n und bestätige deine Einschätzung mit der mit der oberen Pfeiltaste.'; - rect = [p.ptb.width*0.2 p.ptb.midpoint(2) p.ptb.width*0.6 100]; - response = RatingSlider(rect,2,1,p.keys.increase,p.keys.decrease,p.keys.confirm,{ 'nicht\nerträglich' 'erträglich'},message,0); - if response == 2 - fprintf('All is fine :)\n'); - fprintf('Subject confirmed the shock intensity inside the scanner...\n') - fprintf('INTENSITY TO BE USED FOR THE MAIN EXPERIMENT: %g mA\n',p.var.ShockIntensity); - p.out.ShockIntensity = p.var.ShockIntensity; - return; - elseif response == 1 - fprintf('Shit... :(, %g is too much for the subject\n',p.var.ShockIntensity); - fprintf('We will try a little milder intensity.\n'); - p.out.ShockFactor = p.out.ShockFactor - 0.05; - ConfirmIntensity; - end - - - end - function PresentStimuli - %Enter the presentation loop and wait for the first pulse to - %arrive. - - - - - - % - - TimeEndStim = GetSecs; - for nTrial = 1:p.presentation.tTrial; - % - %Get the variables that Trial function needs. - stim_id = p.presentation.stim_id(nTrial); - % - fix = p.presentation.CrossPosition(nTrial,:); - - ISI = p.presentation.isi(nTrial); - ucs = p.presentation.ucs(nTrial); - oddball = p.presentation.oddball(nTrial); - prestimdur = p.duration.prestim+rand(1)*.25; - dist = p.presentation.dist(nTrial); - %prestimdur = p_presentation_prestim_dur(nTrial); - - - fprintf('%d of %d, S: %d, ISI: %d, UCS: %d, ODD: %d.\n',nTrial,p.presentation.tTrial,stim_id,ISI,ucs,oddball); - % - - OnsetTime = TimeEndStim + ISI-p.duration.stim ; - - % jetz = GetSecs; - % if mod(nTrial,100) == 0 - % ShowInstruction(14,1); - % OnsetTime = OnsetTime + GetSecs - jetz; - % end - - KbQueueStart(p.ptb.device);%monitor keypresses... - - %Start with the trial, here is time-wise sensitive must be - %optimal - [TimeEndStim]= Trial(nTrial,OnsetTime, prestimdur, stim_id , ucs , fix , oddball,dist); - % - [keypressed, firstPress]=KbQueueCheck(p.ptb.device); - %if the press was after stimulus onset and before stimulus - %offset - if keypressed && (firstPress(p.keys.confirm) > OnsetTime) && (firstPress(p.keys.confirm) < TimeEndStim) - p.out.response(nTrial) = 1; - Log(firstPress(p.keys.confirm),7,NaN);%log the key press for hit detection. - fprintf('Subject Pressed the Hit Key!!\n'); - end -% if (phase == 4 && nTrial == ceil(p.presentation.tTrial/2)) -% ShowInstruction(14,1) -% CalibrateEL; -% end - end - end - function [TimeEndStim]=Trial(nTrial,TimeStimOnset , prestimdur, stim_id , ucs , fix , oddball, dist ) - %get all the times - TimeCrossOnset = TimeStimOnset - prestimdur; - TimeEndStim = TimeStimOnset + p.duration.stim; - TimeStartShock = TimeStimOnset + p.duration.onset2shock; - TimeTrackerOff = TimeStimOnset + p.duration.keep_recording; - - %% Fixation Onset - FixCross = [fix(1)-1,fix(2)-20,fix(1)+1,fix(2)+20;fix(1)-20,fix(2)-1,fix(1)+20,fix(2)+1]; - Screen('FillRect', p.ptb.w, [255,255,255], FixCross'); - TimeCrossOn = Screen('Flip',p.ptb.w,TimeCrossOnset,0); - MarkCED( p.com.lpt.address, p.com.lpt.FixOnset ); - Eyelink('Message', 'FX Onset at %d %d',fix(1),fix(2)); - Log(TimeCrossOn,1,stim_id);%cross onset. - %turn the eye tracker on - StartEyelinkRecording(nTrial,stim_id,p_var_ExpPhase,dist,oddball,ucs,fix); - - - - %% Draw the stimulus to the buffer - if ~stim_id==0 - Screen('DrawTexture', p.ptb.w, p.ptb.stim_sprites(stim_id)); - end - %Screen('DrawText' , p.ptb.w, double('+'), p.ptb.CrossPosition_x,fix, p.stim.white); -% if oddball%add freckles to the face -% x = randn(1,100)*35; -% y = randn(1,100)*10; -% s = rand(1,100);%[0 1] -% Screen('DrawDots',p.ptb.w,[x;y],1+s.*1.5,[100 100 100 160],p.ptb.midpoint,1); -% %the dots size -% end - Screen('DrawingFinished',p.ptb.w,0); - - %% STIMULUS ONSET - %Here we wait only for the next pulse. - %The proper amount is obtained with the second call of WaitPulse - %below, before the onset of the fixation cross. - %fprintf('Will Wait for the pulse to Stim Onset\n'); - TimeStimOnset = Screen('Flip',p.ptb.w,TimeStimOnset,0);%asap and dont clear - %send eyelink and ced a marker asap - Eyelink('Message', 'Stim Onset'); - Eyelink('Message', 'SYNCTIME'); - MarkCED( p.com.lpt.address, p.com.lpt.StimOnset ); - if oddball - MarkCED( p.com.lpt.address, p.com.lpt.oddball ); - end - Log(TimeStimOnset,2,stim_id);%log the stimulus onset - - - if ucs == 1 - %%%%%%%%%%%%%%%%%%%%%%% - %Deliver shock and stim off immediately - TimeStartShock = WaitSecs('UntilTime',TimeStartShock); - MarkCED( p.com.lpt.address, p.com.lpt.shock ); - Eyelink('Message', 'UCS Onset'); - - while GetSecs < TimeEndStim; - Buzz;%this is anyway sent to CED. - end - Eyelink('Message', 'UCS Offset'); - end - - %% STIM OFF immediately - TimeEndStim = Screen('Flip',p.ptb.w,TimeEndStim,0); - %send eyelink and ced a marker - Eyelink('Message', 'Stim Offset'); - Eyelink('Message', 'BLANK_SCREEN'); - Screen('Textsize', p.ptb.w,p.text.fontsize); - Log(TimeEndStim,-2,stim_id);%log the stimulus offset - % - %% record some more eye data after stimulus offset. - WaitSecs('UntilTime',TimeTrackerOff); - TimeTrackerOff = StopEyelinkRecording; - - - if oddball == 1 - fprintf('This was an oddball trial!\n'); - end - if ucs == 1 - fprintf('This was a UCS trial!\n'); - Log(TimeStartShock,4,NaN);%UCS delivery...This is done here to not waste time there - end - - end - - function SetParams - - % - p.var.timings = zeros(1,10); - p_var_event_count = 0; - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %relative path to stim and experiments - %Path Business. - [~, hostname] = system('hostname'); - p.hostname = deblank(hostname); - if strcmp(p.hostname,'triostim1') - p.path.baselocation = 'C:\USER\onat\Experiments\'; - elseif strcmp(p.hostname,'etpc') - p.path.baselocation = 'C:\Users\onat\Documents\Experiments\'; - else - p.path.baselocation = 'C:\Users\onat\Documents\Experiments\'; - end - - p.path.experiment = [p.path.baselocation 'feargen_master' filesep]; - p.path.stim = 'C:\Users\onat\Documents\Experiments\feargen_master\stim\'; - p.path.stim24 = [p.path.stim '24bit8' '\']; - % - p.subID = sprintf('sub%02d',subject); - p.path.edf = sprintf([p.subID 'p%02d' ],phase); - timestamp = datestr(now,30); - p.path.subject = [p.path.experiment 'data\tmp\' p.subID '_' timestamp '\']; - p.path.finalsubject = [p.path.experiment 'data\' p.subID '_' timestamp '\' ]; - %create folder hierarchy - mkdir(p.path.subject); - mkdir([p.path.subject 'scr']); - mkdir([p.path.subject 'eye']); - mkdir([p.path.subject 'stimulation']); - mkdir([p.path.subject 'midlevel']); - p.path.path_param = sprintf([regexprep(p.path.subject,'\\','\\\') 'stimulation\\param_phase_%02d'],phase); - - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %get stim files - [p.stim.files p.stim.label] = FileMatrix([p.path.stim '*.bmp']); - p.stim.tFile = size(p.stim.files,1);%number of different files (including the UCS symbol) - p.stim.tFace = p.stim.tFile - 1;%number of faces. - % - display([mat2str(p.stim.tFile) ' found in the destination.']); - %set the background gray according to the background of the stimuli - for i = 1:p.stim.tFile; - im = imread(p.stim.files(i,:)); - bg(i) = im(1,1,1); - end - %is all the captured bg values the same? - if sum(diff(bg))==0; - %if so take it as the bg color - p.stim.bg = double([bg(1) bg(1) bg(1)]); - else - fprintf('background luminance was not successfully detected...\n') - keyboard; - end - %bg of the rating screen. - p.stim.bg_rating = [0 128 0]; - % - %font size and background gray level - p.text.fontname = 'Times New Roman'; - p.text.fontsize = 18;%30; - p.text.fixsize = 60; - %rating business - p.rating.division = 10;%number of divisions for the rating slider - p.rating.repetition = 2;%how many times a given face has to be repeated... - % - p.stim.white = [255 255 255]; - %get the actual stim size (assumes all the same) - info = imfinfo(p.stim.files(1,:)); - p.stim.width = info.Width; - p.stim.height = info.Height; - - if strcmp(p.hostname,'triostim1') - p.keys.confirm = KbName('7'); - p.keys.increase = KbName('8'); - p.keys.decrease = KbName('6'); - p.keys.space = KbName('space'); - p.keys.esc = KbName('esc'); - else - %All settings for laptop computer. - p.keys.confirm = KbName('up'); - p.keys.increase = KbName('right'); - p.keys.decrease = KbName('left'); - p.keys.space = KbName('space'); - p.keys.esc = KbName('esc'); - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %Communication business - %parallel port - p.com.lpt.address = 888; - %codes for different events - p.com.lpt.InitExperiment = 64;%which is all channels without digitimer - p.com.lpt.FixOnset = 4; - p.com.lpt.StimOnset = 8; - p.com.lpt.shock = 16; - p.com.lpt.oddball = 32; - p.com.lpt.keypress = 2; - p.com.lpt.digitimer = 128; - % - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %timing business - %these are the intervals of importance - %time2fixationcross->cross2onset->onset2shock->shock2offset - %these (duration.BLA) are average duration values: - p.duration.stim = 0.6;%2;%s - p.duration.shock = 0.1;%s;x - p.duration.shockpulse = 0.005;%ms; duration of each individual pulses - p.duration.intershockpulse = 0.01;%ms; and the time between each pulse - p.duration.onset2shock = p.duration.stim - p.duration.shock; - p.duration.crossmoves = p.duration.stim./2; - p.duration.keep_recording = 0.25;%this is the time we will keep recording (eye data) after stim offset. - p.duration.prestim_ori = .95; - %p.duration.prestim = 2-p.duration.prestim_ori;%that is 0.95 seconds - p.duration.prestim = .85; - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %stimulus sequence - seqpool = load('C:\Users\onat\Documents\Experiments\feargen_master\seq\seq.mat'); - seq = seqpool.s(phase,csp,RandSample(1:size(seqpool.s,3),[1 1])); - clear seqpool -% if phase == 2 -% seq = seq_feargen_cloudseq(csp,'baseline');%only 1 short seq -% elseif phase == 3%conditioning -% seq = seq_feargen_cloudseq(csp,'cond');%gets 1 short seq -% elseif phase == 4 -% seq = seq_feargen_cloudseq(csp,'test');%gets 2 short seqs -% end - %create the randomized design - p.stim.cs_plus = csp;%index of cs stimulus, this is the one paired to shock - p.stim.cs_neg = csn; - %Record which Phase are we going to run in this run. - p.stim.phase = phase; - %this will deal all the presentation sequence related information - p.presentation = seq; - - p.out.rating = []; - p.out.log = zeros(1000000,4).*NaN; - p.out.response = zeros(p.presentation.tTrial,1); - p.out.PainThreshold = PainThreshold; - p.out.ShockFactor = 2; - %Save the stuff - save(p.path.path_param,'p'); - % - function [FM labels] = FileMatrix(path) - %Takes a path with file extension associated to regexp (e.g. - %C:\blabl\bla\*.bmp) returns the file matrix - dummy = dir(path); - FM = [repmat([fileparts(path) filesep],length(dummy),1) vertcat(dummy(:).name)]; - labels = {dummy(:).name}; - end - end - function AskStimRating - - MarkCED( p.com.lpt.address, p.com.lpt.InitExperiment); - % - p_var_ExpPhase = 5; - BG = p.stim.bg;% - p.stim.bg = p.stim.bg_rating; - nseq = 0; - rating_seq = []; - pos1_seq = []; - % - while nseq < p.rating.repetition - nseq = nseq + 1; - rating_seq = [ rating_seq Shuffle(1:p.stim.tFile-2)']; - end - message = GetText(11); - SliderTextL = GetText(13); - SliderTextR = GetText(12); - % - Screen('FillRect', p.ptb.w , p.stim.bg); - Screen('Flip',p.ptb.w); - WaitSecs(2); - % - ShowInstruction(7,1); - rect = [p.ptb.width*0.2 p.ptb.midpoint(2) p.ptb.width*0.6 100]; - tRatend = length(rating_seq); - %save the rating sequence just for security - p.out.rating_seq = rating_seq; - - for nRatend = 1:tRatend; - % - %the variable that are used by Trial function - stim_id = rating_seq(nRatend); - - fix = p.presentation.CrossPosition(nRatend,:); - % - next_stim_id = [];%this is a trick, otherwise a fixation cross appears right before the rating :( - next_pos1 = []; - - %to send know the distance here, little dummy setup: - dummy = -135:45:180; - dist = dummy(stim_id); - %We will turn on the fixation cross and start the tracker - %for the first trial. These have to be done before the main - %for loop. - FixCross = [fix(1)-1,fix(2)-20,fix(1)+1,fix(2)+20;fix(1)-20,fix(2)-1,fix(1)+20,fix(2)+1]; - Screen('FillRect', p.ptb.w, [255,255,255], FixCross'); - t = Screen('Flip',p.ptb.w); - Screen('Textsize', p.ptb.w,p.text.fontsize); - % - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %Mark the onset - Eyelink('Message', 'FX Onset at %d %d',fix(1),fix(2)); - Log(t,1,fix(1));%log the mark onset... - Log(t,1,fix(2)) - - % - Trial(1000+nRatend,GetSecs+1,0.5,stim_id,0,fix,0,dist); - rate(nRatend,1) = RatingSlider(rect, p.rating.division, Shuffle(1:p.rating.division,1), p.keys.increase, p.keys.decrease, p.keys.confirm, {SliderTextL{1} SliderTextR{1}},message,1); - - %%%%%%%%%%%%%%%%%%%%%%%%%%%% - %Verbose the rating of the subject - fprintf('============\nRating Results %d (%d/%d):\n', stim_id, nRatend, tRatend); - dummy = rating_seq(1:nRatend);%trials shown so far - for iii = 1:p.stim.tFile-2 - r = round(mean(rate(dummy == iii))); - if isnan(r) - r = 0; - end - if iii == p.stim.cs_plus - fprintf('Stimulus %02d: * %s \n',iii,repmat('+',1,1+r)); - else - fprintf('Stimulus %02d: %s \n',iii,repmat('+',1,1+r)); - end - end - end - %sort the stim_ids and then sort the same the rates and make a - %matrix out of that to store - [~, i] = sort(rating_seq); - rate = reshape(rate(i),p.rating.repetition,p.stim.tFile-2)'; - p.out.rating = rate; - save(p.path.path_param,'p'); - Screen('FillRect',p.ptb.w,p.stim.bg); - p.stim.bg = BG; - % - save(p.path.path_param,'p'); - end - function [rating] = RatingSlider(rect,tSection,position,up,down,confirm,labels,message,numbersOn) - % - %Detect the bounding boxes of the labels. - for nlab = 1:2 - [~ , ~, bb(nlab,:)]=DrawFormattedText(p.ptb.w,labels{nlab}, 'center', 'center', p.stim.white,[],[],[],2); - Screen('FillRect',p.ptb.w,p.stim.bg); - end - bb = max(bb); - bb_size = bb(3)-bb(1);%vertical size of the bb. - % - DrawSkala; - ok = 1; - while ok == 1 - [secs, keyCode, ~] = KbStrokeWait; - keyCode = find(keyCode); - Log(secs,7,keyCode); - if length(keyCode) == 1%this loop avoids crashes to accidential presses of meta keys - if (keyCode == up) || (keyCode == down) - next = position + increment(keyCode); - if next < (tSection+1) && next > 0 - position = position + increment(keyCode); - %rating = tSection - position + 1; - end - DrawSkala; - elseif keyCode == confirm - MarkCED( p.com.lpt.address, p.com.lpt.keypress); - WaitSecs(0.1); - ok = 0; - Screen('FillRect',p.ptb.w,p.stim.bg); - t=Screen('Flip',p.ptb.w); - end - end - end - - function DrawSkala - %rating = tSection - position + 1; - rating = position ; - increment([up down]) = [1 -1];%delta - tick_x = linspace(rect(1),rect(1)+rect(3),tSection+1);%tick positions - tick_size = rect(3)./tSection; - ss = tick_size/5*0.9;%slider size. - % - for tick = 1:length(tick_x)%draw ticks - Screen('DrawLine', p.ptb.w, [255 0 0], tick_x(tick), rect(2), tick_x(tick), rect(2)+rect(4) , 3); - if tick <= tSection && numbersOn - Screen('TextSize', p.ptb.w,p.text.fontsize./2); - DrawFormattedText(p.ptb.w, mat2str(tick) , tick_x(tick)+ss/2, rect(2)+rect(4), p.stim.white); - Screen('TextSize', p.ptb.w,p.text.fontsize); - end - if tick == 1 - DrawFormattedText(p.ptb.w, labels{1},tick_x(tick)-bb_size*1.4,rect(2), p.stim.white); - elseif tick == tSection+1 - DrawFormattedText(p.ptb.w, labels{2},tick_x(tick)+bb_size*0.4,rect(2), p.stim.white); - end - end - %slider coordinates - slider = [ tick_x(position)+tick_size*0.1 rect(2) tick_x(position)+tick_size*0.9 rect(2)+rect(4)]; - %draw the slider - Screen('FillRect',p.ptb.w, p.stim.white, round(slider)); - Screen('TextSize', p.ptb.w,p.text.fontsize./2); - DrawFormattedText(p.ptb.w,message, 'center', p.ptb.midpoint(2)*0.2, p.stim.white,[],[],[],2); - Screen('TextSize', p.ptb.w,p.text.fontsize); - t = Screen('Flip',p.ptb.w); - Log(t,6,NaN); - end - end - function ShowInstruction(nInstruct,waitforkeypress) - %ShowInstruction(nInstruct,waitforkeypress) - %if waitforkeypress is 1, then subject has to press a button to - %make the instruction text dissappear. Otherwise you have to take - %care of it later - - [text]= GetText(nInstruct); - ShowText(text); - %let subject read it and ask confirmation to proceed. But we don't - %need that in the case of INSTRUCT = 5; - if waitforkeypress - if nInstruct ~= 10%this is for the Reiz kommnt - KbStrokeWait; - else - WaitSecs(2.5+rand(1)); - end - Screen('FillRect',p.ptb.w,p.stim.bg); - t = Screen('Flip',p.ptb.w); - Log(t,-5,nInstruct); - else - if nInstruct ~= 10%this is for the Reiz kommnt - KbStrokeWait; - else - WaitSecs(1+rand(1)); - end - end - - - function ShowText(text) - - Screen('FillRect',p.ptb.w,p.stim.bg); - %DrawFormattedText(p.ptb.w, text, p.text.start_x, 'center',p.stim.white,[],[],[],2,[]); - DrawFormattedText(p.ptb.w, text, 'center', 'center',p.stim.white,[],[],[],2,[]); - t=Screen('Flip',p.ptb.w); - Log(t,5,nInstruct); - %show the messages at the experimenter screen - fprintf('=========================================================\n'); - fprintf('Text shown to the subject:\n'); - fprintf('=========================================================\n'); - fprintf(text); - fprintf('=========================================================\n'); - - end - end - function [text]=GetText(nInstruct) - if nInstruct == 0%Eyetracking calibration - - text = ['Um Ihre Augenbewegungen zu messen, \n' ... - 'müssen wir jetzt den Eye-Tracker kalibrieren.\n' ... - 'Dazu zeigen wir Ihnen einige Punkte auf dem Bildschirm, \n' ... - 'bei denen Sie sich wie folgt verhalten:\n' ... - 'Bitte fixieren Sie den kleinen weißen Kreis und \n' ... - 'bleiben so lange darauf, wie es zu sehen ist.\n' ... - 'Bitte drücken Sie jetzt den oberen Knopf, \n' ... - 'um mit der Kalibrierung weiterzumachen.\n' ... - ]; - - elseif nInstruct == 1%first Instr. of the training phase. - text = ['Wir werden nun als erstes einen Übungsdurchgang machen,\n' ... - 'damit Sie sich an Ihre Aufgabe gewöhnen können.\n' ... - 'In diesem Durchgang können Sie sich vollkommen sicher fühlen,\n' ... - 'es werden keine elektrischen Reize verabreicht.\n' ... - 'Eine wichtige grundsätzliche Regel ist, dass Sie das Fixationskreuz (das „+“)\n' ... - 'wenn es zu sehen ist, mit Ihren Augen fixieren. \n' ... - 'Drücken Sie die obere Taste um fortzufahren.\n' ... - ]; - elseif nInstruct == 101%first Instr. of the training phase. - text = ['Willkommen zum zweiten Teil des Experiments.\n'... - 'Eine wichtige grundsätzliche Regel ist auch hier,\n'... - 'dass Sie das Fixationskreuz (das „+“)\n' ... - 'wenn es zu sehen ist, mit Ihren Augen fixieren. \n' ... - 'Drücken Sie die obere Taste um fortzufahren.\n' ... - ]; - elseif nInstruct == 2%second Instr. of the training phase. - text = ['Ein paar Bemerkungen zu den Zielreizen: \n' ... - 'Zur Erinnerung: Zielreize sind die verschwommenen Gesichter.\n' ... - 'Sobald ein solcher Zielreiz erscheint, \n' ... - 'sollen Sie schnellstmöglich die obere Taste drücken, \n' ... - 'und zwar bevor der Reiz wieder verschwunden ist \n' ... - '(Sie müssen also sehr schnell und aufmerksam sein).' ... - ]; - elseif nInstruct == 3%third Instr. of the training phase. - text = ['Es ist sehr wichtig, dass Sie Ihren Kopf während \n' ... - 'des Experiments nicht bewegen. \n' ... - 'Das ist besonders wichtig für die Qualität der Messung.\n' ... - ]; - elseif nInstruct == 4%third Instr. of the training phase. - text = ['Vor dem Experiment legen wir nun \n' ... - 'die Schockintensität für den Rest des Experiments fest. \n' ... - 'Drücken Sie die obere Taste um fortzufahren.' ... - ]; - - elseif nInstruct == 5%Baseline Phase - % - % - %=================================================================================================================% - text = ['Jetzt geht es mit dem Experiment los.\n' ... - 'Ihre Aufgabe ist es jetzt, die Gesichter, \n' ... - 'die Ihnen gezeigt werden aufmerksam zu betrachten und \n' ... - 'den oberen Knopf zu drücken, sobald Sie einen Zielreiz sehen.\n' ... - '\n'... - 'Hin und wieder erscheint ein Symbol (ein Blitzpfeil, der vor Strom warnt), \n' ... - 'das einen elektrischen Reiz ankündigt. \n' ... - 'Die Reize erfolgen aber nur bei diesem Symbol, nicht bei den Gesichtern! \n' ... - 'Bei Gesichtern können Sie sich also sicher fühlen.\n' ... - 'Bitte denken Sie daran: 1. Fixationskreuz fixieren und 2. nicht bewegen!\n\n' ... - 'Sie können das Experiment nun durch Drücken der oberen Taste starten. \n' ... - ]; - - elseif nInstruct == 6%Test and Conditioning Phase - %=================================================================================================================% - text = ['Auch im nun folgenden Teil des Experiments \n' ... - 'sollen Sie die Gesichter aufmerksam betrachten und \n' ... - 'den oberen Knopf drücken, sobald Sie einen Zielreiz sehen. \n' ... - 'Wie im ersten Teil des Experiments sollen Sie \n' ... - 'das Fixationskreuz immer fixieren. \n' ... - 'In dieser Phase des Experiments werden Sie\n' ... - 'gelegentlich elektrische Reize bekommen.\n\n' ... - 'Die elektrischen Reize folgen jetzt auf bestimmte Gesichter. \n' ... - - ]; - - - elseif nInstruct == 7;%rating - text = ['In dieser Phase hätten wir gerne, dass Sie die Gesichter\n'... - 'im Hinblick auf folgende Frage bewerten:\n'... - '„Wie wahrscheinlich ist es, bei dem gerade gesehenen Gesicht \n'... - 'einen elektrischen Schock zu erhalten?“\n'... - 'Bewegen Sie den Zeiger mit der rechten und linken Pfeiltaste \n'... - 'und bestätigen Sie Ihre Einschätzung mit der oberen Pfeiltaste.\n'... - ]; - - elseif nInstruct == 8 %CS+ detection - text = ['Du bekommen nun eine Reihe von Gesichtern gezeigt.\n' ... - 'Bitte wählen Sie das Gesicht aus bei dem der Schock verabreicht wurde.\n'... - 'Drücken Sie die obere Taste um fortzufahren.\n'... - ]; - elseif nInstruct == 9% - %=================================================================================================================% - text = ['Bitte geben Sie an, ob die Reizstärke des folgenden Schocks\n für Sie erträglich ist.\n'... - '\n'... - 'Drücken Sie bitte die obere Taste um den Reiz zu bekommen.\n'... - ]; - - elseif nInstruct == 10%just before the shock - text = ['Reiz kommt...\n']; - elseif nInstruct == 11%this is the rating question - text = ['Wie wahrscheinlich ist es, bei dem gerade gesehenen Gesicht \n'... - 'einen elektrischen Schock zu erhalten?“\n' ... - 'Bewegen Sie den "Zeiger" mit der rechten und linken Pfeiltaste\n' ... - 'und bestätigen Sie Ihre Einschätzung mit der mit der oberen Pfeiltaste'... - ]; - elseif nInstruct == 12 %These two below are the possible responses to the question in 11 - text = {'Sehr\nwahrscheinlich'}; - elseif nInstruct == 13 - text = {'Überhaupt\nnicht\nwahrscheinlich'}; - elseif nInstruct == 14 - text = ['Bitte machen Sie eine kurze Pause.\n' ... - 'Sie können hierbei gern die Augen einen Moment schließen.\n'... - 'Drücken Sie anschließend die obere Taste um fortzufahren.\n'... - 'Wir werden dann den Eyetracker noch einmal kalibrieren.\n'... - ]; - else - text = {''}; - end - end - function SetPTB - %Sets the parameters related to the PTB toolbox. Including - %fontsizes, font names. - %Find the number of the screen to be opened - screens = Screen('Screens'); - p.ptb.screenNumber = 1;%the maximum is the second monitor - %Make everything transparent for debugging purposes. - if debug - commandwindow; - PsychDebugWindowConfiguration; - end - %Default parameters - Screen('Preference', 'SkipSyncTests', 1); - Screen('Preference', 'DefaultFontSize', p.text.fontsize); - Screen('Preference', 'DefaultFontName', p.text.fontname); - Screen('Preference', 'TextAntiAliasing',2);%enable textantialiasing high quality - Screen('Preference', 'VisualDebuglevel', 0); - Screen('Preference', 'SkipSyncTests', 1); - Screen('Preference', 'SuppressAllWarnings', 1); - %set the resolution correctly - if strcmp(p.hostname,'triostim1') - p.ptb.oldres = Screen('resolution',p.ptb.screenNumber,1280,960); - %hide the cursor - HideCursor(p.ptb.screenNumber); - elseif strcmp(p.hostname,'etpc') - p.ptb.oldres = Screen('resolution',p.ptb.screenNumber,1600,1200); - %hide the cursor - HideCursor(p.ptb.screenNumber); - end - - %Open a graphics window using PTB - p.ptb.w = Screen('OpenWindow', p.ptb.screenNumber, p.stim.bg); - Screen('BlendFunction', p.ptb.w, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - Screen('Flip',p.ptb.w);%make the bg - p.ptb.slack = Screen('GetFlipInterval',p.ptb.w)./2; - [p.ptb.width, p.ptb.height] = Screen('WindowSize', p.ptb.screenNumber); - if sum([p.ptb.width p.ptb.height] - [1280 960]) ~= 0 - fprintf('SET THE CORRECT SCREEN RESOLUTION\n'); - end - %find the mid position on the screen. - p.ptb.midpoint = [ p.ptb.width./2 p.ptb.height./2]; - p.ptb.imrect = [ p.ptb.midpoint(1)-p.stim.width/2 p.ptb.midpoint(2)-p.stim.height/2 p.stim.width p.stim.height]; - % %compute the cross position. - % [~, ny bb] = DrawFormattedText(p.ptb.w,'+','center','center'); - % p.ptb.cross_shift = [45 60];%incremental upper and lower cross positions - % p.ptb.CrossPosition_y = p.ptb.midpoint(2)%[ny-p.ptb.cross_shift(1) ny+p.ptb.cross_shift(2) ]; - p.ptb.CrossPosition_x = p.ptb.midpoint(1);%bb(1);%always the same - % %cross position for the eyetracker screen. - % p.ptb.CrossPositionET_x = [p.ptb.midpoint(1) p.ptb.midpoint(1)]; - % p.ptb.CrossPositionET_y = [p.ptb.midpoint(2)-p.ptb.cross_shift(2) p.ptb.midpoint(2)+p.ptb.cross_shift(2)]; - % %% - [nx, ny bb] = DrawFormattedText(p.ptb.w,'+','center','center'); - - - %cross position for the eyetracker screen. -% p.ptb.CrossPositionET_x = [p.ptb.midpoint(1) p.ptb.midpoint(1)]; -% p.ptb.CrossPositionET_y = [p.ptb.midpoint(2)-p.ptb.cross_shift(2) p.ptb.midpoint(2)+p.ptb.cross_shift(2)]; - %% - %priorityLevel=MaxPriority(['GetSecs'],['KbCheck'],['KbWait'],['GetClicks']); - Priority(MaxPriority(p.ptb.w)); - %this is necessary for the Eyelink calibration - InitializePsychSound(0) - %sound('Open') - Beeper(5000) - - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %set serial communication channels - IOPort('CloseAll'); - p.com.serial = IOPort('OpenSerialPort', 'COM1', 'InputBufferSize=51840000 HardwareBufferSizes=32768,32768 Terminator=0 ReceiveLatency=0.0001 BaudRate=9600 ReceiveTimeout=7'); - IOPort('ConfigureSerialPort', p.com.serial, 'BlockingBackgroundRead=1'); - %because of the BlockingBackgroundRead=1, the flush and close all - %command will wait for the next byte to arrive... - IOPort('ConfigureSerialPort', p.com.serial, 'StartBackgroundRead=2'); - IOPort('Flush', p.com.serial); - %2 is the granularity of the data, cogent box sends 2 bytes. - %IOPort('ConfigureSerialPort', p.com.serial, 'ReadTimeout=5'); - - %%%%%%%%%%%%%%%%%%%%%%%%%%%Prepare the keypress queue listening. - p.ptb.device = -1; - p.ptb.keysOfInterest=zeros(1,256); - p.ptb.keysOfInterest(p.keys.confirm) = 1; - KbQueueCreate(p.ptb.device,p.ptb.keysOfInterest);%default device. - - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %prepare parallel port communication. This relies on cogent i - %think. We could do it with PTB as well. - config_io; - outp(p.com.lpt.address,0); - if( cogent.io.status ~= 0 ) - error('inp/outp installation failed'); - end - %test whether CED receives the triggers correctly... - k = 0; - while k ~= 49; - outp(p.com.lpt.address,p.com.lpt.InitExperiment);pause(0.1);outp(p.com.lpt.address,0);%247 means all but the UCS channel (so that we dont shock the subject during initialization). - fprintf('=================\nDid the trigger test work?\nPress 0 to send it again, 1 to continue...\n') - [~, k] = KbStrokeWait; - k = find(k); - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %load the pictures to the memory. - p.ptb.stim_sprites = CreateStimSprites(p.stim.files);% - - function [out]=CreateStimSprites(files) - %loads all the stims to video memory - for nStim = 1:p.stim.tFile - filename = files(nStim,:); - [im , ~, ~] = imread(filename); - out(nStim) = Screen('MakeTexture', p.ptb.w, im ); - end - end - end - function [t]=StopEyelinkRecording - Eyelink('StopRecording'); - t = GetSecs; - %this is the end of the trial scope. - WaitSecs(0.01); - Eyelink('Message', 'TRIAL_RESULT 0'); - % - WaitSecs(0.01); - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('Command', 'clear_screen %d', 0); - Screen('Textsize', p.ptb.w,p.text.fontsize); - Log(t,-8,NaN); - end - - function [t]=StartEyelinkRecording(nTrial,nStim,phase,dist,oddball,ucs,fix) - t = []; - if isnan(dist) - dist=3000; - end - nStim = double(nStim); - Eyelink('Message', 'TRIALID: %04d, PHASE: %04d, FILE: %04d, DELTACSP: %04d, ODDBALL: %04d, UCS: %04d, FIXX: %04d, FIXY %04d', nTrial, phase, nStim, dist, double(oddball), double(ucs),fix(1),fix(2)); - % an integration message so that an image can be loaded as - % overlay background when performing Data Viewer analysis. - WaitSecs(0.01); - %return - if nStim~=0 - Eyelink('Message', '!V IMGLOAD CENTER %s %d %d', p.stim.files(nStim,:), p.ptb.midpoint(1), p.ptb.midpoint(2)); - end - % This supplies the title at the bottom of the eyetracker display - Eyelink('Command', 'record_status_message "Stim: %02d, Phase: %d"', nStim, phase); - % - %Put the tracker offline and draw the stimuli. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - % clear tracker display and draw box at center - Eyelink('Command', 'clear_screen %d', 0); - %draw the image on the screen but also the two crosses - if (nStim <= 16 && nStim>0) - Eyelink('ImageTransfer',p.stim.files24(nStim,:),p.ptb.imrect(1),p.ptb.imrect(2),p.ptb.imrect(3),p.ptb.imrect(4),p.ptb.imrect(1),p.ptb.imrect(2)); - - end -% Eyelink('Command', 'draw_cross %d %d 15',p_ptb_CrossPositionET_x(1),p_ptb_CrossPositionET_y(1) ); -% Eyelink('Command', 'draw_cross %d %d 15',p_ptb_CrossPositionET_x(2),p_ptb_CrossPositionET_y(2) ); - Eyelink('Command', 'draw_cross %d %d 15',fix(1),fix(2)); - - % - %drift correction - %EyelinkDoDriftCorrection(el,crosspositionx,crosspositiony,0,0); - %start recording following mode transition and a short pause. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('StartRecording'); - t = GetSecs; - Log(t,8,NaN); - end - function shuffled = Shuffle(vector,N) - %takes first N from the SHUFFLED before outputting. This function - %could be used as a replacement for randsample - if nargin < 2;N = length(vector);end - [~, idx] = sort(rand([1 length(vector)])); - shuffled = vector(idx(1:N)); - shuffled = shuffled(:); - end - function Buzz - outp(p.com.lpt.address, p.com.lpt.digitimer ); - WaitSecs(p.duration.shockpulse); - outp(p.com.lpt.address, 0); - WaitSecs(p.duration.intershockpulse); - end - function MarkCED(socket,port) - %send pulse to SCR# - outp(socket,port); - WaitSecs(0.01); - outp(socket,0); - end - function InitEyeLink - % - if EyelinkInit(0)%use 0 to init normaly - fprintf('=================\nEyelink initialized correctly...\n') - else - fprintf('=================\nThere is problem in Eyelink initialization\n') - keyboard; - end - % - WaitSecs(0.5); - [~, vs] = Eyelink('GetTrackerVersion'); - fprintf('=================\nRunning experiment on a ''%s'' tracker.\n', vs ); - - %load 24bits pictures for eyelink... - dummy = dir([p.path.stim24 '*.bmp']); - p.stim.files24 = [repmat([fileparts(p.path.stim24) filesep],length(dummy),1) vertcat(dummy(:).name)]; - % - el = EyelinkInitDefaults(p.ptb.w); - %update the defaults of the eyelink tracker - el.backgroundcolour = p.stim.bg; - el.msgfontcolour = WhiteIndex(el.window); - el.imgtitlecolour = WhiteIndex(el.window); - el.targetbeep = 0; - el.calibrationtargetcolour = WhiteIndex(el.window); - el.calibrationtargetsize = 1.5; - el.calibrationtargetwidth = 0.5; - el.displayCalResults = 1; - el.eyeimgsize = 50; - el.waitformodereadytime = 25;%ms - el.msgfont = 'Times New Roman'; - el.cal_target_beep = [0 0 0];%[1250 0.6 0.05]; - %shut all sounds off - el.drift_correction_target_beep = [0 0 0]; - el.calibration_failed_beep = [0 0 0]; - el.calibration_success_beep = [0 0 0]; - el.drift_correction_failed_beep = [0 0 0]; - el.drift_correction_success_beep= [0 0 0]; - EyelinkUpdateDefaults(el); - %PsychEyelinkDispatchCallback(el) - - % open file. - res = Eyelink('Openfile', p.path.edf); - % - Eyelink('command', 'add_file_preamble_text ''Recorded by EyelinkToolbox FearCloud Experiment'''); - Eyelink('command', 'screen_pixel_coords = %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - Eyelink('message', 'DISPLAY_COORDS %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - % set calibration type. - Eyelink('command','auto_calibration_messages = YES'); - Eyelink('command', 'calibration_type = HV13'); - Eyelink('command', 'select_parser_configuration = 1'); - %what do we want to record - Eyelink('command', 'file_sample_data = LEFT,RIGHT,GAZE,HREF,AREA,GAZERES,STATUS,INPUT,HTARGET'); - Eyelink('command', 'file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON,INPUT'); - Eyelink('command', 'use_ellipse_fitter = no'); - % set sample rate in camera setup screen - Eyelink('command', 'sample_rate = %d',1000); - end - function StopEyelink(filename) - try - fprintf('Trying to stop the Eyelink system with StopEyelink\n'); - Eyelink('StopRecording'); - WaitSecs(0.5); - Eyelink('Closefile'); - display('receiving the EDF file...'); - Eyelink('ReceiveFile',filename,[p.path.subject '\eye\'],1); - display('...finished!') - % Shutdown Eyelink: - Eyelink('Shutdown'); - catch - display('StopEyeLink routine didn''t really run well'); - end - end - function cleanup - - % Close window: - sca; - %set back the old resolution - if strcmp(p.hostname,'triostim1') - Screen('Resolution',p.ptb.screenNumber, p.ptb.oldres.width, p.ptb.oldres.height ); - %show the cursor - ShowCursor(p.ptb.screenNumber); - end - % - IOPort('ConfigureSerialPort', p.com.serial,' StopBackgroundRead'); - IOPort('Close',p.com.serial); - commandwindow; - ListenChar(0); - KbQueueRelease(p.ptb.device); - end - function CalibrateEL - fprintf('=================\n=================\nEntering Eyelink Calibration\n') - p_var_ExpPhase = 0; - ShowInstruction(0,1); - EyelinkDoTrackerSetup(el); - %Returns 'messageString' text associated with result of last calibration - [~, messageString] = Eyelink('CalMessage'); - Eyelink('Message','%s',messageString);% - WaitSecs(0.05); - fprintf('=================\n=================\nNow we are done with the calibration\n') - end - function Log(ptb_time, event_type, event_info) - %Phases: - %Instruction : 1 - %Baseline : 2 - %Conditioning : 3 - %Test : 4 - %Rating : 5 - %Calibration : 0 - % - %event types are as follows: - % - %Scan Detection : 0 info: NaN; - %Cross Onset : 1 info: position - %Stimulus Onset/Offset: 2/-2 info: stim_id - %Cross Movement : 3 info: NaN; - %Stimulus Offset : -2 info: NaN; - %UCS Delivery : 4 info: NaN; - %Key Presses : 7 info: NaN; - %Tracker Onset/Offset : 8 info: NaN; - % - %Text on the screen : 5 info: Which Text? - %RatingScreen Onset : 6 info: NaN; - - p_var_event_count = p_var_event_count + 1; - %% - % - % for x = 1:10 - % disp(x) - % end - % - p.out.log(p_var_event_count,:) = [ptb_time event_type event_info p_var_ExpPhase]; - % % p.out.log(p.out.event_counter,:) - %logstring([ 'Logged: ' mat2str(p.out.log(p.out.event_counter,:)) ' - Type: ' p.verbose.eventtype{abs(event_type)} ' - Phase: ' p.verbose.eventphase{CurrentExperimentalPhase}]) - %for i = 1:3;subplot(3,1,i);plot(p.out.log(1:p.out.event_counter ,i),'o-');drawnow;end - % - - end - - -end diff --git a/FearGen_eyelab_PlaPil.m b/FearGen_eyelab_PlaPil.m deleted file mode 100644 index 7e280c4..0000000 --- a/FearGen_eyelab_PlaPil.m +++ /dev/null @@ -1,1131 +0,0 @@ -function [p]=FearGen_eyelab_PlaPil(subject,phase,csp,PainThreshold) -%[p]=Conditioning(subject,NthSeq,CSpface,phase,PainThreshold) -% -%Used for the last recording (3rd Scan Request) sessions of the Feargen -%project. Mainly different in loading the precomputed sequences... -% -% - -if nargin ~= 4 - fprintf('Wrong number of inputs\n'); - keyboard; -end - -csn = mod( csp + 8/2-1, 8)+1; -ListenChar(2);%disable pressed keys to be spitted around -commandwindow; -%clear everything -clear mex global functions -cgshut; -global cogent; -%%%%%%%%%%%load the GETSECS mex files so call them at least once -GetSecs; -WaitSecs(0.001); -% -el = []; -p = []; -SetParams; -fprintf('length: %d',length(p.presentation.cond_id)) -[p.presentation.cond_id'; p.presentation.stim_id'; p.presentation.ucs';p.presentation.oddball'] -unique(p.presentation.stim_id) -pause(5); -debug = 0;%debug mode -SetPTB; -% -%init all the variables -t = []; -nTrial = 0; -%% -%Time Storage -TimePulse1 = []; -TimePulse2 = []; -TimeStimOnset = []; -TimeCrossJumpTime = []; -TimeEndStim = []; -TimeStartShock = []; -TimeTrackerOff = []; -TimeTrackerOn = []; -TimeCrossOn = []; -p_var_ExpPhase = []; -p_var_event_count = 0; - - - -%% -InitEyeLink; -WaitSecs(2); -%calibrate if we are at the scanner computer. -if strcmp(p.hostname,'triostim1') || strcmp(p.hostname,'etpc'); - CalibrateEL; -end -%save again the parameter file -save(p.path.path_param,'p'); -if phase == 1 - ShowInstruction(1,1); - -elseif phase == 2 - % - p_var_ExpPhase = phase; - ShowInstruction(101,1); - ShowInstruction(2,1); - ShowInstruction(3,1); - ShowInstruction(4,1); - ConfirmIntensity; - ShowInstruction(5,1);%will wait for keypresses - PresentStimuli; - AskStimRating;%make sure that scanner doesnt stop prematurely asa the stim offset - -elseif phase == 3 - % - p_mrt_on = 0; - p_var_ExpPhase = phase; - % - ShowInstruction(6,1);%will not wait for keypresses - % - PresentStimuli; - % - %makee sure that scanner doesnt stop prematurely asa the stim offset - AskStimRating; -elseif phase == 4 - p_mrt_on = 0; - p_var_ExpPhase = phase; - % - ShowInstruction(6,1);%will not wait for keypresses - PresentStimuli; - %makee sure that scanner doesnt stop prematurely asa the stim offset - AskStimRating; - %makee sure that scanner doesnt stop prematurely asa the stim offset - fprintf('Finished with the rating\n'); - %AskWhichFace; -end - -%get the eyelink file back to this computer -StopEyelink(p.path.edf); -%trim the log file and save -p.out.log = p.out.log(sum(isnan(p.out.log),2) ~= size(p.out.log,2),:); -%shift the time so that the first timestamp is equal to zero -p.out.log(:,1) = p.out.log(:,1) - p.out.log(1); -p.out.log = p.out.log;%copy it to the output variable. -save(p.path.path_param,'p'); -% -%move the file to its final location. -movefile(p.path.subject,p.path.finalsubject); -%close everything down -cleanup; - - function ConfirmIntensity - %Compute the intensity we want to deliver to the subject. - - p.var.ShockIntensity = p.out.PainThreshold*p.out.ShockFactor; - - % - ShowInstruction(9,1); - % - fprintf([repmat('=',1,50) '\n']); - fprintf('TEST SHOCK:\n'); - fprintf('!!! ADJUST THE SHOCK INTENSITY ON THE DIGITIMER !!!\n'); - fprintf(' The intensity is now: %g mA\n',p.var.ShockIntensity); - fprintf(' Experimenter: Press any key to deliver a shock.\n'); - fprintf([repmat('=',1,50) '\n']); - % - [secs, keyCode, deltaSecs] = KbStrokeWait; - ShowInstruction(10,0);%shock is coming message... - t = GetSecs + p.duration.shock; - MarkCED( p.com.lpt.address, p.com.lpt.shock ); - while GetSecs < t; - Buzz; - end - % - message = 'Bewege den "Zeiger" mit der rechten und linken Pfeiltaste\n und bestätige deine Einschätzung mit der mit der oberen Pfeiltaste.'; - rect = [p.ptb.width*0.2 p.ptb.midpoint(2) p.ptb.width*0.6 100]; - response = RatingSlider(rect,2,1,p.keys.increase,p.keys.decrease,p.keys.confirm,{ 'nicht\nerträglich' 'erträglich'},message,0); - if response == 2 - fprintf('All is fine :)\n'); - fprintf('Subject confirmed the shock intensity inside the scanner...\n') - fprintf('INTENSITY TO BE USED FOR THE MAIN EXPERIMENT: %g mA\n',p.var.ShockIntensity); - p.out.ShockIntensity = p.var.ShockIntensity; - return; - elseif response == 1 - fprintf('Shit... :(, %g is too much for the subject\n',p.var.ShockIntensity); - fprintf('We will try a little milder intensity.\n'); - p.out.ShockFactor = p.out.ShockFactor - 0.05; - ConfirmIntensity; - end - - - end - function PresentStimuli - %Enter the presentation loop and wait for the first pulse to - %arrive. - - - - - - % - - TimeEndStim = GetSecs; - for nTrial = 1:p.presentation.tTrial; - % - %Get the variables that Trial function needs. - stim_id = p.presentation.stim_id(nTrial); - % - fix = p.presentation.CrossPosition(nTrial,:); - - ISI = p.presentation.isi(nTrial); - ucs = p.presentation.ucs(nTrial); - oddball = p.presentation.oddball(nTrial); - prestimdur = p.duration.prestim+rand(1)*.25; - dist = p.presentation.dist(nTrial); - %prestimdur = p_presentation_prestim_dur(nTrial); - - - fprintf('%d of %d, S: %d, ISI: %d, UCS: %d, ODD: %d.\n',nTrial,p.presentation.tTrial,stim_id,ISI,ucs,oddball); - % - - OnsetTime = TimeEndStim + ISI-p.duration.stim ; - - % jetz = GetSecs; - % if mod(nTrial,100) == 0 - % ShowInstruction(14,1); - % OnsetTime = OnsetTime + GetSecs - jetz; - % end - - KbQueueStart(p.ptb.device);%monitor keypresses... - - %Start with the trial, here is time-wise sensitive must be - %optimal - [TimeEndStim]= Trial(nTrial,OnsetTime, prestimdur, stim_id , ucs , fix , oddball,dist); - % - [keypressed, firstPress]=KbQueueCheck(p.ptb.device); - %if the press was after stimulus onset and before stimulus - %offset - if keypressed && (firstPress(p.keys.confirm) > OnsetTime) && (firstPress(p.keys.confirm) < TimeEndStim) - p.out.response(nTrial) = 1; - Log(firstPress(p.keys.confirm),7,NaN);%log the key press for hit detection. - fprintf('Subject Pressed the Hit Key!!\n'); - end -% if (phase == 4 && nTrial == ceil(p.presentation.tTrial/2)) -% ShowInstruction(14,1) -% CalibrateEL; -% end - end - end - function [TimeEndStim]=Trial(nTrial,TimeStimOnset , prestimdur, stim_id , ucs , fix , oddball, dist ) - %get all the times - TimeCrossOnset = TimeStimOnset - prestimdur; - TimeEndStim = TimeStimOnset + p.duration.stim; - TimeStartShock = TimeStimOnset + p.duration.onset2shock; - TimeTrackerOff = TimeStimOnset + p.duration.keep_recording; - - %% Fixation Onset - FixCross = [fix(1)-1,fix(2)-20,fix(1)+1,fix(2)+20;fix(1)-20,fix(2)-1,fix(1)+20,fix(2)+1]; - Screen('FillRect', p.ptb.w, [255,255,255], FixCross'); - TimeCrossOn = Screen('Flip',p.ptb.w,TimeCrossOnset,0); - MarkCED( p.com.lpt.address, p.com.lpt.FixOnset ); - Eyelink('Message', 'FX Onset at %d %d',fix(1),fix(2)); - Log(TimeCrossOn,1,stim_id);%cross onset. - %turn the eye tracker on - StartEyelinkRecording(nTrial,stim_id,p_var_ExpPhase,dist,oddball,ucs,fix); - - - - %% Draw the stimulus to the buffer - if ~stim_id==0 - Screen('DrawTexture', p.ptb.w, p.ptb.stim_sprites(stim_id)); - end - %Screen('DrawText' , p.ptb.w, double('+'), p.ptb.CrossPosition_x,fix, p.stim.white); -% if oddball%add freckles to the face -% x = randn(1,100)*35; -% y = randn(1,100)*10; -% s = rand(1,100);%[0 1] -% Screen('DrawDots',p.ptb.w,[x;y],1+s.*1.5,[100 100 100 160],p.ptb.midpoint,1); -% %the dots size -% end - Screen('DrawingFinished',p.ptb.w,0); - - %% STIMULUS ONSET - %Here we wait only for the next pulse. - %The proper amount is obtained with the second call of WaitPulse - %below, before the onset of the fixation cross. - %fprintf('Will Wait for the pulse to Stim Onset\n'); - TimeStimOnset = Screen('Flip',p.ptb.w,TimeStimOnset,0);%asap and dont clear - %send eyelink and ced a marker asap - Eyelink('Message', 'Stim Onset'); - Eyelink('Message', 'SYNCTIME'); - MarkCED( p.com.lpt.address, p.com.lpt.StimOnset ); - if oddball - MarkCED( p.com.lpt.address, p.com.lpt.oddball ); - end - Log(TimeStimOnset,2,stim_id);%log the stimulus onset - - - if ucs == 1 - %%%%%%%%%%%%%%%%%%%%%%% - %Deliver shock and stim off immediately - TimeStartShock = WaitSecs('UntilTime',TimeStartShock); - MarkCED( p.com.lpt.address, p.com.lpt.shock ); - Eyelink('Message', 'UCS Onset'); - - while GetSecs < TimeEndStim; - Buzz;%this is anyway sent to CED. - end - Eyelink('Message', 'UCS Offset'); - end - - %% STIM OFF immediately - TimeEndStim = Screen('Flip',p.ptb.w,TimeEndStim,0); - %send eyelink and ced a marker - Eyelink('Message', 'Stim Offset'); - Eyelink('Message', 'BLANK_SCREEN'); - Screen('Textsize', p.ptb.w,p.text.fontsize); - Log(TimeEndStim,-2,stim_id);%log the stimulus offset - % - %% record some more eye data after stimulus offset. - WaitSecs('UntilTime',TimeTrackerOff); - TimeTrackerOff = StopEyelinkRecording; - - - if oddball == 1 - fprintf('This was an oddball trial!\n'); - end - if ucs == 1 - fprintf('This was a UCS trial!\n'); - Log(TimeStartShock,4,NaN);%UCS delivery...This is done here to not waste time there - end - - end - - function SetParams - - % - p.var.timings = zeros(1,10); - p_var_event_count = 0; - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %relative path to stim and experiments - %Path Business. - [~, hostname] = system('hostname'); - p.hostname = deblank(hostname); - if strcmp(p.hostname,'triostim1') - p.path.baselocation = 'C:\USER\onat\Experiments\'; - elseif strcmp(p.hostname,'etpc') - p.path.baselocation = 'C:\Users\onat\Documents\Experiments\'; - else - p.path.baselocation = 'C:\Users\onat\Documents\Experiments\'; - end - - p.path.experiment = [p.path.baselocation 'plapil\']; - p.path.stim = 'C:\Users\onat\Documents\Experiments\plapil\stim\'; - p.path.stim24 = [p.path.stim '24bits' '\']; - % - p.subID = sprintf('sub%02d',subject); - p.path.edf = sprintf([p.subID 'p%02d' ],phase); - timestamp = datestr(now,30); - p.path.subject = [p.path.experiment 'data\tmp\' p.subID '_' timestamp '\']; - p.path.finalsubject = [p.path.experiment 'data\' p.subID '_' timestamp '\' ]; - %create folder hierarchy - mkdir(p.path.subject); - mkdir([p.path.subject 'scr']); - mkdir([p.path.subject 'eye']); - mkdir([p.path.subject 'stimulation']); - mkdir([p.path.subject 'midlevel']); - p.path.path_param = sprintf([regexprep(p.path.subject,'\\','\\\') 'stimulation\\param_phase_%02d'],phase); - - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %get stim files - [p.stim.files p.stim.label] = FileMatrix([p.path.stim '*.png']); - p.stim.tFile = size(p.stim.files,1);%number of different files (including the UCS symbol) - p.stim.tFace = p.stim.tFile - 1;%number of faces. - % - display([mat2str(p.stim.tFile) ' found in the destination.']); - %set the background gray according to the background of the stimuli - for i = 1:p.stim.tFile; - im = imread(p.stim.files(i,:)); - bg(i) = im(1,1,1); - end - %is all the captured bg values the same? - - if sum(diff(bg))==0; - %if so take it as the bg color - p.stim.bg = double([bg(1) bg(1) bg(1)]); - else - fprintf('background luminance was not successfully detected...\n') -% keyboard; - p.stim.bg = double([bg(1) bg(1) bg(1)]) - end - %bg of the rating screen. - p.stim.bg_rating = [0 128 0]; - % - %font size and background gray level - p.text.fontname = 'Times New Roman'; - p.text.fontsize = 18;%30; - p.text.fixsize = 60; - %rating business - p.rating.division = 10;%number of divisions for the rating slider - p.rating.repetition = 2;%how many times a given face has to be repeated... - % - p.stim.white = [255 255 255]; - %get the actual stim size (assumes all the same) - info = imfinfo(p.stim.files(1,:)); - p.stim.width = info.Width; - p.stim.height = info.Height; - - if strcmp(p.hostname,'triostim1') - p.keys.confirm = KbName('7'); - p.keys.increase = KbName('8'); - p.keys.decrease = KbName('6'); - p.keys.space = KbName('space'); - p.keys.esc = KbName('esc'); - else - %All settings for laptop computer. - p.keys.confirm = KbName('up'); - p.keys.increase = KbName('right'); - p.keys.decrease = KbName('left'); - p.keys.space = KbName('space'); - p.keys.esc = KbName('esc'); - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %Communication business - %parallel port - p.com.lpt.address = 888; - %codes for different events - p.com.lpt.InitExperiment = 64;%which is all channels without digitimer - p.com.lpt.FixOnset = 4; - p.com.lpt.StimOnset = 8; - p.com.lpt.shock = 16; - p.com.lpt.oddball = 32; - p.com.lpt.keypress = 2; - p.com.lpt.digitimer = 128; - % - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %timing business - %these are the intervals of importance - %time2fixationcross->cross2onset->onset2shock->shock2offset - %these (duration.BLA) are average duration values: - p.duration.stim = 1.0;%2;%s - p.duration.shock = 0.1;%s;x - p.duration.shockpulse = 0.005;%ms; duration of each individual pulses - p.duration.intershockpulse = 0.01;%ms; and the time between each pulse - p.duration.onset2shock = p.duration.stim - p.duration.shock; - p.duration.crossmoves = p.duration.stim./2; - p.duration.keep_recording = 0.25;%this is the time we will keep recording (eye data) after stim offset. - p.duration.prestim_ori = .95; - %p.duration.prestim = 2-p.duration.prestim_ori;%that is 0.95 seconds - p.duration.prestim = .85; - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %stimulus sequence - if ismember(phase,[3 4]) - seqpool = load('C:\Users\onat\Documents\Experiments\feargen_master\seq\seq.mat'); - seq = seqpool.s(phase,csp,RandSample(1:size(seqpool.s,3),[1 1])); - clear seqpool - fprintf('Recomputing FixCrosses...\n') - dummycp = seq_feargen_fixcross(seq); - seq.CrossPosition = dummycp; - elseif phase == 2 - clear seq - seq.cond_id = Shuffle([0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10]); - while any(diff(seq.cond_id)==0) - seq.cond_id = Shuffle([0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10]); - end - seq.ucs = seq.cond_id ==9; - seq.oddball = seq.cond_id == 10; - seq.isi = repmat(3,size(seq.cond_id)); - seq.stim_id = seq.cond_id; - - seq.tTrial = length(seq.cond_id); - seq.tFacetrial = sum(ismember(seq.cond_id,1:8)); - seq.dist = MinimumAngle((seq.stim_id-1)*45,(csp-1)*45); - seq.dist(seq.cond_id==0)=NaN; - %oddball=1000 - seq.dist(seq.cond_id==10)=1000; - %ucs=500 - seq.dist(seq.cond_id==9)=500; - - dummycp = seq_feargen_fixcross(seq); - seq.CrossPosition = dummycp; - else - fprintf('Please chose correct phase option (2 - baseline, 3 - cond, 4 - test)') - - end -% if phase == 2 -% seq = seq_feargen_cloudseq(csp,'baseline');%only 1 short seq -% elseif phase == 3%conditioning -% seq = seq_feargen_cloudseq(csp,'cond');%gets 1 short seq -% elseif phase == 4 -% seq = seq_feargen_cloudseq(csp,'test');%gets 2 short seqs -% end - %create the randomized design - p.stim.cs_plus = csp;%index of cs stimulus, this is the one paired to shock - p.stim.cs_neg = csn; - %Record which Phase are we going to run in this run. - p.stim.phase = phase; - %this will deal all the presentation sequence related information - p.presentation = seq; - - p.out.rating = []; - p.out.log = zeros(1000000,4).*NaN; - p.out.response = zeros(p.presentation.tTrial,1); - p.out.PainThreshold = PainThreshold; - p.out.ShockFactor = 2; - %Save the stuff - save(p.path.path_param,'p'); - % - function [FM labels] = FileMatrix(path) - %Takes a path with file extension associated to regexp (e.g. - %C:\blabl\bla\*.bmp) returns the file matrix - dummy = dir(path); - FM = [repmat([fileparts(path) filesep],length(dummy),1) vertcat(dummy(:).name)]; - labels = {dummy(:).name}; - end - end - function AskStimRating - - MarkCED( p.com.lpt.address, p.com.lpt.InitExperiment); - % - p_var_ExpPhase = 5; - BG = p.stim.bg;% - p.stim.bg = p.stim.bg_rating; - nseq = 0; - rating_seq = []; - pos1_seq = []; - % - while nseq < p.rating.repetition - nseq = nseq + 1; - rating_seq = [ rating_seq Shuffle(1:p.stim.tFile-2)']; - end - message = GetText(11); - SliderTextL = GetText(13); - SliderTextR = GetText(12); - % - Screen('FillRect', p.ptb.w , p.stim.bg); - Screen('Flip',p.ptb.w); - WaitSecs(2); - % - ShowInstruction(7,1); - rect = [p.ptb.width*0.2 p.ptb.midpoint(2) p.ptb.width*0.6 100]; - tRatend = length(rating_seq); - %save the rating sequence just for security - p.out.rating_seq = rating_seq; - - for nRatend = 1:tRatend; - % - %the variable that are used by Trial function - stim_id = rating_seq(nRatend); - - fix = p.presentation.CrossPosition(nRatend,:); - % - next_stim_id = [];%this is a trick, otherwise a fixation cross appears right before the rating :( - next_pos1 = []; - - %to send know the distance here, little dummy setup: - dummy = -135:45:180; - dist = dummy(stim_id); - %We will turn on the fixation cross and start the tracker - %for the first trial. These have to be done before the main - %for loop. - FixCross = [fix(1)-1,fix(2)-20,fix(1)+1,fix(2)+20;fix(1)-20,fix(2)-1,fix(1)+20,fix(2)+1]; - Screen('FillRect', p.ptb.w, [255,255,255], FixCross'); - t = Screen('Flip',p.ptb.w); - Screen('Textsize', p.ptb.w,p.text.fontsize); - % - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %Mark the onset - Eyelink('Message', 'FX Onset at %d %d',fix(1),fix(2)); - Log(t,1,fix(1));%log the mark onset... - Log(t,1,fix(2)) - - % - Trial(1000+nRatend,GetSecs+1,0.5,stim_id,0,fix,0,dist); - rate(nRatend,1) = RatingSlider(rect, p.rating.division, Shuffle(1:p.rating.division,1), p.keys.increase, p.keys.decrease, p.keys.confirm, {SliderTextL{1} SliderTextR{1}},message,1); - - %%%%%%%%%%%%%%%%%%%%%%%%%%%% - %Verbose the rating of the subject - fprintf('============\nRating Results %d (%d/%d):\n', stim_id, nRatend, tRatend); - dummy = rating_seq(1:nRatend);%trials shown so far - for iii = 1:p.stim.tFile-2 - r = round(mean(rate(dummy == iii))); - if isnan(r) - r = 0; - end - if iii == p.stim.cs_plus - fprintf('Stimulus %02d: * %s \n',iii,repmat('+',1,1+r)); - else - fprintf('Stimulus %02d: %s \n',iii,repmat('+',1,1+r)); - end - end - end - %sort the stim_ids and then sort the same the rates and make a - %matrix out of that to store - [~, i] = sort(rating_seq); - rate = reshape(rate(i),p.rating.repetition,p.stim.tFile-2)'; - p.out.rating = rate; - save(p.path.path_param,'p'); - Screen('FillRect',p.ptb.w,p.stim.bg); - p.stim.bg = BG; - % - save(p.path.path_param,'p'); - end - function [rating] = RatingSlider(rect,tSection,position,up,down,confirm,labels,message,numbersOn) - % - %Detect the bounding boxes of the labels. - for nlab = 1:2 - [~ , ~, bb(nlab,:)]=DrawFormattedText(p.ptb.w,labels{nlab}, 'center', 'center', p.stim.white,[],[],[],2); - Screen('FillRect',p.ptb.w,p.stim.bg); - end - bb = max(bb); - bb_size = bb(3)-bb(1);%vertical size of the bb. - % - DrawSkala; - ok = 1; - while ok == 1 - [secs, keyCode, ~] = KbStrokeWait; - keyCode = find(keyCode); - Log(secs,7,keyCode); - if length(keyCode) == 1%this loop avoids crashes to accidential presses of meta keys - if (keyCode == up) || (keyCode == down) - next = position + increment(keyCode); - if next < (tSection+1) && next > 0 - position = position + increment(keyCode); - %rating = tSection - position + 1; - end - DrawSkala; - elseif keyCode == confirm - MarkCED( p.com.lpt.address, p.com.lpt.keypress); - WaitSecs(0.1); - ok = 0; - Screen('FillRect',p.ptb.w,p.stim.bg); - t=Screen('Flip',p.ptb.w); - end - end - end - - function DrawSkala - %rating = tSection - position + 1; - rating = position ; - increment([up down]) = [1 -1];%delta - tick_x = linspace(rect(1),rect(1)+rect(3),tSection+1);%tick positions - tick_size = rect(3)./tSection; - ss = tick_size/5*0.9;%slider size. - % - for tick = 1:length(tick_x)%draw ticks - Screen('DrawLine', p.ptb.w, [255 0 0], tick_x(tick), rect(2), tick_x(tick), rect(2)+rect(4) , 3); - if tick <= tSection && numbersOn - Screen('TextSize', p.ptb.w,p.text.fontsize./2); - DrawFormattedText(p.ptb.w, mat2str(tick) , tick_x(tick)+ss/2, rect(2)+rect(4), p.stim.white); - Screen('TextSize', p.ptb.w,p.text.fontsize); - end - if tick == 1 - DrawFormattedText(p.ptb.w, labels{1},tick_x(tick)-bb_size*1.4,rect(2), p.stim.white); - elseif tick == tSection+1 - DrawFormattedText(p.ptb.w, labels{2},tick_x(tick)+bb_size*0.4,rect(2), p.stim.white); - end - end - %slider coordinates - slider = [ tick_x(position)+tick_size*0.1 rect(2) tick_x(position)+tick_size*0.9 rect(2)+rect(4)]; - %draw the slider - Screen('FillRect',p.ptb.w, p.stim.white, round(slider)); - Screen('TextSize', p.ptb.w,p.text.fontsize./2); - DrawFormattedText(p.ptb.w,message, 'center', p.ptb.midpoint(2)*0.2, p.stim.white,[],[],[],2); - Screen('TextSize', p.ptb.w,p.text.fontsize); - t = Screen('Flip',p.ptb.w); - Log(t,6,NaN); - end - end - function ShowInstruction(nInstruct,waitforkeypress) - %ShowInstruction(nInstruct,waitforkeypress) - %if waitforkeypress is 1, then subject has to press a button to - %make the instruction text dissappear. Otherwise you have to take - %care of it later - - [text]= GetText(nInstruct); - ShowText(text); - %let subject read it and ask confirmation to proceed. But we don't - %need that in the case of INSTRUCT = 5; - if waitforkeypress - if nInstruct ~= 10%this is for the Reiz kommnt - KbStrokeWait; - else - WaitSecs(2.5+rand(1)); - end - Screen('FillRect',p.ptb.w,p.stim.bg); - t = Screen('Flip',p.ptb.w); - Log(t,-5,nInstruct); - else - if nInstruct ~= 10%this is for the Reiz kommnt - KbStrokeWait; - else - WaitSecs(1+rand(1)); - end - end - - - function ShowText(text) - - Screen('FillRect',p.ptb.w,p.stim.bg); - %DrawFormattedText(p.ptb.w, text, p.text.start_x, 'center',p.stim.white,[],[],[],2,[]); - DrawFormattedText(p.ptb.w, text, 'center', 'center',p.stim.white,[],[],[],2,[]); - t=Screen('Flip',p.ptb.w); - Log(t,5,nInstruct); - %show the messages at the experimenter screen - fprintf('=========================================================\n'); - fprintf('Text shown to the subject:\n'); - fprintf('=========================================================\n'); - fprintf(text); - fprintf('=========================================================\n'); - - end - end - function [text]=GetText(nInstruct) - if nInstruct == 0%Eyetracking calibration - - text = ['Um Ihre Augenbewegungen zu messen, \n' ... - 'müssen wir jetzt den Eye-Tracker kalibrieren.\n' ... - 'Dazu zeigen wir Ihnen einige Punkte auf dem Bildschirm, \n' ... - 'bei denen Sie sich wie folgt verhalten:\n' ... - 'Bitte fixieren Sie den kleinen weißen Kreis und \n' ... - 'bleiben so lange darauf, wie es zu sehen ist.\n' ... - 'Bitte drücken Sie jetzt den oberen Knopf, \n' ... - 'um mit der Kalibrierung weiterzumachen.\n' ... - ]; - - elseif nInstruct == 1%first Instr. of the training phase. - text = ['Wir werden nun als erstes einen Übungsdurchgang machen,\n' ... - 'damit Sie sich an Ihre Aufgabe gewöhnen können.\n' ... - 'In diesem Durchgang können Sie sich vollkommen sicher fühlen,\n' ... - 'es werden keine elektrischen Reize verabreicht.\n' ... - 'Eine wichtige grundsätzliche Regel ist, dass Sie das Fixationskreuz (das „+“)\n' ... - 'wenn es zu sehen ist, mit Ihren Augen fixieren. \n' ... - 'Drücken Sie die obere Taste um fortzufahren.\n' ... - ]; - elseif nInstruct == 101%first Instr. of the training phase. - text = ['Willkommen zum zweiten Teil des Experiments.\n'... - 'Eine wichtige grundsätzliche Regel ist auch hier,\n'... - 'dass Sie das Fixationskreuz (das „+“)\n' ... - 'wenn es zu sehen ist, mit Ihren Augen fixieren. \n' ... - 'Drücken Sie die obere Taste um fortzufahren.\n' ... - ]; - elseif nInstruct == 2%second Instr. of the training phase. - text = ['Ein paar Bemerkungen zu den Zielreizen: \n' ... - 'Zur Erinnerung: Der Zielreiz ist das in der Instruktion gesehene Muster.\n' ... - 'Sobald ein solcher Zielreiz erscheint, \n' ... - 'sollen Sie schnellstmöglich die obere Taste drücken, \n' ... - 'und zwar bevor der Reiz wieder verschwunden ist \n' ... - '(Sie müssen also sehr schnell und aufmerksam sein).' ... - ]; - elseif nInstruct == 3%third Instr. of the training phase. - text = ['Es ist sehr wichtig, dass Sie Ihren Kopf während \n' ... - 'des Experiments nicht bewegen. \n' ... - 'Das ist besonders wichtig für die Qualität der Messung.\n' ... - ]; - elseif nInstruct == 4%third Instr. of the training phase. - text = ['Vor dem Experiment legen wir nun \n' ... - 'die Schockintensität für den Rest des Experiments fest. \n' ... - 'Drücken Sie die obere Taste um fortzufahren.' ... - ]; - - elseif nInstruct == 5%Baseline Phase - % - % - %=================================================================================================================% - text = ['Jetzt geht es mit dem Experiment los.\n' ... - 'Ihre Aufgabe ist es jetzt, die Muster, \n' ... - 'die Ihnen gezeigt werden aufmerksam zu betrachten und \n' ... - 'den oberen Knopf zu drücken, sobald Sie einen Zielreiz sehen.\n' ... - '\n'... - 'Hin und wieder erscheint ein Symbol (ein Blitzpfeil, der vor Strom warnt), \n' ... - 'das einen elektrischen Reiz ankündigt. \n' ... - 'Die Reize erfolgen aber nur bei diesem Symbol, nicht bei den Mustern! \n' ... - 'Bei den Mustern können Sie sich also sicher fühlen.\n' ... - 'Bitte denken Sie daran: 1. Fixationskreuz fixieren und 2. nicht bewegen!\n\n' ... - 'Sie können das Experiment nun durch Drücken der oberen Taste starten. \n' ... - ]; - - elseif nInstruct == 6%Test and Conditioning Phase - %=================================================================================================================% - text = ['Auch im nun folgenden Teil des Experiments \n' ... - 'sollen Sie die Muster aufmerksam betrachten und \n' ... - 'den oberen Knopf drücken, sobald Sie einen Zielreiz sehen. \n' ... - 'Wie im ersten Teil des Experiments sollen Sie \n' ... - 'das Fixationskreuz immer fixieren. \n' ... - 'In dieser Phase des Experiments werden Sie\n' ... - 'gelegentlich elektrische Reize bekommen.\n\n' ... - 'Die elektrischen Reize folgen jetzt auf ein bestimmtes Muster. \n' ... - - ]; - - - elseif nInstruct == 7;%rating - text = ['In dieser Phase hätten wir gerne, dass Sie die Muster\n'... - 'im Hinblick auf folgende Frage bewerten:\n'... - '„Wie wahrscheinlich ist es, bei dem gerade gesehenen Muster \n'... - 'einen elektrischen Schock zu erhalten?“\n'... - 'Bewegen Sie den Zeiger mit der rechten und linken Pfeiltaste \n'... - 'und bestätigen Sie Ihre Einschätzung mit der oberen Pfeiltaste.\n'... - ]; - - elseif nInstruct == 8 %CS+ detection - text = ['Du bekommen nun eine Reihe von Mustern gezeigt.\n' ... - 'Bitte wählen Sie das Muster aus bei dem der Schock verabreicht wurde.\n'... - 'Drücken Sie die obere Taste um fortzufahren.\n'... - ]; - elseif nInstruct == 9% - %=================================================================================================================% - text = ['Bitte geben Sie an, ob die Reizstärke des folgenden Schocks\n für Sie erträglich ist.\n'... - '\n'... - 'Drücken Sie bitte die obere Taste um den Reiz zu bekommen.\n'... - ]; - - elseif nInstruct == 10%just before the shock - text = ['Reiz kommt...\n']; - elseif nInstruct == 11%this is the rating question - text = ['Wie wahrscheinlich ist es, bei dem gerade gesehenen Muster \n'... - 'einen elektrischen Schock zu erhalten?“\n' ... - 'Bewegen Sie den "Zeiger" mit der rechten und linken Pfeiltaste\n' ... - 'und bestätigen Sie Ihre Einschätzung mit der mit der oberen Pfeiltaste'... - ]; - elseif nInstruct == 12 %These two below are the possible responses to the question in 11 - text = {'Sehr\nwahrscheinlich'}; - elseif nInstruct == 13 - text = {'Überhaupt\nnicht\nwahrscheinlich'}; - elseif nInstruct == 14 - text = ['Bitte machen Sie eine kurze Pause.\n' ... - 'Sie können hierbei gern die Augen einen Moment schließen.\n'... - 'Drücken Sie anschließend die obere Taste um fortzufahren.\n'... - 'Wir werden dann den Eyetracker noch einmal kalibrieren.\n'... - ]; - else - text = {''}; - end - end - function SetPTB - %Sets the parameters related to the PTB toolbox. Including - %fontsizes, font names. - %Find the number of the screen to be opened - screens = Screen('Screens'); - p.ptb.screenNumber = 1;%the maximum is the second monitor - %Make everything transparent for debugging purposes. - if debug - commandwindow; - PsychDebugWindowConfiguration; - end - %Default parameters - Screen('Preference', 'SkipSyncTests', 1); - Screen('Preference', 'DefaultFontSize', p.text.fontsize); - Screen('Preference', 'DefaultFontName', p.text.fontname); - Screen('Preference', 'TextAntiAliasing',2);%enable textantialiasing high quality - Screen('Preference', 'VisualDebuglevel', 0); - Screen('Preference', 'SkipSyncTests', 1); - Screen('Preference', 'SuppressAllWarnings', 1); - %set the resolution correctly - if strcmp(p.hostname,'triostim1') - p.ptb.oldres = Screen('resolution',p.ptb.screenNumber,1280,960); - %hide the cursor - HideCursor(p.ptb.screenNumber); - elseif strcmp(p.hostname,'etpc') - p.ptb.oldres = Screen('resolution',p.ptb.screenNumber,1600,1200); - %hide the cursor - HideCursor(p.ptb.screenNumber); - end - - %Open a graphics window using PTB - p.ptb.w = Screen('OpenWindow', p.ptb.screenNumber, p.stim.bg); - Screen('BlendFunction', p.ptb.w, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - Screen('Flip',p.ptb.w);%make the bg - p.ptb.slack = Screen('GetFlipInterval',p.ptb.w)./2; - [p.ptb.width, p.ptb.height] = Screen('WindowSize', p.ptb.screenNumber); - if sum([p.ptb.width p.ptb.height] - [1280 960]) ~= 0 - fprintf('SET THE CORRECT SCREEN RESOLUTION\n'); - end - %find the mid position on the screen. - p.ptb.midpoint = [ p.ptb.width./2 p.ptb.height./2]; - p.ptb.imrect = [ p.ptb.midpoint(1)-p.stim.width/2 p.ptb.midpoint(2)-p.stim.height/2 p.stim.width p.stim.height]; - % %compute the cross position. - % [~, ny bb] = DrawFormattedText(p.ptb.w,'+','center','center'); - % p.ptb.cross_shift = [45 60];%incremental upper and lower cross positions - % p.ptb.CrossPosition_y = p.ptb.midpoint(2)%[ny-p.ptb.cross_shift(1) ny+p.ptb.cross_shift(2) ]; - p.ptb.CrossPosition_x = p.ptb.midpoint(1);%bb(1);%always the same - % %cross position for the eyetracker screen. - % p.ptb.CrossPositionET_x = [p.ptb.midpoint(1) p.ptb.midpoint(1)]; - % p.ptb.CrossPositionET_y = [p.ptb.midpoint(2)-p.ptb.cross_shift(2) p.ptb.midpoint(2)+p.ptb.cross_shift(2)]; - % %% - [nx, ny bb] = DrawFormattedText(p.ptb.w,'+','center','center'); - - - %cross position for the eyetracker screen. -% p.ptb.CrossPositionET_x = [p.ptb.midpoint(1) p.ptb.midpoint(1)]; -% p.ptb.CrossPositionET_y = [p.ptb.midpoint(2)-p.ptb.cross_shift(2) p.ptb.midpoint(2)+p.ptb.cross_shift(2)]; - %% - %priorityLevel=MaxPriority(['GetSecs'],['KbCheck'],['KbWait'],['GetClicks']); - Priority(MaxPriority(p.ptb.w)); - %this is necessary for the Eyelink calibration - InitializePsychSound(0) - %sound('Open') - Beeper(5000) - - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %set serial communication channels - IOPort('CloseAll'); - p.com.serial = IOPort('OpenSerialPort', 'COM1', 'InputBufferSize=51840000 HardwareBufferSizes=32768,32768 Terminator=0 ReceiveLatency=0.0001 BaudRate=9600 ReceiveTimeout=7'); - IOPort('ConfigureSerialPort', p.com.serial, 'BlockingBackgroundRead=1'); - %because of the BlockingBackgroundRead=1, the flush and close all - %command will wait for the next byte to arrive... - IOPort('ConfigureSerialPort', p.com.serial, 'StartBackgroundRead=2'); - IOPort('Flush', p.com.serial); - %2 is the granularity of the data, cogent box sends 2 bytes. - %IOPort('ConfigureSerialPort', p.com.serial, 'ReadTimeout=5'); - - %%%%%%%%%%%%%%%%%%%%%%%%%%%Prepare the keypress queue listening. - p.ptb.device = -1; - p.ptb.keysOfInterest=zeros(1,256); - p.ptb.keysOfInterest(p.keys.confirm) = 1; - KbQueueCreate(p.ptb.device,p.ptb.keysOfInterest);%default device. - - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %prepare parallel port communication. This relies on cogent i - %think. We could do it with PTB as well. - config_io; - outp(p.com.lpt.address,0); - if( cogent.io.status ~= 0 ) - error('inp/outp installation failed'); - end - %test whether CED receives the triggers correctly... - k = 0; - while k ~= 49; - outp(p.com.lpt.address,p.com.lpt.InitExperiment);pause(0.1);outp(p.com.lpt.address,0);%247 means all but the UCS channel (so that we dont shock the subject during initialization). - fprintf('=================\nDid the trigger test work?\nPress 0 to send it again, 1 to continue...\n') - [~, k] = KbStrokeWait; - k = find(k); - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %load the pictures to the memory. - p.ptb.stim_sprites = CreateStimSprites(p.stim.files);% - - function [out]=CreateStimSprites(files) - %loads all the stims to video memory - for nStim = 1:p.stim.tFile - filename = files(nStim,:); - [im , ~, ~] = imread(filename); - out(nStim) = Screen('MakeTexture', p.ptb.w, im ); - end - end - end - function [t]=StopEyelinkRecording - Eyelink('StopRecording'); - t = GetSecs; - %this is the end of the trial scope. - WaitSecs(0.01); - Eyelink('Message', 'TRIAL_RESULT 0'); - % - WaitSecs(0.01); - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('Command', 'clear_screen %d', 0); - Screen('Textsize', p.ptb.w,p.text.fontsize); - Log(t,-8,NaN); - end - - function [t]=StartEyelinkRecording(nTrial,nStim,phase,dist,oddball,ucs,fix) - t = []; - if isnan(dist) - dist=3000; - end - nStim = double(nStim); - Eyelink('Message', 'TRIALID: %04d, PHASE: %04d, FILE: %04d, DELTACSP: %04d, ODDBALL: %04d, UCS: %04d, FIXX: %04d, FIXY %04d', nTrial, phase, nStim, dist, double(oddball), double(ucs),fix(1),fix(2)); - % an integration message so that an image can be loaded as - % overlay background when performing Data Viewer analysis. - WaitSecs(0.01); - %return - if nStim~=0 - Eyelink('Message', '!V IMGLOAD CENTER %s %d %d', p.stim.files(nStim,:), p.ptb.midpoint(1), p.ptb.midpoint(2)); - end - % This supplies the title at the bottom of the eyetracker display - Eyelink('Command', 'record_status_message "Stim: %02d, Phase: %d"', nStim, phase); - % - %Put the tracker offline and draw the stimuli. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - % clear tracker display and draw box at center - Eyelink('Command', 'clear_screen %d', 0); - %draw the image on the screen but also the two crosses - if (nStim <= 16 && nStim>0) - Eyelink('ImageTransfer',p.stim.files24(nStim,:),p.ptb.imrect(1),p.ptb.imrect(2),p.ptb.imrect(3),p.ptb.imrect(4),p.ptb.imrect(1),p.ptb.imrect(2)); - - end -% Eyelink('Command', 'draw_cross %d %d 15',p_ptb_CrossPositionET_x(1),p_ptb_CrossPositionET_y(1) ); -% Eyelink('Command', 'draw_cross %d %d 15',p_ptb_CrossPositionET_x(2),p_ptb_CrossPositionET_y(2) ); - Eyelink('Command', 'draw_cross %d %d 15',fix(1),fix(2)); - - % - %drift correction - %EyelinkDoDriftCorrection(el,crosspositionx,crosspositiony,0,0); - %start recording following mode transition and a short pause. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('StartRecording'); - t = GetSecs; - Log(t,8,NaN); - end - function shuffled = Shuffle(vector,N) - %takes first N from the SHUFFLED before outputting. This function - %could be used as a replacement for randsample - if nargin < 2;N = length(vector);end - [~, idx] = sort(rand([1 length(vector)])); - shuffled = vector(idx(1:N)); - shuffled = shuffled(:); - end - function Buzz - outp(p.com.lpt.address, p.com.lpt.digitimer ); - WaitSecs(p.duration.shockpulse); - outp(p.com.lpt.address, 0); - WaitSecs(p.duration.intershockpulse); - end - function MarkCED(socket,port) - %send pulse to SCR# - outp(socket,port); - WaitSecs(0.01); - outp(socket,0); - end - function InitEyeLink - % - if EyelinkInit(0)%use 0 to init normaly - fprintf('=================\nEyelink initialized correctly...\n') - else - fprintf('=================\nThere is problem in Eyelink initialization\n') - keyboard; - end - % - WaitSecs(0.5); - [~, vs] = Eyelink('GetTrackerVersion'); - fprintf('=================\nRunning experiment on a ''%s'' tracker.\n', vs ); - - %load 24bits pictures for eyelink... - dummy = dir([p.path.stim24 '*.bmp']); - p.stim.files24 = [repmat([fileparts(p.path.stim24) filesep],length(dummy),1) vertcat(dummy(:).name)]; - % - el = EyelinkInitDefaults(p.ptb.w); - %update the defaults of the eyelink tracker - el.backgroundcolour = p.stim.bg; - el.msgfontcolour = WhiteIndex(el.window); - el.imgtitlecolour = WhiteIndex(el.window); - el.targetbeep = 0; - el.calibrationtargetcolour = WhiteIndex(el.window); - el.calibrationtargetsize = 1.5; - el.calibrationtargetwidth = 0.5; - el.displayCalResults = 1; - el.eyeimgsize = 50; - el.waitformodereadytime = 25;%ms - el.msgfont = 'Times New Roman'; - el.cal_target_beep = [0 0 0];%[1250 0.6 0.05]; - %shut all sounds off - el.drift_correction_target_beep = [0 0 0]; - el.calibration_failed_beep = [0 0 0]; - el.calibration_success_beep = [0 0 0]; - el.drift_correction_failed_beep = [0 0 0]; - el.drift_correction_success_beep= [0 0 0]; - EyelinkUpdateDefaults(el); - %PsychEyelinkDispatchCallback(el) - - % open file. - res = Eyelink('Openfile', p.path.edf); - % - Eyelink('command', 'add_file_preamble_text ''Recorded by EyelinkToolbox FearCloud Experiment'''); - Eyelink('command', 'screen_pixel_coords = %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - Eyelink('message', 'DISPLAY_COORDS %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - % set calibration type. - Eyelink('command','auto_calibration_messages = YES'); - Eyelink('command', 'calibration_type = HV13'); - Eyelink('command', 'select_parser_configuration = 1'); - %what do we want to record - Eyelink('command', 'file_sample_data = LEFT,RIGHT,GAZE,HREF,AREA,GAZERES,STATUS,INPUT,HTARGET'); - Eyelink('command', 'file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON,INPUT'); - Eyelink('command', 'use_ellipse_fitter = no'); - % set sample rate in camera setup screen - Eyelink('command', 'sample_rate = %d',1000); - end - function StopEyelink(filename) - try - fprintf('Trying to stop the Eyelink system with StopEyelink\n'); - Eyelink('StopRecording'); - WaitSecs(0.5); - Eyelink('Closefile'); - display('receiving the EDF file...'); - Eyelink('ReceiveFile',filename,[p.path.subject '\eye\'],1); - display('...finished!') - % Shutdown Eyelink: - Eyelink('Shutdown'); - catch - display('StopEyeLink routine didn''t really run well'); - end - end - function cleanup - - % Close window: - sca; - %set back the old resolution - if strcmp(p.hostname,'triostim1') - Screen('Resolution',p.ptb.screenNumber, p.ptb.oldres.width, p.ptb.oldres.height ); - %show the cursor - ShowCursor(p.ptb.screenNumber); - end - % - IOPort('ConfigureSerialPort', p.com.serial,' StopBackgroundRead'); - IOPort('Close',p.com.serial); - commandwindow; - ListenChar(0); - KbQueueRelease(p.ptb.device); - end - function CalibrateEL - fprintf('=================\n=================\nEntering Eyelink Calibration\n') - p_var_ExpPhase = 0; - ShowInstruction(0,1); - EyelinkDoTrackerSetup(el); - %Returns 'messageString' text associated with result of last calibration - [~, messageString] = Eyelink('CalMessage'); - Eyelink('Message','%s',messageString);% - WaitSecs(0.05); - fprintf('=================\n=================\nNow we are done with the calibration\n') - end - function Log(ptb_time, event_type, event_info) - %Phases: - %Instruction : 1 - %Baseline : 2 - %Conditioning : 3 - %Test : 4 - %Rating : 5 - %Calibration : 0 - % - %event types are as follows: - % - %Scan Detection : 0 info: NaN; - %Cross Onset : 1 info: position - %Stimulus Onset/Offset: 2/-2 info: stim_id - %Cross Movement : 3 info: NaN; - %Stimulus Offset : -2 info: NaN; - %UCS Delivery : 4 info: NaN; - %Key Presses : 7 info: NaN; - %Tracker Onset/Offset : 8 info: NaN; - % - %Text on the screen : 5 info: Which Text? - %RatingScreen Onset : 6 info: NaN; - - p_var_event_count = p_var_event_count + 1; - %% - % - % for x = 1:10 - % disp(x) - % end - % - p.out.log(p_var_event_count,:) = [ptb_time event_type event_info p_var_ExpPhase]; - % % p.out.log(p.out.event_counter,:) - %logstring([ 'Logged: ' mat2str(p.out.log(p.out.event_counter,:)) ' - Type: ' p.verbose.eventtype{abs(event_type)} ' - Phase: ' p.verbose.eventphase{CurrentExperimentalPhase}]) - %for i = 1:3;subplot(3,1,i);plot(p.out.log(1:p.out.event_counter ,i),'o-');drawnow;end - % - - end - - -end diff --git a/FeargenSequence_ET.m b/FeargenSequence_ET.m deleted file mode 100644 index 62219b0..0000000 --- a/FeargenSequence_ET.m +++ /dev/null @@ -1,203 +0,0 @@ -function [seq]=FeargenSequence_ET(face_stimuli, csp, tblock,method) - -% define parameters in the sequence -pOddball = 0.015; -pReinforcement = 1/3; - -% minimum ISI -mini_isi = 1.5; -% minimum pre stimulus -mini_ps = 0.4; -% additional seconds following oddball/UCS -addsecs=rand(1)+5; - -tItem=length(face_stimuli); - -% for the SecondOrderBalancing: - - - -if ~isempty(csp) && length(csp) == 2; - csn = [mod( csp(1) + 8/2-1, 8)+1 mod( csp(2)-8 + 8/2-1, 8)+1+8 ]; -elseif ~isempty(csp) && length(csp) == 1 - csn = mod( csp(1) + 8/2-1, 8)+1; -else - csn = []; -end - - - -oddball = 18; -ucs = 17; -if method == 1 - stimuli = [face_stimuli oddball ucs]; -else method == 2 - stimuli = [face_stimuli oddball];%ucs's are taken from the CSP indices -end -%% create the block-wise structure of trials -nb = 1; -seq.cond_id = []; -OK=0; -while ~OK - % create tblock-2 blocks of stimuli (faces +oddball (+ucs)) -% while nb <= tblock-2 -% nb = nb + 1; -% seq.cond_id = [seq.cond_id Shuffle(stimuli)]; -% end - m=ones(length(stimuli),length(stimuli)); - m(1:2:end-2,2:2:end-2)=2; - m(2:2:end-2,1:2:end-2)=2; - [S,i]=SecondOrderBalancedSequence(m,1); - % add one block of face_stimuli at beginning and end - seq.cond_id= [Shuffle(face_stimuli) S Shuffle(face_stimuli)]; - seq.tfacetrials=length(find(seq.cond_id<=length(face_stimuli))); - %% - % odd ball cancellation, by default there are as many oddballs as the number of - %blocks. we would like to have much less. - %detect the number of oddball trials we need: -% based on number of trials, but only face_stimuli trials - tOddball = ceil(seq.tfacetrials.*pOddball); - fprintf('Will insert %03d oddballs\n',tOddball); - - oddball_i = Shuffle(find(seq.cond_id == oddball));%all oddballs - oddball_i = oddball_i(tOddball+1:end);%to be cancelled - seq.cond_id(oddball_i) = [];%cancel the oddballs that are too much - %% Add the ucs trials, here we have to choose either by keeping the CSP faces seen by the subjects constant or not - if method == 1 - % this method 1 doesn't keep the amount of CSP faces (shocked + - % non-schocked) equal to the repetition of other stimuli. so overall - % participants see the CSP face a little bit more. -% tucs = round(tblock.*pReinforcement)*length(csp); - tucs = ceil(seq.tfacetrials/length(face_stimuli).*pReinforcement*length(face_stimuli)/8); - fprintf('Will insert %03d tucss\n',tucs); - %replace 17 with a randomly selected stimulus face, but exclude csp and csn - %faces - ucs_i = Shuffle(find(seq.cond_id == ucs));%all ucs - ucs_i = ucs_i(tucs+1:end);%to be cancelled - seq.cond_id(ucs_i) = []; - seq.ucs = seq.cond_id == ucs; - - elseif method == 2 - %% - %this method allocate existing CSP faces randomly to UCS, making the total - %CSP repetition same as any other stimuli, but unshocked CSP stimuli is - %less then the rest - tucs = ceil(tblock.*pReinforcement); - tucs = ceil(trep.*pReinforcement); - fprintf('Will insert %03d tucss\n',tucs); - seq.ucs = logical(zeros(1,length(seq.cond_id))); - for csp_ = csp(:)' - ucs_i = Shuffle(find(seq.cond_id == csp_));%all csp - ucs_i = ucs_i(1:tucs);%ucs that we want to keep - seq.ucs(ucs_i) = 1; - end - - end - %% - seq.oddball = seq.cond_id == oddball; - seq.tTrial = length(seq.cond_id); - %% - %Cond_ID to Stim_ID (which is not the same thing for oddballs for - %example) - seq.stim_id = seq.cond_id;%this field is used to chose the face to be shown on the screen. - oddball_i = seq.cond_id == oddball; - %avoid using CSP and CSN as the oddball stimuli - % Select oddballs from orthogonal faces instead - % valid_oddballs = setdiff(1:16,[csp csn]); - valid_oddballs = mod([csp csn]+2,16); - - seq.stim_id(oddball_i) = RandSample( valid_oddballs,[1 sum(oddball_i)]); - % now give ucs trials one of the two CSP as stim_id - if method == 1%this assignement is not necessary if method == 2 - if length(csp) == 1 - seq.stim_id(seq.ucs) = csp; - elseif length(csp) == 2 - i = Shuffle( find(seq.ucs)); - seq.stim_id(i(1:2:end)) = csp(1); - seq.stim_id(i(2:2:end)) = csp(2); - fprintf('Chose %d CSP1, and %d CSP2.',length(i(1:2:end)),length(i(2:2:end))); - - else - keyboard - end - end - -% OK=sanity_check; -OK=1; - -end - -%% final variables -seq.cross_position = ones(1,seq.tTrial).*2; -%prestim durations should be smaller than ISI, right now they are [0.4 0.7] -seq.prestim_duration = mini_ps+rand(1,seq.tTrial).*.3; -% -fprintf('The effective RR is %g percent \n',sum(seq.ucs)./sum(ismember(seq.cond_id,csp))*100); - -%% fix the ISIs -%isis = [1 2 3 4];%in terms of TRs. -%seq.isi = BalancedDist(seq.cond_id,isis); -dummy=exprnd(.75,[1 seq.tTrial]); -seq.isi = mini_isi+floor(dummy*2)/2; -%add an additional [addsecs] seconds following oddball and ucs trials - -seq.isi(find(seq.ucs + seq.oddball)) = seq.isi(find(seq.ucs + seq.oddball)) + addsecs; -duration = sum(seq.isi)+length(seq.cond_id)*1.5; -fprintf('Total duration is %02g minutes\n',duration./60); - - -%% viz stuff. -visualization =1; -if visualization == 1 - plot(1:length(seq.ucs==1 ),seq.cond_id,'o-'); - hold on; - plot(find(seq.ucs == 1),seq.cond_id(seq.ucs == 1),'+r','markersize',10); - plot(find(seq.oddball == 1),seq.cond_id(seq.oddball == 1),'sg','markersize',10); - hold off; -end - -function [OK]=sanity_check - -% if ~isempty(oddball) && ~isempty(ucs) -% % check if number of oddballs is correct -if sum(seq.oddball)==tOddball; - % % check if number of UCS is correct - if sum(seq.ucs)==tucs; - - % check transition matrix - % that's Lea's version - % n = length(seq.stim_id)-1; - % TM = zeros(tItem,tItem); - % for t = 1:n - % TM(seq.stim_id(t), seq.stim_id(t + 1)) = TM(seq.stim_id(t), seq.stim_id(t + 1)) + 1; - % endi - % E=length(seq.stim_id)/(tItem^2); - % chi2=sum(sum((TM-E).^2./E)); - - Seq=seq.stim_id; - [n c] = hist3([Seq(1:end-1) ;Seq(2:end)]',{1:tItem 1:tItem}); - %only proceed if all bars in n are not bigger than ...3 - if ~any(n>3) - - - - % check for time trends - rate=conv(double(seq.ucs),ones(1,20),'valid')'; - X = [[1:length(rate)]' ones(length(rate),1)]; - [b bint]= regress( rate, X ); - if sum(rate > 4) == 0 - if bint(1)<=0 && bint(1,2)>=0 - %then 0 is in the CI, so it's not significant - OK=1; - else - OK=0; - fprintf('Time Trend significant...Creating New Sequence.') - end - end - else OK=0; - fprintf('%d oddballs found instead of %d!',sum(seq.oddball),tOddball) - end -else OK=0; - fprintf('%d UCS found instead of %d!',sum(seq.ucs),tucs) -end -end diff --git a/InitSerialPort.m b/InitSerialPort.m deleted file mode 100755 index 7e2dd71..0000000 --- a/InitSerialPort.m +++ /dev/null @@ -1,9 +0,0 @@ -function [port]=InitSerialPort - -% -port = IOPort('OpenSerialPort', 'COM1', 'InputBufferSize=51840000 HardwareBufferSizes=32768,32768 Terminator=0 ReceiveLatency=0.0001 BaudRate=9600 ReceiveTimeout=7'); -IOPort('ConfigureSerialPort', port, 'BlockingBackgroundRead=1'); -%because of the BlockingBackgroundRead=1, the flush and close all -%command will wait for the next byte to arrive... -IOPort('Purge', port); -IOPort('ConfigureSerialPort', port, 'StartBackgroundRead=2'); \ No newline at end of file diff --git a/KbQueueDump.m b/KbQueueDump.m deleted file mode 100644 index 1ef7127..0000000 --- a/KbQueueDump.m +++ /dev/null @@ -1,21 +0,0 @@ -function [keycode, secs] = KbQueueDump(deviceIndex) -%[keycode, secs] = KbQueueDump(deviceIndex) -% -% -% Will dump all the events accumulated in the queue. - - -fprintf('there are %03d events\n',KbEventAvail(deviceIndex)); - -while KbEventAvail(deviceIndex) - [evt, n] = KbEventGet(deviceIndex); - n = n + 1; - keycode(n) = evt.Keycode; - pressed(n) = evt.Pressed; - secs(n) = evt.Time; - fprintf('Event is: %d\n',keycode(n)); -end -i = pressed == 1; -keycode(~i) = [] -secs(~i) = []; -fprintf('there are %03d events found...\n',length(keycode)); diff --git a/README.md b/README.md deleted file mode 100644 index 90f43bb..0000000 --- a/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# ExperimentalCode - -This repo contains code for conducting experiments (fMRI, behavioral) with psychophysics toolbox. diff --git a/SendPulses.m b/SendPulses.m deleted file mode 100755 index 0148511..0000000 --- a/SendPulses.m +++ /dev/null @@ -1,23 +0,0 @@ -function SendPulses(N,TR) -%function SendPulses(N) -% -%Sends N pulses to COM2 serial port. TR is the interpulse TR (that is -%the "TR"). -% -%Selim Onat, 24-Jan-2013 10:55:53 - -IOPort('CloseAll') -box.port = IOPort('OpenSerialPort', 'COM2'); -counter = 0; -% -t = GetSecs;%now -t = (t+TR):TR:(t+TR*N);%time of the future pulses -for n = 0:N-1 - counter = counter +1; - tobesent = [floor(n./255) rem(n,255)];%two byte to be sent - WaitSecs('untiltime',t(counter));%wait and fire. - [~,t_]=IOPort( 'Write' , box.port , [char(tobesent(1)+1), char(tobesent(2)+1)]); - - fprintf('Pulse No: %3d sent at %0.10g was due to at %0.10g\n',n,t_,t(counter)); - drawnow%give some time for Control-C -end \ No newline at end of file diff --git a/WaitForPulseZero.m b/WaitForPulseZero.m deleted file mode 100755 index 806e9c8..0000000 --- a/WaitForPulseZero.m +++ /dev/null @@ -1,26 +0,0 @@ -function [t_pulse,value]=WaitForPulseZero(port) -%[t_pulse,value]=WaitForPulseZero(port,n) -% -% OBSOLETE. Since the arrival of the Current Design system, pulses are -% treated as key presses. - - - -value = []; -t_now = GetSecs;%this is the time this function is called, we require that the pulse -%which is detected to arrive later than this time. - -t_pulse = t_now;%if n=0, that is no wait for pulse, than pulse arrival is now... - -ok =1; -while ok - %read data with a granularity of 2 in a blocking way... - [value, t_pulse] = IOPort('Read', port,1,2); - if (t_pulse > t_now) && sum(value) == 0%only consider pulses that arrives strictly after the call of this function. - ok = 0; - %Log(t_pulse,0,NaN);%log the scan onset, this is done - %outside - end -end -fprintf('Pulse Detected at %g\nValue is [%d %d]\n',t_pulse,value(1),value(2)); - diff --git a/WaitPulse.m b/WaitPulse.m deleted file mode 100755 index 98c7c16..0000000 --- a/WaitPulse.m +++ /dev/null @@ -1,19 +0,0 @@ -function [secs]=WaitPulse(keycode,n) -%[secs]=WaitPulse(keycode,n) -% -% This function waits for the Nth upcoming pulse. If N=1, it will wait for -% the very next pulse to arrive. 1 MEANS NEXT PULSE. So if you wish to wait -% for 6 full dummy scans, you should use N = 7 to be sure that at least 6 -% full acquisitions are finished. -% -% The function avoids KbCheck, KbWait functions, but relies on the OS -% level event queues, which are much less likely to skip short events. A -% nice discussion on the topic can be found here: -% http://ftp.tuebingen.mpg.de/pub/pub_dahl/stmdev10_D/Matlab6/Toolboxes/Psychtoolbox/PsychDocumentation/KbQueue.html - -secs = nan(1,n); -pulse = 0; -while pulse < n - secs(pulse+1) = KbTriggerWait(keycode); - pulse = pulse + 1; -end diff --git a/WaitPulseStrictlyAfterNow.m b/WaitPulseStrictlyAfterNow.m deleted file mode 100755 index 4b0ac91..0000000 --- a/WaitPulseStrictlyAfterNow.m +++ /dev/null @@ -1,44 +0,0 @@ -function [t_pulse,value]=WaitPulseStrictlyAfterNow(port,n) -%[t_pulse,value]=WaitPulseStrictlyAfterNow(port,n) -% -% OBSOLETE (see WaitPulse.m) -% -%This function waits for the Nth upcoming pulse. If N=1, it will wait for -%the very next pulse to arrive. 1 MEANS NEXT PULSE. So if you want to wait -%for 6 full dummy scans, you should use N = 7 to be sure that at least 6 -%full scans are finished. T_PULSE is the timestamp of the last -%pulse in case N is >1. -% -%If there are however pulses that were already waiting in the -%buffer before you called this function additional measures has to -%be taken. Therefore this function do not considers all the pulses -%that were received right after the call of this function. This -%costs us an additional IF loop.. -% -%It expects that the serial port handle is a global variable. -% -%Selim Onat, 24-Jan-2013 10:55:53 - - - - -value = []; -t_now = GetSecs;%this is the time this function is called, we require that the pulse -%which is detected to arrive later than this time. -pulse = 0;%pulse counter -t_pulse = t_now;%if n=0, that is no wait for pulse, than pulse arrival is now... - -while pulse < n - ok =1; - while ok - %read data with a granularity of 2 in a blocking way... - [value, t_pulse] = IOPort('Read', port,1,2); - if t_pulse > t_now%only consider pulses that arrives strictly after the call of this function. - ok = 0; - %Log(t_pulse,0,NaN);%log the scan onset, this is done - %outside - end - end - fprintf('Pulse Detected at %g\nValue is [%d %d]\n',t_pulse,value(1),value(2)); - pulse = pulse + 1; -end diff --git a/ana_PFfitting_EL.m b/ana_PFfitting_EL.m deleted file mode 100644 index ac666ad..0000000 --- a/ana_PFfitting_EL.m +++ /dev/null @@ -1,342 +0,0 @@ -%% Loads the feargen ethno fixmat -clear all -filename = '/Users/onat/Documents/BehavioralExperiments/2013_10_feargen_ethno/midlevel/fixmat.mat'; -% -if ~exist(filename) - ppath = '~/Documents/BehavioralExperiments/2013_10_feargen_ethno/'; - addpath('/Users/onat/Documents/Code/Matlab/edfread/current.href/utils'); - addpath(genpath_exclude('/Users/onat/Documents/Code/Matlab/condprob','.svn')); - f = FilterF(ppath,'data.mat','eye'); - tf = length(f); - a = load('/Users/onat/Documents/BehavioralExperiments/2013_10_feargen_ethno//sub002/phase03/stimulation/data.mat'); - f(:) - % - fixmat = []; - for nf = 1:tf - % - load(f{nf}); - %extract subject information - subject = (strvcat(regexp(strvcat(regexp(f{nf},'sub\d\d\d','match')),'\d\d\d','match'))); - load(sprintf('/Users/onat/Documents/BehavioralExperiments/2013_10_feargen_ethno//sub%03d/phase03/stimulation/data.mat',str2num(subject))); - csp = p.stim.cs_plus; - %remove the space from the field name - trials = cell2struct( struct2cell(trials), regexprep(fieldnames(trials),' ','')); - - % now produce a set of new fields for fixations.m to be able to create - % a nice fixmat for us. - % - for nt = 1:length(trials) - T = trials(nt).UCS.msg(1,:); - %extract relevant info first from the text message - phase = (strvcat(regexp(strvcat(regexp(T,'PHASE: \d\d','match')),'\d\d','match'))); - cond = (strvcat(regexp(T,'\d\d\d','match'))); - ucs = (strvcat(regexp(strvcat(regexp(T,'UCS: \d\d','match')),'\d\d','match'))); - odd = (strvcat(regexp(strvcat(regexp(T,'ODDBALL: \d\d','match')),'\d\d','match'))); - - chain = (strvcat(regexp(strvcat(regexp(T,'CHAIN: \d\d','match')),'\d\d','match'))); - ctrial = (strvcat(regexp(strvcat(regexp(T,'CHAINTRIAL: \d\d','match')),'\d\d','match'))); - ttrial = (strvcat(regexp(strvcat(regexp(T,'TTRIAL: \d\d','match')),'\d\d','match'))); - isref = (strvcat(regexp(strvcat(regexp(T,'ISREF: \d\d','match')),'\d\d','match'))); - file = (strvcat(regexp(strvcat(regexp(T,'FILE: \d\d','match')),'\d\d','match'))); - dref = (strvcat(regexp(strvcat(regexp(T,'DELTAREF: \d\d','match')),'\d\d','match'))); - dcsp = (strvcat(regexp(strvcat(regexp(T,'DELTACSP: \d\d','match')),'\d\d','match'))); - dFG = (strvcat(regexp(strvcat(regexp(T,'FGDELTA: \d\d','match')),'\d\d','match'))); - fxx = (strvcat(regexp(strvcat(regexp(T,'FXX: \d\d','match')),'\d\d','match'))); - fxy = (strvcat(regexp(strvcat(regexp(T,'FXY: \d\d','match')),'\d\d','match'))); - % - trials(nt).trial.msg = mat2str(nt); - trials(nt).phase.msg = phase; - trials(nt).subject.msg = subject; - trials(nt).condition.msg = cond; -% trials(nt).condition_aligned.msg = mat2str(ConditionAligner(FaceIndex2Degrees(csp(1),str2num(cond))) + 8*( 8 < str2num(cond))); - trials(nt).ucs.msg = ucs; - trials(nt).oddball.msg = odd; - trials(nt).chain.msg = chain; - trials(nt).ctrial.msg = ctrial; - trials(nt).ttrial.msg = ttrial; - trials(nt).isref.msg = isref; - trials(nt).file.msg = file; - trials(nt).dref.msg = dref; - trials(nt).dcsp.msg = dcsp; - trials(nt).dFG.msg = dFG; - trials(nt).fxx.msg = fxx; - trials(nt).fxy.msg = fxy; - end - % - trials = rmfield(trials,{'StimOnset','StimOffset','FX','UCS','TRIALID','IMG','MODE'}); - dummy = fixations(trials,info); - % - for fn = fieldnames(dummy)' - if ~isfield(fixmat,fn{1}) - fixmat.(fn{1}) = []; - end - fixmat.(fn{1}) = [fixmat.(fn{1}) dummy.(fn{1})]; - end - fixmat.rect = [400 800 600 1000];%[Y_start Y_stop X_start X_stop] - end - %remove out of frame fixations as well as oddball and ucs fixations - fixmat = SelectFix(fixmat,'ucs',0,'oddball',0); - save(filename,'fixmat'); -else - load(filename) -end -%% Compute Fixation Maps for each single subject and condition -% we create maps corrected with 3 different ways. The first one is the raw -% fixation maps, simple probability maps. The Second one is corrected -% within a given subject, by taking out the subject-specific average -% fixation map. This tell you in which conditions a given location is more -% fixated than the average. Across all conditions it sums to zero for a -% given subject. The Third way corrects by the global average, taken across -% all subjects. This tells you how much more or less a given location is -% fixated across all the subject group. -filename = '/Users/onat/Documents/BehavioralExperiments/2013_10_feargen_ethno/midlevel/fixmaps.mat'; -if ~exist(filename) - map = []; - pp = GetParameters('FWHM',20); - nphase = 4; - % - for ns = unique(fixmat.subject) - for cond = unique(fixmat.condition) - fprintf('Processing: Subject: %d, Condition: %d\n',ns,cond); - dummy = fixmat2fixmap(fixmat,pp.kernel,0,1,'','subject',ns,'condition_aligned',cond,'phase',nphase); - map{1}(:,cond,ns) = Vectorize(dummy(401:800,601:1000)); - end - end - map{2} = map{1} - repmat( mean(map{1},2) , [1 16 1] ); - map{3} = map{1} - repmat( mean(mean(map{1},2),3) , [1 16 8] ); - save(filename,'map'); -else - load(filename) -end -%% plot subject specific fixation maps, here we exclude 2 because it sums to zero anyways. -for n = [1 3] - figure(n); - set(gcf,'position',[ 5 -21 1676 955]) - clf - imagesc(reshape(mean(map{n}(:,1:16,:),2),400,400*8)); - axis image - axis off - colorbar -% SaveFigure(sprintf('/Users/onat/Documents/BehavioralExperiments/2013_10_feargen_ethno/figs/SubjectFixMat_%02d.png',n) ,'-r120'); -end -%% compute how similar are different subjects? This is done by averaging the correlation across different conditions. -filename = '/Users/onat/Documents/BehavioralExperiments/2013_10_feargen_ethno/midlevel/covmat_subjects.mat'; -if ~exist(filename) | 1 - cmat_sub=[]; - for ntype = 1:3 - for conds = unique(fixmat.condition) - cmat_sub{ntype}(:,:,conds) = corr(squeeze(map{ntype}(:,conds,:))); - end - end - save(filename,'cmat_sub'); -else - load(filename); -end -% - -for ntype = 1:3 - figure(ntype); - clf; - imagesc(triu(mean(cmat_sub{ntype},3),1)) - axis square; - colorbar -% SaveFigure(sprintf('/Users/onat/Documents/BehavioralExperiments/2013_10_feargen_ethno/figs/CovMat_subjects_%02d.png',ntype)); -end -%% create a condition VS. subject matrix -for ntype = 1:3 - % - D = []; - for ns = unique(fixmat.subject) - D = [D ;reshape(map{ntype}(:,:,ns),400,400*16)]; - end - figure(ntype); - set(gcf,'position',[ 1776 -288 1550 893 ]); - [d u] = GetColorMapLimits(D(:),[10]); - imagesc(D,[d u]); - colorbar; - axis image; - set(gca,'ytick',linspace(0,400*8,9),'ygrid','on','xtick',linspace(0,400*16,17),'xgrid','on','xticklabel',{'1' '2' '3' '4' '5' '6' '7' '8' '9' '10' '11' '12' '13' '14' '15' '16' ''} ,'yticklabel',{'1' '2' '3' '4' '5' '6' '7' '8' ''},'gridlinestyle','-') - grid minor -end -%% Compute Covariance Matrices between Condition Maps for each subject separately -filename = '/Users/onat/Documents/BehavioralExperiments/2013_10_feargen_ethno/midlevel/covmat_fixmat.mat'; -if ~exist(filename) - for ntype = 1:3 - c_cond = 0; - for conds = [1:8 ; 9:16]'; - c_cond = c_cond + 1; - for ns = unique(fixmat.subject) - cmat{ntype}{c_cond}(:,:,ns) = cov(map{ntype}(:,conds,ns)); - end - end - end - save(filename,'cmat'); -else - load(filename) -end -imagesc([mean(cmat{2}{1},3) mean(cmat{2}{2},3)]);colorbar -SaveFigure('/Users/onat/Documents/BehavioralExperiments/2013_10_feargen_ethno/figs/CovMat_fixmats.png' ,'-r120'); - -%% induced across GS subjects DELETE -% % % sub = 0; -% % % r = []; -% % % for ns = gs -% % % sub = sub + 1; -% % % induced_corrected_map = map(:,1:8,ns) - repmat(mean(map(:,1:8,ns),2),[1 8 1]); -% % % r{1}(:,:,sub) = cov(induced_corrected_map); -% % % induced_corrected_map = map(:,9:16,ns) - repmat(mean(map(:,9:16,ns),2),[1 8 1]); -% % % r{2}(:,:,sub) = cov(induced_corrected_map); -% % % end -% % % figure;imagesc([mean(r{1},3) mean(r{2},3) (mean(r{1},3)+mean(r{2},3))/2]);colorbar; -% % % [y x] = meshgrid(linspace(0,2*pi-2*pi/8,8)); -% % % y = repmat(y,[1 1 length(gs)]); -% % % x = repmat(x,[1 1 length(gs)]); -% % % xdata = [y(:) x(:)]; -% % % - -%% fit a model without the gaussian component: DEPENDING ON WHICH CELL ABOVE YOU FIRST EXECUTE -%% THE R will be overwritten -ntype = 2;%type of fixation map normalization, within subject normalization is good because -%it doesn't get corrupted by the shape of the global mean from other subjects. -c = 0; -for dummy = cmat{ntype} - c = c +1; - RSA = mean(dummy{1},3); - options = optimset('Display','iter','maxfunevals',10000,'tolX',10^-12,'tolfun',10^-12,'MaxIter',10000,'Algorithm',''); - [y x] = meshgrid(linspace(0,2*pi-2*pi/8,8)); - xdata = [y(:) x(:)]; - %% fit a model with the diagonal - dia = trace(RSA)/8; - %the diagonal component - x0 = dia; - model_diag = @(x) sum((RSA(:) - CorrMatDecomposition([0 0 0 0 0 x],xdata)).^2); - % - figure(1); - imagesc( reshape([CorrMatDecomposition([0 0 0 0 0 x0],X) Vectorize(RSA)],8,16) ); - figure(2) - [o.Est, o.Likelihood, o.ExitFlag] = fminsearch(model_diag , x0 , options); - dia = o.Est; - imagesc( reshape([CorrMatDecomposition([0 0 0 0 0 dia],X) Vectorize(mean(RSA,3)) CorrMatDecomposition([0 0 0 0 0 dia],X)-Vectorize(mean(RSA,3))],8,24) ) ; - - - %% fit a model with the similarity model, i.e. without any gaussian - - ampc = abs(max(RSA(:)) - min(RSA(:))) - dia; - freq = 1.1; - % - x0 = [ampc freq ]; - model_nogaussian = @(x) sum((RSA(:) - CorrMatDecomposition([x 0 0 0 dia],xdata)).^2); - figure(1); - imagesc( reshape([CorrMatDecomposition([x0 0 0 0 dia],X) Vectorize(mean(RSA,3))],8,16) ) ; - figure(2) - [o.Est, o.Likelihood, o.ExitFlag] = fminsearch(model_nogaussian, x0, options); - ampc = o.Est(1); - freq = o.Est(2); - phase= 0; - imagesc( reshape([CorrMatDecomposition([ampc freq 0 0 0 dia],X) Vectorize(mean(RSA,3)) CorrMatDecomposition([ampc freq 0 0 0 dia],X)-Vectorize(mean(RSA,3))],8,24) ) ; - - %% fit a model with the gaussian componenet - % - ampg = std(CorrMatDecomposition([ampc freq 0 0 0 dia],X)-Vectorize(mean(RSA,3))); - sigma = 1.4; - % - x0 = [ampg sigma ]; - model_gaussian = @(x) sum((RSA(:) - CorrMatDecomposition([ampc freq 0 x dia],xdata)).^2); - figure(1); - imagesc( reshape([CorrMatDecomposition([ampc freq 0 x0(1) x0(2) dia] , X) Vectorize(mean(RSA,3))],8,16) ) ; - figure(2) - [o.Est, o.Likelihood, o.ExitFlag] = fminsearch(model_gaussian, x0,options); - ampg = o.Est(1); - sigma = o.Est(2); - imagesc( reshape([CorrMatDecomposition([ampc freq 0 ampg sigma dia ],X) Vectorize(mean(RSA,3)) CorrMatDecomposition([ampc freq 0 ampg sigma dia ],X)-Vectorize(mean(RSA,3))],8,24) ) ; - - - %% - - Params{c} = [ampc freq phase ampg sigma dia]; - %plot separately the similarity and generalization componenets - figure - imagesc( reshape([CorrMatDecomposition([0 0 0 0 0 dia],X) CorrMatDecomposition([ampc freq 0 0 0 0],X) CorrMatDecomposition([0 0 0 ampg sigma 0],X) Vectorize(mean(RSA,3))],8,32) ) ; - -end - -%% create a mask: mask values are: -%0 : face -%255 : left eye -%182 : right eye -%53 : mouth -%87 : bg -%make mask human readable. -M = rgb2gray(imread('/Users/onat/Documents/BehavioralExperiments/2013_10_feargen_ethno/figs/mask.png')); -M(M == 0) = 1;%face -M(M == 255) = 2;%left eye -M(M == 182) = 3;%right eye -M(M == 53) = 4;%mouthn -M(M == 87) = 5;%bg -M.d = M;%the mask -M.label = {'face' 'left eye' 'right eye' 'mouth' 'bg'} -for nroi = 1:5; - M.ind(:,nroi) = double(M.d(:) == nroi); -end -M.ind = M.ind./repmat(sum(M.ind),size(M.ind,1),1); -% count fixation density -roi=[]; -for ns = 1:8; - roi(:,:,ns)=squeeze(map{2}(:,1:16,ns))'*M.ind(:,2:4); -end -% -t = {'L.Eye' 'R.eye' 'Mouth'} -for nroi = 1:3 - subplot(3,1,nroi); - bar(mean(roi(:,nroi,:),3)); - title(t{nroi}); - axis tight - box off -end -%% compute entropy -for ns = 1:8 - for ncond = 1:16 - E(ncond,ns) = -nansum(map(:,ncond,ns).*log2(map(:,ncond,ns))); - end -end -%% count number of fixations on different parts of the face for each -% condition -P = []; -for nphase = 4 - for ns = unique(fixmat.subject) - for nface = unique(fixmat.condition_aligned) - [ns nface] - % - i = (fixmat.subject == ns) & (fixmat.phase == nphase) & (fixmat.condition_aligned == nface); - % - x = round(fixmat.x(i) - fixmat.rect(3)); - y = round(fixmat.y(i) - fixmat.rect(1)); - % - dummy = diag(M.d(y,x)); - for nroi = 1:5 - P(nroi,mod(nface-1,8)+1,ns) = sum(dummy == nroi); - end - end - P(:,:,ns) = P(:,:,ns)./repmat(sum(P(:,:,ns)),5,1)*100; - end -end - - - - - - - -% compute the similarity of fixation maps and average -gs = [1 3 4 5 6 7]; - - - - - - - - - - - diff --git a/bin/FearGen_Stimuli/01.bmp b/bin/FearGen_Stimuli/01.bmp deleted file mode 100644 index 4bb411c..0000000 Binary files a/bin/FearGen_Stimuli/01.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli/02.bmp b/bin/FearGen_Stimuli/02.bmp deleted file mode 100644 index 163a52a..0000000 Binary files a/bin/FearGen_Stimuli/02.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli/03.bmp b/bin/FearGen_Stimuli/03.bmp deleted file mode 100644 index 743e8fc..0000000 Binary files a/bin/FearGen_Stimuli/03.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli/04.bmp b/bin/FearGen_Stimuli/04.bmp deleted file mode 100644 index 845ea6a..0000000 Binary files a/bin/FearGen_Stimuli/04.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli/05.bmp b/bin/FearGen_Stimuli/05.bmp deleted file mode 100644 index da95f2a..0000000 Binary files a/bin/FearGen_Stimuli/05.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli/06.bmp b/bin/FearGen_Stimuli/06.bmp deleted file mode 100644 index 1beca50..0000000 Binary files a/bin/FearGen_Stimuli/06.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli/07.bmp b/bin/FearGen_Stimuli/07.bmp deleted file mode 100644 index 23d3047..0000000 Binary files a/bin/FearGen_Stimuli/07.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli/08.bmp b/bin/FearGen_Stimuli/08.bmp deleted file mode 100644 index 3d92d5a..0000000 Binary files a/bin/FearGen_Stimuli/08.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli/09.bmp b/bin/FearGen_Stimuli/09.bmp deleted file mode 100644 index dd3b026..0000000 Binary files a/bin/FearGen_Stimuli/09.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli/10.bmp b/bin/FearGen_Stimuli/10.bmp deleted file mode 100644 index 4b02ac1..0000000 Binary files a/bin/FearGen_Stimuli/10.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli/24bit/01.bmp b/bin/FearGen_Stimuli/24bit/01.bmp deleted file mode 100644 index 8a674e2..0000000 Binary files a/bin/FearGen_Stimuli/24bit/01.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli/24bit/02.bmp b/bin/FearGen_Stimuli/24bit/02.bmp deleted file mode 100644 index f2f0954..0000000 Binary files a/bin/FearGen_Stimuli/24bit/02.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli/24bit/03.bmp b/bin/FearGen_Stimuli/24bit/03.bmp deleted file mode 100644 index caeeedb..0000000 Binary files a/bin/FearGen_Stimuli/24bit/03.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli/24bit/04.bmp b/bin/FearGen_Stimuli/24bit/04.bmp deleted file mode 100644 index 26d4061..0000000 Binary files a/bin/FearGen_Stimuli/24bit/04.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli/24bit/05.bmp b/bin/FearGen_Stimuli/24bit/05.bmp deleted file mode 100644 index 52f7fac..0000000 Binary files a/bin/FearGen_Stimuli/24bit/05.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli/24bit/06.bmp b/bin/FearGen_Stimuli/24bit/06.bmp deleted file mode 100644 index 541e75f..0000000 Binary files a/bin/FearGen_Stimuli/24bit/06.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli/24bit/07.bmp b/bin/FearGen_Stimuli/24bit/07.bmp deleted file mode 100644 index b3392ca..0000000 Binary files a/bin/FearGen_Stimuli/24bit/07.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli/24bit/08.bmp b/bin/FearGen_Stimuli/24bit/08.bmp deleted file mode 100644 index 34d6184..0000000 Binary files a/bin/FearGen_Stimuli/24bit/08.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli/24bit/09.bmp b/bin/FearGen_Stimuli/24bit/09.bmp deleted file mode 100644 index 3415a7a..0000000 Binary files a/bin/FearGen_Stimuli/24bit/09.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/01.bmp b/bin/FearGen_Stimuli_32/01.bmp deleted file mode 100644 index 4bb411c..0000000 Binary files a/bin/FearGen_Stimuli_32/01.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/02.bmp b/bin/FearGen_Stimuli_32/02.bmp deleted file mode 100644 index c00a02f..0000000 Binary files a/bin/FearGen_Stimuli_32/02.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/03.bmp b/bin/FearGen_Stimuli_32/03.bmp deleted file mode 100644 index 99bf49c..0000000 Binary files a/bin/FearGen_Stimuli_32/03.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/04.bmp b/bin/FearGen_Stimuli_32/04.bmp deleted file mode 100644 index 9ad68bb..0000000 Binary files a/bin/FearGen_Stimuli_32/04.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/05.bmp b/bin/FearGen_Stimuli_32/05.bmp deleted file mode 100644 index 163a52a..0000000 Binary files a/bin/FearGen_Stimuli_32/05.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/06.bmp b/bin/FearGen_Stimuli_32/06.bmp deleted file mode 100644 index 0921c1a..0000000 Binary files a/bin/FearGen_Stimuli_32/06.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/07.bmp b/bin/FearGen_Stimuli_32/07.bmp deleted file mode 100644 index bd9289d..0000000 Binary files a/bin/FearGen_Stimuli_32/07.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/08.bmp b/bin/FearGen_Stimuli_32/08.bmp deleted file mode 100644 index e0ee161..0000000 Binary files a/bin/FearGen_Stimuli_32/08.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/09.bmp b/bin/FearGen_Stimuli_32/09.bmp deleted file mode 100644 index 743e8fc..0000000 Binary files a/bin/FearGen_Stimuli_32/09.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/10.bmp b/bin/FearGen_Stimuli_32/10.bmp deleted file mode 100644 index 37bbebb..0000000 Binary files a/bin/FearGen_Stimuli_32/10.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/11.bmp b/bin/FearGen_Stimuli_32/11.bmp deleted file mode 100644 index 209eed8..0000000 Binary files a/bin/FearGen_Stimuli_32/11.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/12.bmp b/bin/FearGen_Stimuli_32/12.bmp deleted file mode 100644 index 160b803..0000000 Binary files a/bin/FearGen_Stimuli_32/12.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/13.bmp b/bin/FearGen_Stimuli_32/13.bmp deleted file mode 100644 index 845ea6a..0000000 Binary files a/bin/FearGen_Stimuli_32/13.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/14.bmp b/bin/FearGen_Stimuli_32/14.bmp deleted file mode 100644 index c36f017..0000000 Binary files a/bin/FearGen_Stimuli_32/14.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/15.bmp b/bin/FearGen_Stimuli_32/15.bmp deleted file mode 100644 index 510e1d6..0000000 Binary files a/bin/FearGen_Stimuli_32/15.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/16.bmp b/bin/FearGen_Stimuli_32/16.bmp deleted file mode 100644 index 71afeb0..0000000 Binary files a/bin/FearGen_Stimuli_32/16.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/17.bmp b/bin/FearGen_Stimuli_32/17.bmp deleted file mode 100644 index da95f2a..0000000 Binary files a/bin/FearGen_Stimuli_32/17.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/18.bmp b/bin/FearGen_Stimuli_32/18.bmp deleted file mode 100644 index 9cde85e..0000000 Binary files a/bin/FearGen_Stimuli_32/18.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/19.bmp b/bin/FearGen_Stimuli_32/19.bmp deleted file mode 100644 index a8d444e..0000000 Binary files a/bin/FearGen_Stimuli_32/19.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/20.bmp b/bin/FearGen_Stimuli_32/20.bmp deleted file mode 100644 index c4cb7b5..0000000 Binary files a/bin/FearGen_Stimuli_32/20.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/21.bmp b/bin/FearGen_Stimuli_32/21.bmp deleted file mode 100644 index 1beca50..0000000 Binary files a/bin/FearGen_Stimuli_32/21.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/22.bmp b/bin/FearGen_Stimuli_32/22.bmp deleted file mode 100644 index d5506a0..0000000 Binary files a/bin/FearGen_Stimuli_32/22.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/23.bmp b/bin/FearGen_Stimuli_32/23.bmp deleted file mode 100644 index 113076d..0000000 Binary files a/bin/FearGen_Stimuli_32/23.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/24.bmp b/bin/FearGen_Stimuli_32/24.bmp deleted file mode 100644 index 90f790a..0000000 Binary files a/bin/FearGen_Stimuli_32/24.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/24bits/01.bmp b/bin/FearGen_Stimuli_32/24bits/01.bmp deleted file mode 100644 index 8a674e2..0000000 Binary files a/bin/FearGen_Stimuli_32/24bits/01.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/24bits/02.bmp b/bin/FearGen_Stimuli_32/24bits/02.bmp deleted file mode 100644 index 1a540b5..0000000 Binary files a/bin/FearGen_Stimuli_32/24bits/02.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/24bits/03.bmp b/bin/FearGen_Stimuli_32/24bits/03.bmp deleted file mode 100644 index b78a126..0000000 Binary files a/bin/FearGen_Stimuli_32/24bits/03.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/24bits/04.bmp b/bin/FearGen_Stimuli_32/24bits/04.bmp deleted file mode 100644 index 74a56ad..0000000 Binary files a/bin/FearGen_Stimuli_32/24bits/04.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/24bits/05.bmp b/bin/FearGen_Stimuli_32/24bits/05.bmp deleted file mode 100644 index f2f0954..0000000 Binary files a/bin/FearGen_Stimuli_32/24bits/05.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/24bits/06.bmp b/bin/FearGen_Stimuli_32/24bits/06.bmp deleted file mode 100644 index bf6534c..0000000 Binary files a/bin/FearGen_Stimuli_32/24bits/06.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/24bits/07.bmp b/bin/FearGen_Stimuli_32/24bits/07.bmp deleted file mode 100644 index 9683219..0000000 Binary files a/bin/FearGen_Stimuli_32/24bits/07.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/24bits/08.bmp b/bin/FearGen_Stimuli_32/24bits/08.bmp deleted file mode 100644 index 85709b8..0000000 Binary files a/bin/FearGen_Stimuli_32/24bits/08.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/24bits/09.bmp b/bin/FearGen_Stimuli_32/24bits/09.bmp deleted file mode 100644 index caeeedb..0000000 Binary files a/bin/FearGen_Stimuli_32/24bits/09.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/24bits/10.bmp b/bin/FearGen_Stimuli_32/24bits/10.bmp deleted file mode 100644 index 74af6c2..0000000 Binary files a/bin/FearGen_Stimuli_32/24bits/10.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/24bits/11.bmp b/bin/FearGen_Stimuli_32/24bits/11.bmp deleted file mode 100644 index ecedd75..0000000 Binary files a/bin/FearGen_Stimuli_32/24bits/11.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/24bits/12.bmp b/bin/FearGen_Stimuli_32/24bits/12.bmp deleted file mode 100644 index 07916a0..0000000 Binary files a/bin/FearGen_Stimuli_32/24bits/12.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/24bits/13.bmp b/bin/FearGen_Stimuli_32/24bits/13.bmp deleted file mode 100644 index 26d4061..0000000 Binary files a/bin/FearGen_Stimuli_32/24bits/13.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/24bits/14.bmp b/bin/FearGen_Stimuli_32/24bits/14.bmp deleted file mode 100644 index 3bb0869..0000000 Binary files a/bin/FearGen_Stimuli_32/24bits/14.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/24bits/15.bmp b/bin/FearGen_Stimuli_32/24bits/15.bmp deleted file mode 100644 index 8f8c58f..0000000 Binary files a/bin/FearGen_Stimuli_32/24bits/15.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/24bits/16.bmp b/bin/FearGen_Stimuli_32/24bits/16.bmp deleted file mode 100644 index 6c28b88..0000000 Binary files a/bin/FearGen_Stimuli_32/24bits/16.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/24bits/17.bmp b/bin/FearGen_Stimuli_32/24bits/17.bmp deleted file mode 100644 index 52f7fac..0000000 Binary files a/bin/FearGen_Stimuli_32/24bits/17.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/24bits/18.bmp b/bin/FearGen_Stimuli_32/24bits/18.bmp deleted file mode 100644 index 3364e0d..0000000 Binary files a/bin/FearGen_Stimuli_32/24bits/18.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/24bits/19.bmp b/bin/FearGen_Stimuli_32/24bits/19.bmp deleted file mode 100644 index b417ccb..0000000 Binary files a/bin/FearGen_Stimuli_32/24bits/19.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/24bits/20.bmp b/bin/FearGen_Stimuli_32/24bits/20.bmp deleted file mode 100644 index 4d43403..0000000 Binary files a/bin/FearGen_Stimuli_32/24bits/20.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/24bits/21.bmp b/bin/FearGen_Stimuli_32/24bits/21.bmp deleted file mode 100644 index 541e75f..0000000 Binary files a/bin/FearGen_Stimuli_32/24bits/21.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/24bits/22.bmp b/bin/FearGen_Stimuli_32/24bits/22.bmp deleted file mode 100644 index 4ad4d3b..0000000 Binary files a/bin/FearGen_Stimuli_32/24bits/22.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/24bits/23.bmp b/bin/FearGen_Stimuli_32/24bits/23.bmp deleted file mode 100644 index a2adb13..0000000 Binary files a/bin/FearGen_Stimuli_32/24bits/23.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/24bits/24.bmp b/bin/FearGen_Stimuli_32/24bits/24.bmp deleted file mode 100644 index 88d82ff..0000000 Binary files a/bin/FearGen_Stimuli_32/24bits/24.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/24bits/25.bmp b/bin/FearGen_Stimuli_32/24bits/25.bmp deleted file mode 100644 index b3392ca..0000000 Binary files a/bin/FearGen_Stimuli_32/24bits/25.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/24bits/26.bmp b/bin/FearGen_Stimuli_32/24bits/26.bmp deleted file mode 100644 index b17a193..0000000 Binary files a/bin/FearGen_Stimuli_32/24bits/26.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/24bits/27.bmp b/bin/FearGen_Stimuli_32/24bits/27.bmp deleted file mode 100644 index 848c5cc..0000000 Binary files a/bin/FearGen_Stimuli_32/24bits/27.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/24bits/28.bmp b/bin/FearGen_Stimuli_32/24bits/28.bmp deleted file mode 100644 index 5835ead..0000000 Binary files a/bin/FearGen_Stimuli_32/24bits/28.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/24bits/29.bmp b/bin/FearGen_Stimuli_32/24bits/29.bmp deleted file mode 100644 index 34d6184..0000000 Binary files a/bin/FearGen_Stimuli_32/24bits/29.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/24bits/30.bmp b/bin/FearGen_Stimuli_32/24bits/30.bmp deleted file mode 100644 index bce40eb..0000000 Binary files a/bin/FearGen_Stimuli_32/24bits/30.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/24bits/31.bmp b/bin/FearGen_Stimuli_32/24bits/31.bmp deleted file mode 100644 index 79a5979..0000000 Binary files a/bin/FearGen_Stimuli_32/24bits/31.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/24bits/32.bmp b/bin/FearGen_Stimuli_32/24bits/32.bmp deleted file mode 100644 index 7e91692..0000000 Binary files a/bin/FearGen_Stimuli_32/24bits/32.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/25.bmp b/bin/FearGen_Stimuli_32/25.bmp deleted file mode 100644 index 23d3047..0000000 Binary files a/bin/FearGen_Stimuli_32/25.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/26.bmp b/bin/FearGen_Stimuli_32/26.bmp deleted file mode 100644 index 9f78c2d..0000000 Binary files a/bin/FearGen_Stimuli_32/26.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/27.bmp b/bin/FearGen_Stimuli_32/27.bmp deleted file mode 100644 index 1dc036c..0000000 Binary files a/bin/FearGen_Stimuli_32/27.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/28.bmp b/bin/FearGen_Stimuli_32/28.bmp deleted file mode 100644 index bbeeb4a..0000000 Binary files a/bin/FearGen_Stimuli_32/28.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/29.bmp b/bin/FearGen_Stimuli_32/29.bmp deleted file mode 100644 index 3d92d5a..0000000 Binary files a/bin/FearGen_Stimuli_32/29.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/30.bmp b/bin/FearGen_Stimuli_32/30.bmp deleted file mode 100644 index d0de784..0000000 Binary files a/bin/FearGen_Stimuli_32/30.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/31.bmp b/bin/FearGen_Stimuli_32/31.bmp deleted file mode 100644 index bd4a2a1..0000000 Binary files a/bin/FearGen_Stimuli_32/31.bmp and /dev/null differ diff --git a/bin/FearGen_Stimuli_32/32.bmp b/bin/FearGen_Stimuli_32/32.bmp deleted file mode 100644 index a5639c2..0000000 Binary files a/bin/FearGen_Stimuli_32/32.bmp and /dev/null differ diff --git a/bin/fearamy_seq.mat b/bin/fearamy_seq.mat deleted file mode 100644 index ad026e3..0000000 Binary files a/bin/fearamy_seq.mat and /dev/null differ diff --git a/bin/feargen_seq.mat b/bin/feargen_seq.mat deleted file mode 100644 index ed7aeac..0000000 Binary files a/bin/feargen_seq.mat and /dev/null differ diff --git a/calibrate_display.m b/calibrate_display.m new file mode 100644 index 0000000..46fa188 --- /dev/null +++ b/calibrate_display.m @@ -0,0 +1,119 @@ +function [ gammaTables1, displayBaselines, displayRanges, displayGammas, maxLevel, measurements, levels] = calibrate_display(numMeasures, ppd, gabor_dim_pix, varargin) +% Adapt psychtoolbox's CalibrateMonitorPhotometer to show two stimuli at +% different locations and to read measurements from a color hug. +Screen('Preference', 'SkipSyncTests', 1); +xpos = default_arguments(varargin, 'xpos', [0]); +ypos = default_arguments(varargin, 'ypos', [0]); +devices =1; +path = default_arguments(varargin, 'path', '/home/meg/Documents/Argyll_V1.7.0/bin'); + +screenid = min(Screen('Screens')); + +psychlasterror('reset'); +try + + % Open black window: + white = WhiteIndex(screenid); + black = BlackIndex(screenid); + grey = white / 2; + % Open the screen + [win, windowRect] = Screen('OpenWindow', screenid, grey); + maxLevel = Screen('ColorRange', win); + + % Compute presentation locations + xpos = xpos*ppd; + ypos = ypos*ppd; + [xCenter, yCenter] = RectCenter(windowRect); + xpos = xpos + xCenter; + ypos = ypos + yCenter; + ngabors = numel(xpos); + baseRect = [0 0 gabor_dim_pix gabor_dim_pix]; + allRects = nan(4, ngabors); + for i = 1:ngabors + allRects(:, i) = CenterRectOnPointd(baseRect, xpos(i), ypos(i)); + end + for n = 1:ngabors + Screen('FillOval', win, i, allRects(:,n)); + end + Screen('Flip',win); + + % make Kb Queue + keyList = zeros(1, 256); keyList(KbName({'ESCAPE'})) = 1; % only listen to those keys! + PsychHID('KbQueueCreate', [], keyList); + PsychHID('KbQueueStart'); + WaitSecs(.1); + PsychHID('KbQueueFlush'); + + % keyIsDown = false; + % while ~keyIsDown + % [keyIsDown, firstPress] = PsychHID('KbQueueCheck'); + % end + + + + % Load identity gamma table for calibration: + LoadIdentityClut(win); + + measurements = []; + + inputV = [0:(maxLevel+1)/(numMeasures - 1):(maxLevel+1)]; %#ok + inputV(end) = maxLevel; + levels = inputV; + for i = inputV + colors = [i, i]; + for n = 1:ngabors + Screen('FillOval', win, colors(n), allRects(:,n)); + end + Screen('Flip',win); + WaitSecs(0.1); + data = read_rgb; + %data = read_xyz();g + measurements = [measurements; data]; %#ok + + end + + % Restore normal gamma table and close down: + RestoreCluts; + Screen('CloseAll'); +catch %#ok<*CTCH> + RestoreCluts; + Screen('CloseAll'); + psychrethrow(psychlasterror); +end + + +% [ gammaTable1, gammaTable2, displayBaseline, displayRange, displayGamma, maxLevel, raw_vals, levels] +gammaTables1 = []; +gammaTables2 = []; +displayBaselines = []; +displayRanges = []; +displayGammas = []; + + +for n = 1:3 + %Normalize values + + vals = measurements; + vals = vals(:, n)'; + displayRange = range(vals); + displayBaseline = min(vals); + displayRanges = [displayRanges displayRange]; + displayBaselines = [displayBaselines displayBaseline]; + + raw_vals = vals; + vals = (vals - displayBaseline) / displayRange; + inputV = [0:(maxLevel+1)/(numMeasures - 1):(maxLevel+1)]; %#ok + inputV(end) = maxLevel; + inputV = inputV/maxLevel; + + %Gamma function fitting + g = fittype('x^g'); + fittedmodel = fit(inputV',vals',g); + displayGamma = fittedmodel.g; + displayGammas = [displayGammas displayGamma]; + gammaTable1 = ((([0:maxLevel]'/maxLevel))).^(1/fittedmodel.g); %#ok + gammaTables1 = [gammaTables1, gammaTable1]; %#ok + firstFit = fittedmodel([0:maxLevel]/maxLevel); %#ok + +end +return; diff --git a/config_display.m b/config_display.m deleted file mode 100755 index 4e48ddd..0000000 --- a/config_display.m +++ /dev/null @@ -1,79 +0,0 @@ -function config_display( varargin ) -% CONFIG_DISPLAY configures display -% -% Description: -% Configures display. Call before START_COGENT. -% -% Usage: -% CONFIG_DISPLAY -% CONFIG_DISPLAY( mode, resolution, background, foreground, fontname, fontsize, nbuffers, number_of_bits, scale ) -% -% Arguments: -% mode - window mode ( 0=window, 1=full screen ) -% resolution - screen resolution (0=native, 1=640x480, 2=800x600, 3=1024x768, 4=1152x864, 5=1280x1024, 6=1600x1200) -% background - background colour ( [reg,green,blue] or palette index ) -% foreground - foreground colour ( [reg,green,blue] or palette index ) -% fontname - name of font, -% fontsize - size of font, -% number_of_buffers - number of offscreen buffers -% number_of_bits - number of bits per pixel (8=palette mode, 16, 24, 32, -% or 0=Direct mode, maximum possible bits per pixel) -% scale - horizontal size of screen in (visual degrees) -% -% Examples: -% -% CONFIG_DISPLAY -% Default display configuration, full screen mode, 640x480 resolution, white background, black foreground, -% 50 point Helvetica font, 4 offscreen buffers. -% -% CONFIG_DISPLAY( 0, 2, [0 0 0], [1 1 1], 'Arial', 25, 4 ) -% window mode, 800x600 resolution, black background, white foreground, 25 point Arial font, 4 offscreen buffers -% -% See also: -% CONFIG_DISPLAY, CLEARPICT, DRAWPICT, LOADPICT, PREPAREPICT, PREPARESTRING, SETFORECOLOUR, -% SETTEXTSTYLE -% -% Cogent 2000 function. - -global cogent; - - -% Check number of arguments -if nargin > 9 - error( 'wrong number of arguments' ); -end - -res = default_arg( 1, varargin, 2 ); -if res < 0 | res > 6 - error( 'resolution argument must be in range 0-6' ); -end -%screen_size = [ 640 480; 800 600; 1024 768; 1152 864; 1600 1200 ]; % replaced 19/02/2002 e.f. -screen_size = [ 640 480; 800 600; 1024 768; 1152 864; 1280 1024; 1600 1200 ]; - -% Set congent.display -cogent.display.res = res; -if res == 0 - sz = get(0,'ScreenSize'); - cogent.display.size = sz(3:4); -else - cogent.display.size = screen_size( res, : ); -end -cogent.display.mode = default_arg( 1, varargin, 1 ); -cogent.display.bg = default_arg( [0,0,0], varargin, 3 ); -cogent.display.fg = default_arg( [1,1,1], varargin, 4 ); -cogent.display.font = default_arg( 'Helvetica', varargin, 5 ); -cogent.display.fontsize = default_arg( 50, varargin, 6 ); -cogent.display.number_of_buffers = default_arg( 4, varargin, 7 ); -cogent.display.nbpp = default_arg( 0, varargin, 8 ); % default was 16 26-03-3003 ef Defaulk was 32 19/04/02 ch -if nargin >= 9 - cogent.display.scale = varargin{9}; -end - -switch cogent.display.nbpp -% case { 16, 24, 32 } % Add palette mode 27-3-01 -case { 0, 8, 16, 24, 32 } % Add 0 for the default mode -otherwise -% error( 'number_of_bits must be 16, 24 or 32' ); % Add palette mode 27-3-01 - error( 'number_of_bits must be 0, 8, 16, 24 or 32' ); -end - diff --git a/connectivity_sequences.mat b/connectivity_sequences.mat new file mode 100644 index 0000000..861ef37 Binary files /dev/null and b/connectivity_sequences.mat differ diff --git a/data/pilot1/PH_1PH_1/S3_P1_B1.edf b/data/pilot1/PH_1PH_1/S3_P1_B1.edf new file mode 100644 index 0000000..d83a11f Binary files /dev/null and b/data/pilot1/PH_1PH_1/S3_P1_B1.edf differ diff --git a/data/pilot1/PH_1PH_1/S3_P1_B1_data.mat b/data/pilot1/PH_1PH_1/S3_P1_B1_data.mat new file mode 100644 index 0000000..bb0538f Binary files /dev/null and b/data/pilot1/PH_1PH_1/S3_P1_B1_data.mat differ diff --git a/data/pilot1/PH_1PH_2/S3_P1_B2.edf b/data/pilot1/PH_1PH_2/S3_P1_B2.edf new file mode 100644 index 0000000..577a081 Binary files /dev/null and b/data/pilot1/PH_1PH_2/S3_P1_B2.edf differ diff --git a/data/pilot1/PH_1PH_2/S3_P1_B2_data.mat b/data/pilot1/PH_1PH_2/S3_P1_B2_data.mat new file mode 100644 index 0000000..e9e5f3e Binary files /dev/null and b/data/pilot1/PH_1PH_2/S3_P1_B2_data.mat differ diff --git a/data/pilot1/PH_1PH_3/S3_P1_B3.edf b/data/pilot1/PH_1PH_3/S3_P1_B3.edf new file mode 100644 index 0000000..3e0b4c9 Binary files /dev/null and b/data/pilot1/PH_1PH_3/S3_P1_B3.edf differ diff --git a/data/pilot1/PH_1PH_3/S3_P1_B3_data.mat b/data/pilot1/PH_1PH_3/S3_P1_B3_data.mat new file mode 100644 index 0000000..1000c97 Binary files /dev/null and b/data/pilot1/PH_1PH_3/S3_P1_B3_data.mat differ diff --git a/data/pilot1/PH_1PH_4/S3_P1_B4.edf b/data/pilot1/PH_1PH_4/S3_P1_B4.edf new file mode 100644 index 0000000..8e385a1 Binary files /dev/null and b/data/pilot1/PH_1PH_4/S3_P1_B4.edf differ diff --git a/data/pilot1/PH_1PH_4/S3_P1_B4_data.mat b/data/pilot1/PH_1PH_4/S3_P1_B4_data.mat new file mode 100644 index 0000000..2f2e8e9 Binary files /dev/null and b/data/pilot1/PH_1PH_4/S3_P1_B4_data.mat differ diff --git a/degree2pixel.m b/degree2pixel.m deleted file mode 100644 index 9f9bff8..0000000 --- a/degree2pixel.m +++ /dev/null @@ -1,37 +0,0 @@ -function [out]=degree2pixel(where,in,direction) -%[out]=degree2pixel(where,in,direction) -% -% -% Will return approximate number of pixels/degrees that corresponds to a given -% degree/pixels on the monitors used in the scanner or eyelab. -% -% If DIRECTION is deg2pix, degrees are transformed to pixels, for the -% inverse transformation use pix2deg. -% -% IN/OUT depending on the direction are in units of cm or pixels. -% -% Example: -% degree2pixel('scanner',6,1) will return the number of pixels -% corresponding to 6 degrees in the scanner monitor. -% -% Selim Onat. - -if strcmp(where,'scanner') - distance2monitor = 94.5;%cm - left2right.metric = 38.2;%cm - left2right.pixel = 1024;%native PLCXP200L resolution - angular_span = atand((left2right.metric/2)./distance2monitor)*2;%pixels per degree - pixelperdegree = left2right.pixel/angular_span; -elseif strcmp(where,'eyelab') - distance2monitor = 50;%cm - left2right.metric = 40.7;%cm - left2right.pixel = 1600;%native PLCXP200L resolution - angular_span = atand((left2right.metric/2)./distance2monitor)*2;%pixels per degree - pixelperdegree = left2right.pixel/angular_span; -end - -if strcmp(direction,'deg2pix'); %degree 2 pixels - out = pixelperdegree*in; -else strcmp(direction,'pix2deg'); %degree 2 pixels - out = 1./pixelperdegree*in; -end diff --git a/dell241i_calibration.mat b/dell241i_calibration.mat new file mode 100644 index 0000000..8fb456e Binary files /dev/null and b/dell241i_calibration.mat differ diff --git a/display_params.m b/display_params.m new file mode 100644 index 0000000..be6fecd --- /dev/null +++ b/display_params.m @@ -0,0 +1,22 @@ +% lary local laptop +display.numPixels = [2560 1600]; +display.dimensions = [28 17.9]; +display.distance = 60; +display.frameRate = 60; +display.cmapDepth = 8; +display.screenNumber = 1; +display.maxGammaValue: 255 + maxRgbValue: 255 + stimRgbRange: [1 254] + backColorIndex: 128 + backColorRgb: [128 128 128 255] + textColorRgb: [255 255 255 255] + fixType: 'double disk' + fixSizePixels: 6 + fixColorRgb: [2x4 double] + fixX: 400 + fixY: 300 + gamma: [1024x3 double] + gammaTable: [256x3 double] + spectra: [361x3 double] + wavelengths: [361x1 double] \ No newline at end of file diff --git a/exp_AmbiPilot.m b/exp_AmbiPilot.m deleted file mode 100755 index b3c4560..0000000 --- a/exp_AmbiPilot.m +++ /dev/null @@ -1,662 +0,0 @@ -function [p]=exp_AmbiPilot(subject,noise) -%[p]=exp_AmbiPilot(subject,csp,PainThreshold,nth) -% -% Experiment for showing ambigous pictures to people :D. -% - -%% %init all the variables -%Time Storage -TimeEndStim = []; -TimeTrackerOff = []; -TimeCrossOn = []; -p_var_ExpPhase = []; -p_var_event_count = 0; -t = []; -nTrial = 0; -el = []; -p = []; -% -%% ListenChar(2);%disable pressed keys to be spitted around -commandwindow; -%clear everything -clear mex global functions -%%%%%%%%%%%load the GETSECS mex files so call them at least once -GetSecs; -WaitSecs(0.001); -% -SetParams; -debug = 1;%debug mode -SetPTB; - -%% -InitEyeLink; -WaitSecs(2); -%calibrate if necessary -if strcmp(p.hostname,'etpc'); - CalibrateEL; -end -%save again the parameter file -save(p.path.path_param,'p'); -%% RUN THE EXPERIMENT PROPER -% ShowInstruction(1,1); -% ShowInstruction(2,1); -PresentStimuli; -%% -%get the eyelink file back to this computer -StopEyelink(p.path.edf); - -save(p.path.path_param,'p'); -% -%move the file to its final location. -movefile(p.path.subject,p.path.finalsubject); -%close everything down -cleanup; - - - function PresentStimuli - %Enter the presentation loop and wait for the first pulse to - %arrive. - - - for nTrial = 1:p.presentation.tTrial; - % - %stim_id is the image shown. - stim_id = p.presentation.stim_id(nTrial); - % - fprintf('=======================\nTRIAL: %03d (%03d)\nImage being shown: %s\n',nTrial,p.presentation.tTrial,p.stim.files(stim_id,:)); - % - KbQueueStart(p.ptb.device);%monitor keypresses... - - %Start with the trial, here is time-wise sensitive must be - %optimal - Trial(nTrial, stim_id ); - % - ShowInstruction(3,1); - % - AskStimRating; - % - [keypressed, firstPress]=KbQueueCheck(p.ptb.device); - - - end - end - function Trial(nTrial, stim_id ) - - %turn the eye tracker on - StartEyelinkRecording(nTrial,stim_id); - WaitSecs(.25); - %% Fixation Onset - Screen('FillRect', p.ptb.w, [255,255,255], p.presentation.FixCross); - Screen('Flip',p.ptb.w); - Eyelink('Message', 'FX Onset'); - WaitSecs(1.25); - % - p.ptb.imrect = [ p.ptb.midpoint(1)-p.stim.size(stim_id,2)/2 p.ptb.midpoint(2)-p.stim.size(stim_id,1)/2 p.stim.size(stim_id,2) p.stim.size(stim_id,1)]; - %% send eyelink the marker - Eyelink('Message', 'Stim Onset'); - Eyelink('Message', 'SYNCTIME'); - %% Draw the stimulus to the buffer - keep = 1; - p.out.StimOnset(nTrial) = GetSecs; - while keep - ShowStim; - [keyIsDown, secs, keyCode,deltaSecs] = KbCheck([]); - keyCode = find(keyCode); - if length(keyCode) == 1%this loop avoids crashes to accidential presses of meta keys - if (keyCode == p.keys.confirm) - keep = 0; - p.out.PressingTime(nTrial) = secs; - p.out.PressingTime_CI(nTrial) = deltaSecs; - Eyelink('Message', 'KeyPressed'); - Screen('Flip',p.ptb.w); - %send eyelink a marker - Eyelink('Message', 'Stim Offset'); - Eyelink('Message', 'BLANK_SCREEN'); - end - end - end - % - %% STIM OFF immediately after key press - WaitSecs(.3); - %% record some more eye data after stimulus offset. - StopEyelinkRecording; - - function ShowStim() - - [~, R2] = histc(rand(p.stim.t_pixel(stim_id),1),cumsum([0;p.ptb.NoiseWeight(:)./sum(p.ptb.NoiseWeight)])); - image = p.stim.image{stim_id}(:,:); - size(image) - image(R2 == 2) = 0; - image(R2 == 3) = 1; - B = Screen('MakeTexture', p.ptb.w, double(image)*255); - Screen('DrawTexture', p.ptb.w, B); -% Screen('DrawingFinished',p.ptb.w,0); - % STIMULUS ONSET - Screen('Flip',p.ptb.w);%asap and dont clear - end - end - - function SetParams - - % - p.var.timings = zeros(1,10); - p_var_event_count = 0; - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %relative path to stim and experiments - %Path Business. - [~, hostname] = system('hostname'); - p.hostname = deblank(hostname); - if strcmp(p.hostname,'triostim1') - p.path.baselocation = 'C:\USER\onat\Experiments\'; - elseif strcmp(p.hostname,'etpc') - p.path.baselocation = 'C:\Users\onat\Documents\Experiments\'; - else - p.path.baselocation = '~/Documents/BehavioralExperiments/2015_Ambipilote/'; - end - - p.path.experiment = [p.path.baselocation 'AmbiPilot' filesep]; - p.path.stim = '~/Dropbox/SelimTimTim/AmbiPain/stimulus_selection/'; - % - p.subID = sprintf('sub%02d',subject); - p.path.edf = sprintf(p.subID); - timestamp = datestr(now,30); - p.path.subject = [p.path.experiment 'data' filesep 'tmp' filesep p.subID '_' timestamp filesep]; - p.path.finalsubject = [p.path.experiment 'data' filesep p.subID '_' timestamp filesep ]; - %create folder hierarchy - mkdir(p.path.subject); - mkdir([p.path.subject 'scr']); - mkdir([p.path.subject 'eye']); - mkdir([p.path.subject 'stimulation']); - mkdir([p.path.subject 'midlevel']); - p.path.path_param = sprintf([p.path.subject, 'stimulation/param']); - - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %get stim files - [p.stim.files p.stim.label] = FileMatrix([p.path.stim '*.png']); - p.stim.tFile = size(p.stim.files,1);%number of different files (including the UCS symbol) - % - display([mat2str(p.stim.tFile) ' found in the destination.']); - %is all the captured bg values the same? - - p.stim.bg = 0; - % - %font size and background gray level - p.text.fontname = 'Times New Roman'; - p.text.fontsize = 30; - p.text.fixsize = 60; - % - p.stim.white = [255 255 255]; - %get the actual stim size (assumes all the same) - if strcmp(p.hostname,'triostim1') - p.keys.confirm = KbName('7'); - p.keys.increase = KbName('8'); - p.keys.decrease = KbName('6'); - p.keys.space = KbName('space'); - p.keys.esc = KbName('esc'); - elseif ismac - %All settings for laptop computer. - p.keys.confirm = KbName('UpArrow'); - p.keys.increase = KbName('RightArrow'); - p.keys.decrease = KbName('LeftArrow'); - p.keys.space = KbName('space'); - p.keys.esc = KbName('ESCAPE'); - else - p.keys.confirm = KbName('up'); - p.keys.increase = KbName('right'); - p.keys.decrease = KbName('left'); - p.keys.space = KbName('space'); - p.keys.esc = KbName('esc'); - end - % - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %timing business - %these are the intervals of importance - %time2fixationcross->cross2onset->onset2shock->shock2offset - %these (duration.BLA) are average duration values: - p.duration.stim = 5;%2;%s - p.duration.keep_recording = 0.25;%this is the time we will keep recording (eye data) after stim offset. - p.duration.prestim_ori = .95; - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %stimulus sequence - p.presentation.repetition = 10; - p.presentation.tTrial = p.stim.tFile*p.presentation.repetition; - p.presentation.stim_id = Shuffle(repmat(1:p.stim.tFile,1,p.presentation.repetition)); - - - p.rating.division = 5; - %Save the stuff - save(p.path.path_param,'p'); - % - function [FM labels] = FileMatrix(path) - %Takes a path with file extension associated to regexp (e.g. - %C:\blabl\bla\*.bmp) returns the file matrix - cd(fileparts(path)) - dummy = dir(path); - FM = strvcat(dummy(:).name); - labels = {dummy(:).name}; - end - end - function ShowInstruction(nInstruct,waitforkeypress) - %ShowInstruction(nInstruct,waitforkeypress) - %if waitforkeypress is 1, then subject has to press a button to - %make the instruction text dissappear. Otherwise you have to take - %care of it later - - [text]= GetText(nInstruct); - ShowText(text); - %let subject read it and ask confirmation to proceed. But we don't - %need that in the case of INSTRUCT = 5; - if waitforkeypress - if nInstruct ~= 10%this is for the Reiz kommnt - KbStrokeWait; - else - WaitSecs(2.5+rand(1)); - end - Screen('FillRect',p.ptb.w,p.stim.bg); - t = Screen('Flip',p.ptb.w); - else - if nInstruct ~= 10%this is for the Reiz kommnt - KbStrokeWait; - else - WaitSecs(1+rand(1)); - end - end - - - function ShowText(text) - - Screen('FillRect',p.ptb.w,p.stim.bg); - %DrawFormattedText(p.ptb.w, text, p.text.start_x, 'center',p.stim.white,[],[],[],2,[]); - DrawFormattedText(p.ptb.w, text, 'center', 'center',p.stim.white,[],[],[],2,[]); - t=Screen('Flip',p.ptb.w); - %show the messages amaskt the experimenter screen - fprintf('Text shown to the subject:\n'); - fprintf(text); - end - end - function [text]=GetText(nInstruct) - if nInstruct == 0%Eyetracking calibration - - text = ['Um Ihre Augenbewegungen zu messen, \n' ... - 'müssen wir jetzt den Eye-Tracker kalibrieren.\n' ... - 'Dazu zeigen wir Ihnen einige Punkte auf dem Bildschirm, \n' ... - 'bei denen Sie sich wie folgt verhalten:\n' ... - 'Bitte fixieren Sie den kleinen weißen Kreis und \n' ... - 'bleiben so lange darauf, wie es zu sehen ist.\n' ... - 'Bitte drücken Sie jetzt den oberen Knopf, \n' ... - 'um mit der Kalibrierung weiterzumachen.\n' ... - ]; - - elseif nInstruct == 1%first Instr. of the training phase. - text = ['Herzlich Willkommen bei unserer Studie.\n' ... - 'Bevor wir mit dem Experiment beginnen, einige Hinweise zum weiteren Ablauf.\n'... - 'Die Steuerung des Experiments erfolgt mit 3 Tasten;\n'... - 'Die ''Pfeiltaste oben'' entspricht weiter, links=ja und rechts=nein.\n'... - 'Bitte drueck nun "Pfeiltaste oben" um zum naechsten Bildschirm zu kommen.\n']; - - - elseif nInstruct == 2%second Instr. of the training phase. - text = ['Du wirst gleich eine Reihe von Bildern gezeigt bekommen.\n'... - 'Bitte druecke die ''Pfeiltaste oben'' (weiter), sobald du etwas in dem Bild erkennst.\n'... - '\n'... - 'Bitte sag uns im Anschluss daran, was du gesehen hast,\n'... - 'und wie sicher du dir mit deiner Erkennung bist.\n'... - 'Fuer die letzte Frage, benutze bitte die Tasten "rechts", "links" fuer deine Antwort.\n'... - '\n'... - 'Bevor es jedoch mit dem Experiment losgeht, werden wir zuerst ein paar Probedurchlaeufe machen.\n'... - '\n'... - '(weiter mit der Pfeiltaste oben)\n']; - - elseif nInstruct == 3%third Instr. of the training phase. - text = ['Bitte sag uns was du gesehen hast! (danach weiter mit der ''Pfeiltaste oben'')\n']; - - elseif nInstruct == 4%third Instr. of the training phase. - text = ['Vielen Dank. Das waren die Probedurchgaenge.\n'... - 'Jetzt kommen wir zum Experiment. Der Ablauf ist genau wie in den Probedurchgaengen.\n'... - '\n'... - 'Hast du noch Fragen, bevor wir mit dem Experiment beginnen?\n'... - '\n'... - '\n'... - '(''Pfeiltaste oben'' zum Start des Experiments)\n']; - - elseif nInstruct == 11;%rating - text = ['Wie sicher bist Du dir auf einer Skala von 1-5?\n']; - - elseif nInstruct == 12 %These two below are the possible responses to the question in 11 - text = {'sehr unsicher'}; - elseif nInstruct == 13 - text = {'sehr sicher'}; - elseif nInstruct == 14 - text = ['Bitte machen Sie eine kurze Pause.\n' ... - 'Sie können hierbei gern die Augen einen Moment schließen.\n'... - 'Drücken Sie anschließend die obere Taste um fortzufahren.\n'... - 'Wir werden dann den Eyetracker noch einmal kalibrieren.\n'... - ]; - else - text = {''}; - end - end - function SetPTB - %Sets the parameters related to the PTB toolbox. Including - %fontsizes, font names. - %Find the number of the screen to be opened - screens = Screen('Screens'); - p.ptb.screenNumber = 0;%the maximum is the second monitor - %Make everything transparent for debugging purposes. - if debug - commandwindow; - PsychDebugWindowConfiguration; - end - %Default parameters - Screen('Preference', 'SkipSyncTests', 1); - Screen('Preference', 'DefaultFontSize', p.text.fontsize); - Screen('Preference', 'DefaultFontName', p.text.fontname); - Screen('Preference', 'TextAntiAliasing',2);%enable textantialiasing high quality - Screen('Preference', 'VisualDebuglevel', 0); - Screen('Preference', 'SkipSyncTests', 1); - Screen('Preference', 'SuppressAllWarnings', 1); - %set the resolution correctly - if strcmp(p.hostname,'triostim1') - p.ptb.oldres = Screen('resolution',p.ptb.screenNumber,1280,960); - %hide the cursor - HideCursor(p.ptb.screenNumber); - elseif strcmp(p.hostname,'etpc') - p.ptb.oldres = Screen('resolution',p.ptb.screenNumber,1600,1200); - %hide the cursor - HideCursor(p.ptb.screenNumber); - end - - %Open a graphics window using PTB - p.ptb.w = Screen('OpenWindow', p.ptb.screenNumber, p.stim.bg); - Screen('BlendFunction', p.ptb.w, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - Screen('Flip',p.ptb.w);%make the bg - p.ptb.slack = Screen('GetFlipInterval',p.ptb.w)./2; - [p.ptb.width, p.ptb.height] = Screen('WindowSize', p.ptb.screenNumber); - if sum([p.ptb.width p.ptb.height] - [1280 960]) ~= 0 - fprintf('SET THE CORRECT SCREEN RESOLUTION\n'); - end - %find the mid position on the screen. - p.ptb.midpoint = [ p.ptb.width./2 p.ptb.height./2]; - p.ptb.CrossPosition_x = p.ptb.midpoint(1);%bb(1);%always the same - [nx, ny bb] = DrawFormattedText(p.ptb.w,'+','center','center'); - p.presentation.CrossPosition = p.ptb.midpoint; - fix = p.presentation.CrossPosition;%just for readability - p.presentation.FixCross = [fix(1)-1,fix(2)-20,fix(1)+1,fix(2)+20;fix(1)-20,fix(2)-1,fix(1)+20,fix(2)+1]'; - - %% - %priorityLevel=MaxPriority(['GetSecs'],['KbCheck'],['KbWait'],['GetClicks']); - Priority(MaxPriority(p.ptb.w)); - %this is necessary for the Eyelink calibration - InitializePsychSound(0) - %sound('Open') - Beeper(5000) - - %%%%%%%%%%%%%%%%%%%%%%%%%%%Prepare the keypress queue listening. - p.ptb.device = -1; - p.ptb.keysOfInterest=zeros(1,256); - p.ptb.keysOfInterest(p.keys.confirm) = 1; - KbQueueCreate(p.ptb.device,p.ptb.keysOfInterest);%default device. - - p.ptb.noise = noise; - p.ptb.NoiseWeight = [1-p.ptb.noise p.ptb.noise./2 p.ptb.noise./2]; - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %load the pictures to the memory. - p.ptb.stim_sprites = CreateStimSprites(p.stim.files);% - - function [out]=CreateStimSprites(files) - %loads all the stims to video memory - for nStim = 1:p.stim.tFile - filename = files(nStim,:); - [im , ~, ~] = imread(deblank(filename)); - im = double(im)./255; - if size(im,3) == 1 - im = repmat(im,[1 1 3]); - end - out(nStim) = Screen('MakeTexture', p.ptb.w, im ); - p.stim.size(nStim,:) = size(im); - p.stim.image{nStim}(:,:) = logical(im(:,:,1)); - p.stim.t_pixel(nStim) = prod(p.stim.size(nStim,1:2)); - end - end - end - function [t]=StopEyelinkRecording - Eyelink('StopRecording'); - t = GetSecs; - %this is the end of the trial scope. - WaitSecs(0.01); - Eyelink('Message', 'TRIAL_RESULT 0'); - % - WaitSecs(0.01); - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('Command', 'clear_screen %d', 0); - Screen('Textsize', p.ptb.w,p.text.fontsize); - end - function [t]=StartEyelinkRecording(nTrial,nStim) - t = []; - - nStim = double(nStim); - Eyelink('Message', 'TRIALID: %04d, FILE: %04d', nTrial, nStim); - % an integration message so that an image can be loaded as - % overlay background when performing Data Viewer analysis. - WaitSecs(0.01); - %return - if nStim~=0 - Eyelink('Message', '!V IMGLOAD CENTER %s %d %d', p.stim.files(nStim,:), p.ptb.midpoint(1), p.ptb.midpoint(2)); - end - % This supplies the title at the bottom of the eyetracker display - Eyelink('Command', 'record_status_message "Stim: %02d"', nStim); - % - %Put the tracker offline and draw the stimuli. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - % clear tracker display and draw box at center - Eyelink('Command', 'clear_screen %d', 0); - %draw the image on the screen but also the two crosses -% if (nStim <= 16 && nStim>0) -% Eyelink('ImageTransfer',p.stim.files(nStim,:),p.ptb.imrect(1),p.ptb.imrect(2),p.ptb.imrect(3),p.ptb.imrect(4),p.ptb.imrect(1),p.ptb.imrect(2)); -% end - Eyelink('Command', 'draw_cross %d %d 15',p.presentation.CrossPosition(1),p.presentation.CrossPosition(2)); - - % - %drift correction - %EyelinkDoDriftCorrection(el,crosspositionx,crosspositiony,0,0); - %start recording following mode transition and a short pause. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('StartRecording'); - t = GetSecs; - - end - function shuffled = Shuffle(vector,N) - %takes first N from the SHUFFLED before outputting. This function - %could be used as a replacement for randsample - if nargin < 2;N = length(vector);end - [~, idx] = sort(rand([1 length(vector)])); - shuffled = vector(idx(1:N)); - shuffled = shuffled(:); - end - function InitEyeLink - % - if EyelinkInit(0)%use 0 to init normaly - fprintf('=================\nEyelink initialized correctly...\n') - else - fprintf('=================\nThere is problem in Eyelink initialization\n') - keyboard; - end - % - WaitSecs(0.5); - [~, vs] = Eyelink('GetTrackerVersion'); - fprintf('=================\nRunning experiment on a ''%s'' tracker.\n', vs ); - - % - el = EyelinkInitDefaults(p.ptb.w); - %update the defaults of the eyelink tracker - el.backgroundcolour = p.stim.bg; - el.msgfontcolour = WhiteIndex(el.window); - el.imgtitlecolour = WhiteIndex(el.window); - el.targetbeep = 0; - el.calibrationtargetcolour = WhiteIndex(el.window); - el.calibrationtargetsize = 1.5; - el.calibrationtargetwidth = 0.5; - el.displayCalResults = 1; - el.eyeimgsize = 50; - el.waitformodereadytime = 25;%ms - el.msgfont = 'Times New Roman'; - el.cal_target_beep = [0 0 0];%[1250 0.6 0.05]; - %shut all sounds off - el.drift_correction_target_beep = [0 0 0]; - el.calibration_failed_beep = [0 0 0]; - el.calibration_success_beep = [0 0 0]; - el.drift_correction_failed_beep = [0 0 0]; - el.drift_correction_success_beep= [0 0 0]; - EyelinkUpdateDefaults(el); - %PsychEyelinkDispatchCallback(el) - - % open file. - res = Eyelink('Openfile', p.path.edf); - % - Eyelink('command', 'add_file_preamble_text ''Recorded by EyelinkToolbox FearCloud Experiment'''); - Eyelink('command', 'screen_pixel_coords = %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - Eyelink('message', 'DISPLAY_COORDS %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - % set calibration type. - Eyelink('command','auto_calibration_messages = YES'); - Eyelink('command', 'calibration_type = HV13'); - Eyelink('command', 'select_parser_configuration = 1'); - %what do we want to record - Eyelink('command', 'file_sample_data = LEFT,RIGHT,GAZE,HREF,AREA,GAZERES,STATUS,INPUT,HTARGET'); - Eyelink('command', 'file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON,INPUT'); - Eyelink('command', 'use_ellipse_fitter = no'); - % set sample rate in camera setup screen - Eyelink('command', 'sample_rate = %d',1000); - end - function StopEyelink(filename) - try - fprintf('Trying to stop the Eyelink system with StopEyelink\n'); - Eyelink('StopRecording'); - WaitSecs(0.5); - Eyelink('Closefile'); - display('receiving the EDF file...'); - Eyelink('ReceiveFile',filename,[p.path.subject '\eye\'],1); - display('...finished!') - % Shutdown Eyelink: - Eyelink('Shutdown'); - catch - display('StopEyeLink routine didn''t really run well'); - end - end - function cleanup - - % Close window: - sca; - %set back the old resolution - if strcmp(p.hostname,'triostim1') - Screen('Resolution',p.ptb.screenNumber, p.ptb.oldres.width, p.ptb.oldres.height ); - %show the cursor - ShowCursor(p.ptb.screenNumber); - end - % - commandwindow; - ListenChar(0); - KbQueueRelease(p.ptb.device); - end - function CalibrateEL - fprintf('=================\n=================\nEntering Eyelink Calibration\n') - p_var_ExpPhase = 0; - ShowInstruction(0,1); - EyelinkDoTrackerSetup(el); - %Returns 'messageString' text associated with result of last calibration - [~, messageString] = Eyelink('CalMessage'); - Eyelink('Message','%s',messageString);% - WaitSecs(0.05); - fprintf('=================\n=================\nNow we are done with the calibration\n') - end - - function AskStimRating - fprintf('Subject is rating now\n'); - % Get the text to be show during rating - message = GetText(11); - SliderTextL = GetText(12); - SliderTextR = GetText(13); - % Gray everything - Screen('FillRect', p.ptb.w , p.stim.bg); - Screen('Flip',p.ptb.w); - WaitSecs(.6); - % Show the instruction -% ShowInstruction(11,1); - rect = [p.ptb.width*0.2 p.ptb.midpoint(2) p.ptb.width*0.6 100]; - %save the rating sequence just for security - - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % - rate(nTrial) = RatingSlider(rect, p.rating.division, Shuffle(1:p.rating.division,1), p.keys.increase, p.keys.decrease, p.keys.confirm, {SliderTextL{1} SliderTextR{1}},message,1); - fprintf('Subject Rated: %03d\n',rate(nTrial)); - - - %%%%%%%%%%%%%%%%%%%%%%%%%%%% - %Verbose the rating of the subject - end - function [rating] = RatingSlider(rect,tSection,position,up,down,confirm,labels,message,numbersOn) - % - %Detect the bounding boxes of the labels. - for nlab = 1:2 - [~ , ~, bb(nlab,:)]=DrawFormattedText(p.ptb.w,labels{nlab}, 'center', 'center', p.stim.white,[],[],[],2); - Screen('FillRect',p.ptb.w,p.stim.bg); - end - bb = max(bb); - bb_size = bb(3)-bb(1);%vertical size of the bb. - % - DrawSkala; - ok = 1; - while ok == 1 - [secs, keyCode, ~] = KbStrokeWait; - keyCode = find(keyCode); - - if length(keyCode) == 1%this loop avoids crashes to accidential presses of meta keys - if (keyCode == up) || (keyCode == down) - next = position + increment(keyCode); - if next < (tSection+1) && next > 0 - position = position + increment(keyCode); - %rating = tSection - position + 1; - end - DrawSkala; - elseif keyCode == confirm - WaitSecs(0.1); - ok = 0; - Screen('FillRect',p.ptb.w,p.stim.bg); - t=Screen('Flip',p.ptb.w); - end - end - end - - function DrawSkala - %rating = tSection - position + 1; - rating = position ; - increment([up down]) = [1 -1];%delta - tick_x = linspace(rect(1),rect(1)+rect(3),tSection+1);%tick positions - tick_size = rect(3)./tSection; - ss = tick_size/5*0.9;%slider size. - % - for tick = 1:length(tick_x)%draw ticks - Screen('DrawLine', p.ptb.w, [255 0 0], tick_x(tick), rect(2), tick_x(tick), rect(2)+rect(4) , 3); - if tick <= tSection && numbersOn - Screen('TextSize', p.ptb.w,p.text.fontsize./2); - DrawFormattedText(p.ptb.w, mat2str(tick) , tick_x(tick)+ss/2, rect(2)+rect(4), p.stim.white); - Screen('TextSize', p.ptb.w,p.text.fontsize); - end - if tick == 1 - DrawFormattedText(p.ptb.w, labels{1},tick_x(tick)-bb_size*1.4,rect(2), p.stim.white); - elseif tick == tSection+1 - DrawFormattedText(p.ptb.w, labels{2},tick_x(tick)+bb_size*0.4,rect(2), p.stim.white); - end - end - %slider coordinates - slider = [ tick_x(position)+tick_size*0.1 rect(2) tick_x(position)+tick_size*0.9 rect(2)+rect(4)]; - %draw the slider - Screen('FillRect',p.ptb.w, p.stim.white, round(slider)); - DrawFormattedText(p.ptb.w,message, 'center', p.ptb.midpoint(2)*0.2, p.stim.white,[],[],[],2); - t = Screen('Flip',p.ptb.w); - end - end -end diff --git a/exp_Connectivity.m b/exp_Connectivity.m new file mode 100644 index 0000000..9fe0832 --- /dev/null +++ b/exp_Connectivity.m @@ -0,0 +1,2462 @@ +function [p]=exp_Connectivity(subject, phase, target_block, experiment) + +if nargin == 3 + experiment = 'connectivity'; +elseif ~ (strcmp(experiment, 'connectivity') || strcmp(experiment, 'immuno')) + ME = MException('VerifyInput:ExperimentType', ... + 'experiment string must be connecvivity or immuno'); + throw(ME); +end + + +NoEyelink = 0; %is Eyelink wanted? +debug = 0; %debug mode => 1: transparent window enabling viewing the background. +small_window = 0; % Open a small window only + +%% >>>>> Set up a lot of stuff +% Load stimulus sequence +if strcmp(experiment, 'connectivity') + sequences = load('new_connectivity_sequences-S7andfollowing.mat'); +elseif strcmp(experiment, 'immuno') + sequences = load('immuno_sequences.mat'); +end +if subject > 0 +sequences = sequences.sequences; +sequence = sequences{subject}{phase}; + +fmri = sequence{1}.fmri; % qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqif false skip waiting for pulses. +end +%replace parallel port function with a dummy function +outp = @(x,y) 1; +% if ~IsWindows +% outp = @(x,y) 1; +% else +% addpath('C:\USER\_parallelport_cogent') +% config_io; +% keyboard +% outp(p.com.lpt.address,0); +% +% if( cogent.io.status ~= 0 ) +% error('inp/outp installation failed'); +% end +% end + +commandwindow; %focus on the command window, so that output is not written on the editor +%clear everything +clear mex global functions;%clear all before we start. + +if IsWindows %clear cogent if we are in Windows and rely on Cogent for outp. + cgshut; + global cogent; %#ok +end +GetSecs; +WaitSecs(0.001); + +el = [];%eye-tracker variable +p = [];%parameter structure that contains all info about the experiment. + +SetParams;%set parameters of the experiment +SetPTB;%set visualization parameters. + + +if subject == -100 % <---- Do sample retino measurements. + if subject == -101 + p = make_sample_textures(p, false); + else + p = make_sample_textures(p, true); + end + KbQueueStop(p.ptb.device); + KbQueueRelease(p.ptb.device); + p.phase = -100; + p.block = -100; + p = InitEyeLink(p); + CalibrateEL; + KbQueueCreate(p.ptb.device); + KbQueueStart(p.ptb.device); + KbQueueFlush(p.ptb.device); + [p, abort] = MeasureSamplePupilResponses(p); + StopEyelink(p.edffile, 'sample_test.edf') + cleanup; + return +end + + +if subject == -110 % <---- Do sample retino measurements. + ['test'] + KbQueueStop(p.ptb.device); + KbQueueRelease(p.ptb.device); + draw_stimulus(p,0); + Screen('Flip',p.ptb.w); %<----- FLIP + WaitSecs(5) + cleanup; + return +end + +if ~fmri + p.mrt.dummy_scan = 0; +end + +%Time Storage +p.var.event_count = 0; +p.possible_reward = 0; +p.earned_rewards = 0; + +% Load reward file +path_reward = fullfile(p.path.baselocation, sprintf('SUB_%i', p.subject)); +if ~exist(path_reward) %#ok + mkdir(path_reward) +end +reward_file = fullfile(path_reward,'rewards_latest.mat'); + +if strcmp(experiment, 'connectivity') + eur_per_reward = 0.05; +elseif strcmp(experiment, 'immuno') + p = make_sample_textures(p); + eur_per_reward = 0.017; +end + +if exist(reward_file) %#ok + all_rewards = load(reward_file); + all_rewards = all_rewards.all_rewards; + all_rewards.eur_per_reward = eur_per_reward; + all_rewards.weight = 1; +else + all_rewards.money = 0; + all_rewards.total_rewards = 0; + all_rewards.eur_per_reward = eur_per_reward; + all_rewards.weight = 1; + save(reward_file, 'all_rewards'); +end + +p.subject = subject; + + +% Vormessung +p.phase = phase; +ii = 0; + +%while ~(k == KbName(p.keys.el_calib)); +% pause(0.1); +% fprintf('Experimenter!! press V key when the vormessung is finished.\n'); +% [~, k] = KbStrokeWait(p.ptb.device); +% k = find(k); +%end + + +if (numel(target_block) == 0) || sum((target_block == -1))==1 + target_block = 1:length(sequence); +end + +blocks_completed = 0; +ir_blocks_completed = 0; +gl_blocks_completed = 0; + +calibrated = false; + +Screen('TextSize', p.ptb.w, 20); +Screen('TextFont', p.ptb.w, 'Courier'); +Screen('TextStyle', p.ptb.w, 1); + +%% >>>>>>> Experiment starts. +%try + for block = target_block + fprintf('Running SUB=%i, PHASE=%i, BLOCK=%i\n', subject, phase, block); + p.block = block; + p.sequence = sequence{block}; + + + if strcmp('IR', p.sequence.block_type) + all_rewards.weight = 0.7; + if blocks_completed > 0 + p = TakeABreak(p); + end + if ir_blocks_completed == 0 + explain_instructed_rule(p); + end + KbQueueStop(p.ptb.device); + KbQueueRelease(p.ptb.device); + p = InitEyeLink(p); + CalibrateEL; + [p, abort] = InstructedRuleBlock(p); + ir_blocks_completed = ir_blocks_completed+1; + + + elseif strcmp('GL', p.sequence.block_type) + all_rewards.weight = 1; + if blocks_completed > 0 + p = TakeABreak(p); + end + if gl_blocks_completed == 0 + explain_glaze_rule(p); + end + KbQueueStop(p.ptb.device); + KbQueueRelease(p.ptb.device); + p = InitEyeLink(p); + CalibrateEL; + [p, abort] = GlazeBlock(p); + gl_blocks_completed = gl_blocks_completed+1; + + + elseif strcmp('RW', p.sequence.block_type) + all_rewards.weight = 0.0; + if blocks_completed == 0 + explain_retino_block(p) + end + KbQueueStop(p.ptb.device); + KbQueueRelease(p.ptb.device); + p = InitEyeLink(p); + if block == 1 || ~calibrated + CalibrateEL; + calibrated = false; + end + if fmri + [p, abort] = RetinoBlock(p, 0.8, 5, 5.5, false, 5, 'wedge'); + else + [p, abort] = RetinoBlock(p, 0.8, 5, 5.5, false, 0, 'wedge'); + end + + elseif strcmp('RR', p.sequence.block_type) + all_rewards.weight = 0.0; + if blocks_completed == 0 + explain_retino_block(p) + end + KbQueueStop(p.ptb.device); + KbQueueRelease(p.ptb.device); + p = InitEyeLink(p); + if block == 1 || ~calibrated + CalibrateEL; + calibrated = false; + end + if fmri + [p, abort] = RetinoBlock(p, 0.8, 5, 5.5, false, 5, 'ring'); + %p = InitEyeLink(p); + %[p, abort] = RetinoBlock(p, 0.8, 5, 5.5, true, 1, 'ring'); + else + [p, abort] = RetinoBlock(p, 0.8, 5, 5.5, false, 0, 'ring'); + %p = InitEyeLink(p); + %[p, abort] = RetinoBlock(p, 0.8, 5, 5.5, true, 0, 'ring'); + end + + elseif strcmp('NR', p.sequence.block_type) + % A block of the Nassar prediction task. + all_rewards.weight = 0.6; + if blocks_completed == 0 + %explain_nassar_block(p) + end + KbQueueStop(p.ptb.device); + KbQueueRelease(p.ptb.device); + p = InitEyeLink(p); + if block == 1 || ~calibrated + CalibrateEL; + calibrated = true; + end + [p, abort] = NassarPredictionBlock(p); + end + + blocks_completed = blocks_completed+1; + if abort + cleanup + return + end + end +%end + +%WaitSecs(2.5); +cleanup; +lasterr + + %% ----------------------------------- + % Experiment blocks + % ----------------------------------- + + function [p, abort] = InstructedRuleBlock(p) + % 4.8.17 - Check data save. + p.start_time = datestr(now, 'dd-mmm-yy-HH:MM:SS'); + + Screen('FillRect',p.ptb.w,p.var.current_bg); + Screen('Flip',p.ptb.w); + + [secs, p] = WaitPulse(p, p.keys.pulse, p.mrt.dummy_scan); %will log pulses and release keyboard q + KbQueueCreate(p.ptb.device);%, p.ptb.keysOfInterest);%default device. + KbQueueStart(p.ptb.device); + KbQueueFlush(p.ptb.device); + + Eyelink('StartRecording'); + WaitSecs(0.01); + Eyelink('Message', sprintf('SUBJECT %d', p.subject)); + p = Log(p, GetSecs, 'START_IR', nan, p.phase, p.block); + p = Log(p, GetSecs, 'SUBJECT', p.subject, p.phase, p.block); + Eyelink('Message', sprintf('PHASE %d', p.phase)); + Eyelink('Message', sprintf('BLOCK %d', p.block)); + + start_block = secs(end)- p.ptb.slack;%take the first valid pulse as the end of the last stimulus. + + % Reward stuff + draw_fix(p); + p.prev_sample=0; + start_block = GetSecs(); + for trial = 1:size(p.sequence.stim, 2); + %Get the variables that Trial function needs. + stim_id = p.sequence.stim(trial); + rewarded_rule = p.sequence.rewarded_rule(trial); + stimulus_onset = p.sequence.stimulus_onset(trial); + block_change = p.sequence.type(trial); + + p = Log(p, GetSecs, 'IR_STIM', stim_id, p.phase, p.block); + Eyelink('Message', sprintf('IR_STIM %i', stim_id)); + p = Log(p, GetSecs, 'IR_REWARDED_RULE', rewarded_rule, p.phase, p.block); + Eyelink('Message', sprintf('IR_REWARDED_RULE %i', rewarded_rule)); + + StartEyelinkRecording(trial, p.phase, rewarded_rule, stim_id, p.block, block_change); + + if block_change==0 + % Block change trial + fprintf('BLOCK CHANGE! REWRULE: %d\n', rewarded_rule); + show_block(p, rewarded_rule, 2, stimulus_onset+start_block); + else + + fprintf('%d of %d, STIM: %i, ONSET: %3.2f, REWARDED_RULE: %i,',... + trial, size(p.sequence.stim, 2), stim_id, stimulus_onset, rewarded_rule); + + + [p, TimeEndStim, abort, reward] = InstructedRuleTrial(phase, p.block, p, stimulus_onset+start_block, stim_id, rewarded_rule, 0); + fprintf(' REWARD: %i, TOTAL: %i\n',reward, p.earned_rewards); + p = Log(p, GetSecs, 'IR_TRIAL_REWARD', reward, p.phase, p.block); + if ~isnan(reward) + Eyelink('Message', 'IR_TRIAL_REWARD %i', reward); + end + + p = dump_keys(p); + + if abort + break + end + end + if GetSecs() > start_block+600 + break + end + end + p = dump_keys(p); + fprintf('This instructed rule block lasted %3.2fs', GetSecs()-secs(end)) + %wait 6 seconds for the BOLD signal to come back to the baseline... + WaitPulse(p, p.keys.pulse, p.mrt.dummy_scan);% + fprintf('OK!! Stop the Scanner\n'); + + n_trials = sum(p.sequence.type(1:trial)); + money_earned = p.earned_rewards*all_rewards.eur_per_reward*all_rewards.weight; + all_rewards.money = all_rewards.money+money_earned; + all_rewards.total_rewards = all_rewards.total_rewards + p.earned_rewards; + + text = RewardText(p.earned_rewards, p.earned_rewards/n_trials, money_earned, all_rewards.money); + Screen('FillRect',p.ptb.w,p.var.current_bg); + DrawFormattedText(p.ptb.w, text, 'center', 'center', p.stim.white,[],[],[],2,[]); + Screen('Flip',p.ptb.w); + start = GetSecs(); + p = save_data(p, all_rewards); + while GetSecs() < start+5 + end + %stop the queue + KbQueueStop(p.ptb.device); + KbQueueRelease(p.ptb.device); + + end + + + function [p, abort] = GlazeBlock(p) + % 4.8 Check data save + abort=false; + p.start_time = datestr(now, 'dd-mmm-yy-HH:MM:SS'); + %wait for the dummy scans + + Screen('FillRect',p.ptb.w,p.var.current_bg); + Screen('Flip',p.ptb.w); + KbQueueStop(p.ptb.device); + KbQueueRelease(p.ptb.device); + + show_glaze_block(p, 0); % <-- Show glaze block + [secs, p] = WaitPulse(p, p.keys.pulse,p.mrt.dummy_scan); + KbQueueCreate(p.ptb.device); + KbQueueStart(p.ptb.device); + KbQueueFlush(p.ptb.device); + + Screen('Flip', p.ptb.w); + + Eyelink('StartRecording'); + WaitSecs(.01); + Eyelink('Message', sprintf('SUBJECT %d', p.subject)); + p = Log(p, GetSecs, 'START_GLAZE', nan, p.phase, p.block); + p = Log(p, GetSecs, 'SUBJECT', p.subject, p.phase, p.block); + Eyelink('Message', sprintf('PHASE %d', p.phase)); + Eyelink('Message', sprintf('BLOCK %d', p.block)); + + TimeEndStim = secs(end)- p.ptb.slack; + WaitSecs(1); + % Reward stuff + draw_fix(p); + p.prev_sample=0; + %ISI = .25; + StartGlazeEyelinkRecording(p.block, p.phase); + outcomes = []; + start_trials = GetSecs(); + start = start_trials+0.4; + for trial = 1:size(p.sequence.stim, 2); + %Get the variables that Trial function needs. + stim_id = p.sequence.stim(trial); + type = p.sequence.type(trial); + location = p.sequence.sample(trial); + gener_side = p.sequence.generating_side(trial); + OnsetTime = start+p.sequence.stimulus_onset(trial); + if location < 0 + fprintf('-'); + else + fprintf('+'); + end + Eyelink('Command', 'record_status_message "Trial: %i/%i"', trial, size(p.sequence.stim, 2)); + Eyelink('Message', 'trial_id %i', trial); + + p = Log(p, GetSecs, 'GL_TRIAL_START', trial, p.phase, p.block); + if ~isnan(stim_id) + p = Log(p, GetSecs, 'GL_TRIAL_STIM_ID', stim_id, p.phase, p.block); + Eyelink('Message', 'stim_id %i', stim_id); + end + if ~isnan(gener_side) + p = Log(p, GetSecs, 'GL_TRIAL_GENSIDE', gener_side, p.phase, p.block); + Eyelink('Message', 'gener_side %i', round(100*gener_side)); + end + if ~isnan(location) + Eyelink('Message', 'location %d', round(1000*location)); + p = Log(p, GetSecs, 'GL_TRIAL_LOCATION', location, p.phase, p.block); + end + p = Log(p, GetSecs, 'GL_TRIAL_TYPE', type, p.phase, p.block); + Eyelink('Message', 'type %i', type); + + if type == 0 + % Show a single sample + [TimeEndStim, p] = show_one_sample(p, OnsetTime, location); + elseif type == 1 + % Choice trial. + fprintf('\nCHOICE TRIAL; stim_id:%i, gener_side:%02.2f ', stim_id, gener_side>0); + [p, ~, response, rule, abort] = choice_trial(p, OnsetTime, stim_id, p.phase, p.block); + fprintf(' RULE: %i ', rule) + if ~isnan(rule) + if rule ~= (gener_side>0) + outcomes = [outcomes 1]; %#ok + p = Log(p, GetSecs, 'GL_TRIAL_REWARD', 1, p.phase, p.block); + Eyelink('Message', 'GL_TRIAL_REWARD 1'); + fprintf('REWARD!\n'); + else + outcomes = [outcomes 0]; %#ok + p = Log(p, GetSecs, 'GL_TRIAL_REWARD', 0, p.phase, p.block); + Eyelink('Message', 'GL_TRIAL_REWARD 0'); + fprintf('NO REWARD!\n') + end + else + p = Log(p, GetSecs, 'GL_TRIAL_REWARD', nan, p.phase, p.block); + Eyelink('Message', 'IR_TRIAL_REWARD -1'); + + end + end + p = dump_keys(p); + + if abort + break + end + if GetSecs() > start+600 + break + end + + end + fprintf('\n This block of trials lasted %3.2fs\n', GetSecs()-start_trials); + p = dump_keys(p); + %wait 6 seconds for the BOLD signal to come back to the baseline... + WaitPulse(p, p.keys.pulse, p.mrt.dummy_scan);% + fprintf('OK!! Stop the Scanner\n'); + + + % Need to show feedback here! + p.earned_rewards = sum(outcomes); + %money_earned = p.earned_rewards*all_rewards.eur_per_reward; + money_earned = sum(outcomes)*all_rewards.eur_per_reward*all_rewards.weight; + all_rewards.money = all_rewards.money+money_earned; + all_rewards.total_rewards = all_rewards.total_rewards + p.earned_rewards; + + text = RewardText(p.earned_rewards, p.earned_rewards/length(outcomes), money_earned, all_rewards.money); + Screen('FillRect',p.ptb.w,p.var.current_bg); + DrawFormattedText(p.ptb.w, text, 'center', 'center', p.stim.white,[],[],[],2,[]); + Screen('Flip',p.ptb.w); + start = GetSecs(); + p = save_data(p, all_rewards); + while GetSecs() < start+5 + end + %stop the queue + KbQueueStop(p.ptb.device); + KbQueueRelease(p.ptb.device); + + end + + + function [p, abort] = RetinoBlock(p, TR, nrep, IBI, reverse, wait_triggers, type) + % 4.8.17 - Check data save + rule = binornd(1, 0.5); + abort = false; + p.start_time = datestr(now, 'dd-mmm-yy-HH:MM:SS'); + block_info = sprintf('NREP=%i, REVERSE=%i, TYPE=%s, RULE=%i', nrep, reverse, type, rule); + p = Log(p, GetSecs, 'RETINO_START', block_info, p.phase, p.block); + p = Log(p, GetSecs, 'SUBJECT', p.subject, p.phase, p.block); + %IBI is inter change time for task in seconds + % Prepare stimuli + if strcmp(type, 'wedge') + stimulus = load('retino_sequence.mat'); + else + stimulus = load('retino_ring_sequence.mat'); + end + stimulus = stimulus.stimulus; + % Construct stimulus sequence + ret_sequence = struct(); + ret_sequence.seq = []; + ret_sequence.seqtiming = 0; + isi = mean(diff(stimulus.seqtiming)); % sample diff in seconds + for n = 1:nrep + ret_sequence.seq = [ret_sequence.seq; stimulus.seq]; + ret_sequence.seqtiming = [ret_sequence.seqtiming; stimulus.seqtiming + ret_sequence.seqtiming(end) + isi]; + end + for n = 1:nrep + ret_sequence.seq = [ret_sequence.seq; flip(stimulus.seq)]; + ret_sequence.seqtiming = [ret_sequence.seqtiming; stimulus.seqtiming + ret_sequence.seqtiming(end) + isi]; + end + + ret_sequence.seqtiming = ret_sequence.seqtiming(2:end); + images = nan*ones(size(stimulus.images{1}, 3), 1); + for i = 1:length(images) + images(i) = Screen('MakeTexture', p.ptb.w, stimulus.images{1}(:,:,i)); + end + w = size(stimulus.images{1},1)/2; + h = size(stimulus.images{1},2)/2; + stimulus = ret_sequence; + [X,Y] = meshgrid(-w:w-1, -h:h-1); + Z = ((X.^2+Y.^2).^.5)/p.display.ppd; + mask = ones(2*w, 2*h, 2)*128; + mask(:, :, 2) = (1-double((0.582) & (onsets < (2*IBI))); + onsets = cumsum(onsets); + arrows = binornd(1, 0.5, length(onsets), 1); + KbQueueStop(p.ptb.device); + + p = dump_keys(p); + Screen('BlendFunction', p.ptb.w, 'GL_SRC_ALPHA', 'GL_ONE_MINUS_SRC_ALPHA'); + [secs, p] = WaitPulse(p, p.keys.pulse, wait_triggers);%will log it + KbQueueCreate(p.ptb.device); + KbQueueStart(p.ptb.device) + KbQueueFlush(p.ptb.device) + start = secs(end); + StarRetinoEyelinkRecording(type, reverse); + Screen('DrawTexture', p.ptb.w, images(1), [], rect) + Screen('DrawTexture', p.ptb.w, mask, [], rect) + start = Screen('Flip',p.ptb.w, start+TR, 0); %<----- FLIP + Eyelink('message', 'first_flip'); + onsets = onsets+start; + cnt = 1; + first = true; + vbl=0; + %ay = p.FixCross(1, 2) - (p.FixCross(1, 2) - p.FixCross(1, 4))/2; + %ax = p.FixCross(2, 1); + p.FixCross(4) + last_stim_id = nan; + last_response = nan; + for i = 2:length(stimulus.seq) + onset = stimulus.seqtiming(i); + image = images(stimulus.seq(i)); + Screen('DrawTexture', p.ptb.w, image, [], rect) + Screen('DrawTexture', p.ptb.w, mask, [], rect) + if ~isnan(last_stim_id) + % Still waiting for a response + [p, abort, resp_rule] = handle_retino_response(p, last_stim_id); + if isnan(resp_rule) + fix_color = [255, 255, 255]; + elseif rule==resp_rule + fix_color = [0, 200, 0]; + last_stim_id = nan; + last_response = GetSecs; + else + fix_color = [200, 0, 0]; + last_stim_id = nan; + last_response = GetSecs; + end + end + if (GetSecs-last_response)<0.5 + draw_fix(p, fix_color, rule); + else + draw_fix(p, [], rule); + last_response = nan; + end + + if vbl > onsets(cnt) + if first + p = dump_keys(p); + p = Log(p, GetSecs, 'RETINO_GRATIN_ONSET', arrows(cnt), p.phase, p.block); + first = false; + end + % Prompt for a choice! + Screen('BlendFunction', p.ptb.w, 'GL_ONE', 'GL_ZERO'); + draw_very_small_stimulus(p, arrows(cnt)) + Screen('BlendFunction', p.ptb.w, 'GL_SRC_ALPHA', 'GL_ONE_MINUS_SRC_ALPHA'); + last_stim_id = arrows(cnt); + if vbl > (onsets(cnt)+0.5) + cnt = cnt+1; + first = true; + end + end + + vbl = Screen('Flip',p.ptb.w, start+onset, 0); %<----- FLIP + p = Log(p, vbl, 'RETINO_SEQ_CNT', i, p.phase, p.block); + if(abort) + ['Aborting, saving data'] + p = save_data(p, all_rewards); + return + end + if binornd(1, 1/450) + rule = ~rule; + end + + end + fprintf('This sequence took %3.2fs', GetSecs()-start); + Screen('BlendFunction', p.ptb.w, 'GL_ONE', 'GL_ZERO'); + draw_fix(p, [], rule); + Screen('Flip',p.ptb.w, start+onset, 0); + p = save_data(p, all_rewards); + %stop the queue + KbQueueStop(p.ptb.device); + KbQueueRelease(p.ptb.device); + end + + + function [p, abort] = NassarPredictionBlock(p) + % 4.8.17 - Check data save + p.start_time = datestr(now, 'dd-mmm-yy-HH:MM:SS'); + [oldFontName,~,oldTextStyle] = Screen('TextFont', p.ptb.w, 'Courier'); + oldTextSize=Screen('TextSize', p.ptb.w, 70); + abort = nan; + KbQueueStop(p.ptb.device); + KbQueueRelease(p.ptb.device); + + + Screen('FillRect',p.ptb.w,p.var.current_bg); + t = Screen('Flip',p.ptb.w); + + + KbQueueCreate(p.ptb.device);%, p.ptb.keysOfInterest);%default device. + KbQueueStart(p.ptb.device) + KbQueueFlush(p.ptb.device) + + + Eyelink('StartRecording'); + WaitSecs(0.01); + + Eyelink('Message', sprintf('SUBJECT %d', p.subject)); + Eyelink('Message', sprintf('PHASE %d', p.phase)); + Eyelink('Message', sprintf('BLOCK %d', p.block)); + + TimeEndStim = GetSecs(); + + + % Reward stuff + draw_prd_background(p); + p.prev_sample=0; + p.earned_rewards = 0; + p.possible_reward = 0; + prediction = p.sequence.sample(1); + last_sample = p.sequence.sample(1); + + lower_bound = mean(abs(diff(p.sequence.sample))); + upper_bound = mean(abs(p.sequence.sample(2:end) - p.sequence.mu(1:end-1))); + prediction_errors = nan(size(p.sequence.stim,2)); + + Log(p, vbl, 'PRD_LOWER_BOUND', lower_bound, p.phase, p.block); + Log(p, vbl, 'PRD_UPPER_BOUND', upper_bound, p.phase, p.block); + + for trial = 1:size(p.sequence.stim, 2); + Log(p, vbl, 'PRD_TRIAL', trial, p.phase, p.block); + %Get the variables that Trial function needs. + stim_id = p.sequence.stim(trial); + ISI = p.sequence.isi(trial); + jitter = p.sequence.jitter(trial); + sample = p.sequence.sample(trial); + OnsetTime = TimeEndStim + ISI; + sample_duration = p.sequence.sample_duration(trial); + + + fprintf('%d of %d, SAMPLE: %i, Block: %i \n',... + trial, size(p.sequence.stim, 2), round(sample), p.block); + + StartEyelinkRecording(trial, p.phase, 0, 0, 0, 0); + %type, p, TimeStimOnset, stim_id, sample, jitter + [TimeEndStim, p, abort, prediction] = PredictionTrial(p, OnsetTime, sample, sample_duration, jitter, prediction, last_sample); + last_sample = sample; + + prediction_errors(trial) = abs(prediction-sample); + Log(p, vbl, 'PRD_ERROR', prediction_errors(trial), p.phase, p.block); + + [keycode, secs] = KbQueueDump(p); %this contains both the pulses and keypresses. + if numel(keycode) + %log everything but "pulse keys" as pulses, not as keypresses. + pulses = (keycode == KbName(p.keys.pulse)); + + if any(~pulses);%log keys presses if only there is one + p = Log(p,secs(~pulses), 1000,keycode(~pulses), p.phase, p.block); + end + if any(pulses);%log pulses if only there is one + p = Log(p,secs(pulses), 0, keycode(pulses), p.phase, p.block); + end + end + + if abort + %% Save Data + p = save_data(p, all_rewards); + %stop the queue + KbQueueStop(p.ptb.device); + KbQueueRelease(p.ptb.device); + sca + return + end + end + + mean_prediction_error = nanmean(prediction_errors(:)); + fprintf('Mean prediction error: %2.1f\n', mean_prediction_error); + fprintf('Lower bound: %3.2f, upper bound: %3.2f', lower_bound, upper_bound); + payout_weight = 1/4; + if (lower_bound < mean_prediction_error) &&... + (mean_prediction_error < ((2*lower_bound/3) + (upper_bound/3))) + payout_weight = 2/4; + elseif (((2*lower_bound/3) + (upper_bound/3)) < mean_prediction_error) &&... + (mean_prediction_error < (lower_bound+upper_bound)/2) + payout_weight = 3/4; + elseif mean_prediction_error < (lower_bound+upper_bound)/2 + payout_weight = 1; + end + + %money_earned = p.earned_rewards*all_rewards.eur_per_reward; + money_earned = trial*all_rewards.eur_per_reward*all_rewards.weight*payout_weight; + all_rewards.money = all_rewards.money+money_earned; + all_rewards.total_rewards = all_rewards.total_rewards + p.earned_rewards; + + %wait 6 seconds for the pupil signal to come back to the baseline... + start = GetSecs(); + while GetSecs() < start+6 + end + + + [keycode, secs] = KbQueueDump(p);%this contains both the pulses and keypresses. + pulses = (keycode == KbName(p.keys.pulse)); + if any(~pulses);%log keys presses if only there is one + p = Log(p,secs(~pulses), 1000,keycode(~pulses), p.phase, p.block); + end + if any(pulses);%log pulses if only there is one + p = Log(p,secs(pulses), 0,keycode(pulses), p.phase, p.block); + end + text = NassarRewardText(mean_prediction_error, payout_weight, money_earned, all_rewards.money); + + + Screen('FillRect',p.ptb.w,p.var.current_bg); + Screen('TextSize', p.ptb.w, 15); + Screen('TextFont', p.ptb.w, 'Courier'); + Screen('TextStyle', p.ptb.w, 1); + DrawFormattedText(p.ptb.w, text, 'center', 'center', p.stim.white,[],[],[],2,[]); + Screen('Flip',p.ptb.w); + start = GetSecs(); + p = save_data(p, all_rewards); + while GetSecs() < start+10 + end + %stop the queue + KbQueueStop(p.ptb.device); + KbQueueRelease(p.ptb.device); + Screen('TextFont', p.ptb.w, oldFontName, oldTextStyle); + Screen('TextSize', p.ptb.w, oldTextSize); + end + + + function [p, abort] = TakeABreak(p) + % Display 'Take a break', info about next block and next task. + Screen('Flip', p.ptb.w); + start = GetSecs(); + ShowText('1 Minute Pause!\n'); + ShowText('Weiter in 15s. \n', start+45); + ShowText('Weiter in 5s. \n', start+55); + end + + + function [p, abort] = MeasureSamplePupilResponses(p) + % Display 'Take a break', info about next block and next task. + Eyelink('StartRecording'); + WaitSecs(.01); + Eyelink('Message', sprintf('SUBJECT %d', p.subject)); + p = Log(p, GetSecs, 'START_SAMPLE_MEASUREMENT', nan, p.phase, p.block); + p = Log(p, GetSecs, 'SUBJECT', p.subject, p.phase, p.block); + Eyelink('Message', sprintf('PHASE %d', p.phase)); + Eyelink('Message', sprintf('BLOCK %d', p.block)); + Screen('Flip', p.ptb.w); + abort = false; + dt = 5; + samples = [1, 10*(randperm(9)), 10*(randperm(9)), 10*(randperm(9)), 10*(randperm(9)), 10*(randperm(9)), ]; + for iii = 2:length(samples) + sample = samples(iii); + start = GetSecs(); + KbQueueFlush(p.ptb.device); + [evt, n] = KbEventGet(p.ptb.device); + [evt, n] = KbEventGet(p.ptb.device); + while (GetSecs()-start) < 20 + [evt, n] = KbEventGet(p.ptb.device); + if numel(evt)>0 + keys = KbName(evt.Keycode); + switch keys + case p.keys.quit + abort = true; + return + case {'space'} + break + case p.keys.pulse + p = Log(p,RT, 0, NaN, p.phase, p.block); + end + end + end + + draw_prd_sample(p, 10); + draw_fix_bg_angled(p, 45); + Offset = Screen('Flip', p.ptb.w); + Eyelink('message', 'TRIALID %d', iii); + draw_prd_sample(p, sample); + draw_fix_bg_angled(p, 45); + Screen('Flip', p.ptb.w, Offset+1) + samplestr = sprintf('sample %i', sample); + + Eyelink('Message', samplestr); + lumstr = sprintf('lum %f', mean(p.stim.sample_stimuli{sample}(:))); + Eyelink('Message', lumstr); + draw_prd_sample(p, 10); + draw_fix_bg_angled(p, 0); + Screen('Flip', p.ptb.w, Offset+3.5) + if abort + return + end + end + + samples = [255*(randperm(10)/10), 255*(randperm(10)/10), 255*(randperm(10)/10), 255*(randperm(10)/10), 255*(randperm(10)/10)]; + for iii = 1:length(samples) + sample = samples(iii); + start = GetSecs(); + KbQueueFlush(p.ptb.device); + [evt, n] = KbEventGet(p.ptb.device); + [evt, n] = KbEventGet(p.ptb.device); + while (GetSecs()-start) < 20 + [evt, n] = KbEventGet(p.ptb.device); + if numel(evt)>0 + keys = KbName(evt.Keycode); + switch keys + case p.keys.quit + abort = true; + return + case {'space'} + break + case p.keys.pulse + p = Log(p,RT, 0, NaN, p.phase, p.block); + end + end + end + + Screen('FillRect', p.ptb.w, [128, 128, 128]) + draw_fix_bg_angled(p, 0); + Offset = Screen('Flip', p.ptb.w); + Eyelink('message', 'TRIALID %d', iii); + Screen('FillRect', p.ptb.w, [sample, sample, sample]) + draw_fix_bg_angled(p, 45); + Screen('Flip', p.ptb.w, Offset+1) + lumstr = sprintf('sample %f', sample) ; + Eyelink('Message', lumstr); + lumstr = sprintf('lum %f', sample); + Eyelink('Message', lumstr); + Screen('FillRect', p.ptb.w, [128, 128, 128]) + draw_fix_bg_angled(p, 0); + Screen('Flip', p.ptb.w, Offset+3.5) + + if abort + return + end + end + end + + %% ----------------------------------- + % Trial functions + % ----------------------------------- + + function [p, TimeFeedbackOffset, abort, reward] = InstructedRuleTrial(... + phase, block, p, TimeStimOnset, stim_id, rewarded_rule, jitter) + %% Run one trial of the localizer block design task. + rule = nan; %#ok + abort = false; %#ok + TimeFeedbackOffset = nan; + + TrialStart = GetSecs; + trial_info = sprintf('STIM=%i, REW_RULE=%i', stim_id, rewarded_rule); + p = Log(p, TrialStart, 'IR_TRIAL_START', trial_info, phase, block); + + p = dump_keys(p); + + [p, TimeCrossOn] = start_ir_trial(p, phase, block); %#ok + + [p, RT, ~, rule, abort] = choice_trial(p, TimeStimOnset, stim_id, phase, block); + reward = nan; + + % Rewarded rule 1 => Left rule active: || <> left, = <> right + % Rewarded rule 0 => Right rule active: || <> right, = <> left + if ~isnan(rule) + if (rule == rewarded_rule) + reward = 1; + else + reward = 0; + end + + end + [p, TimeFeedbackOffset] = show_feedback(p, 0, RT+jitter, rule, reward, phase, block); + + if ~isnan(reward) + p.earned_rewards = p.earned_rewards + reward; + end + + end + + + function [TimeFeedbackOffset, p, abort, prediction] = PredictionTrial(p, TimeStimOnset, sample, sample_duration, jitter, old_prediction, last_sample) + %% Run one trial + fixerror = nan; + rule = nan; + abort = false; + TimeFeedbackOffset = nan; + TrialStart = GetSecs; + p = Log(p,TrialStart, 'PRD_TRIAL_START', sample, p.phase, p.block); + + [p, prediction_time, prediction, abort] = predict_prd_sample(p, old_prediction, last_sample); + if abort + return + end + + [TimeFeedbackOffset] = show_prd_sample(p, jitter, sample_duration, sample, prediction); + + p.prev_sample = sample; + end + + + function [p, abort, rule] = handle_retino_response(p, stim_id) + [keycodes, secs] = KbQueueDump(p); + response = nan; + abort = false; + rule = nan; + if numel(keycodes) + for iii = 1:length(keycodes) + RT = secs(iii); + keys = KbName(keycodes(iii)); + + switch keys + case p.keys.quit + abort = true; + return + case cat(2, p.keys.answer_a, p.keys.answer_a_train) + % Answer a = Left + response = 0; + p = Log(p, RT, 'RETINO_RESP', 0, p.phase, p.block); + case cat(2, p.keys.answer_b, p.keys.answer_b_train) + % Answer b = Right + response = 1; + p = Log(p, RT, 'RETINO_RESP', 1, p.phase, p.block); + case p.keys.pulse + fprintf('Logging pulse\n') + p = Log(p, RT, 0, KbName(p.keys.pulse), phase, p.block); + end + end + end + + if isnan(response) + rule = nan; + elseif response == stim_id % Stim_id 0: ||, stim_id 1: = + % Rule A: || <> Left, = <> Right + rule = 1; + else + % Rule B: || <> Right, = <> Left + rule = 0; + end + end + + + function [p, TimeCrossOn] = start_ir_trial(p, phase, block) + %% Start a trial + Screen('FillRect', p.ptb.w , p.stim.bg, [] ); %always create a gray background + draw_fix(p); + Screen('FillRect', p.ptb.w, [255, 255, 255], p.FixCross');%draw the prestimus cross atop + TimeCrossOn = Screen('Flip',p.ptb.w); %<----- FLIP + p = Log(p,TimeCrossOn, 'IR_TRIAL_FIXON', nan, phase, block); + Eyelink('Message', 'IR_TRIAL_FIXON'); + %MarkCED( p.com.lpt.address, p.com.lpt.trialOnset); + end + + + function [p, RT, response, rule, abort] = choice_trial(p, ChoiceStimOnset, stim_id, phase, block) + rule = nan; + response = nan; %#ok + RT = nan; %#ok + abort = false; + draw_stimulus(p, stim_id) + % STIMULUS ONSET + TimeStimOnset = Screen('Flip',p.ptb.w, ChoiceStimOnset, 0); %<----- FLIP + start_rt_counter = TimeStimOnset; + p = Log(p,TimeStimOnset, 'CHOICE_TRIAL_ONSET', stim_id, phase, block); + Eyelink('Message', sprintf('CHOICE_TRIAL_ONSET %i', stim_id)); + + MarkCED( p.com.lpt.address, p.com.lpt.stim); + % Check for key events + p = dump_keys(p); + KbQueueFlush(p.ptb.device); + % Now wait for response! + response = nan; + RT = nan; + num_flips = 0.2/p.ptb.slack; + phase = rand*180; + % Duration needs to be exactly 2s. Use for loop for this. + for onset_time = 0.2:0.2:1.8 + % Stimulus Offset + draw_stimulus(p, stim_id, phase); + step = randsample(45:10:360, 1); + phase = mod(phase + step, 360); + draw_fix_bg(p); + Screen('FillRect', p.ptb.w, [255,255,255], p.FixCross'); + LastOnset = Screen('Flip', p.ptb.w, TimeStimOnset+onset_time-p.ptb.slack, 0); %<----- FLIP + end + draw_fix_bg(p) + TimeStimOffset = Screen('Flip', p.ptb.w, TimeStimOnset+ 2 -p.ptb.slack, 0); %<----- FLIP + p = Log(p,TimeStimOffset, 'CHOICE_TRIAL_STIMOFF', nan, phase, p.block); + Eyelink('Message', 'CHOICE_TRIAL_STIMOFF'); + response = nan; + [keycodes, secs] = KbQueueDump(p); + if numel(keycodes) + for iii = 1:length(keycodes) + RT = secs(iii); + keys = KbName(keycodes(iii)); + p = Log(p, RT, 'BUTTON_PRESS', keys, phase, p.block); + switch keys + case p.keys.quit + abort = true; + return + case cat(2, p.keys.answer_a, p.keys.answer_a_train) %{p.keys.answer_a, p.keys.answer_a_train} + % Answer a = Left + response = 0; + break + case cat(2, p.keys.answer_b, p.keys.answer_b_train) %{p.keys.answer_b, p.keys.answer_b_train} + % Answer b = Right + response = 1; + break + case p.keys.pulse + fprintf('Logging pulse\n') + p = Log(p, RT, 0, KbName(p.keys.pulse), phase, p.block); + end + end + end + if ~isnan(RT) + Eyelink('Message', sprintf('RT %i', round(1000*(RT-start_rt_counter)))); + end + if response == 0 + MarkCED(p.com.lpt.address, p.com.lpt.resp0); + else + MarkCED(p.com.lpt.address, p.com.lpt.resp1); + end + Eyelink('message', sprintf('CHOICE_TRIAL_RESP %i', response)); + p = Log(p,RT, 'CHOICE_TRIAL_RESP', response, phase, block); + p = Log(p,RT, 'CHOICE_TRIAL_RT', RT-start_rt_counter, phase, block); + + if ~isnan(response) + if response == stim_id + % Stim_id 0: ||, stim_id 1: = + % Rule A: || <> Left, = <> Right + rule = 1; + else + % Rule B: || <> Right, = <> Left + rule = 0; + end + end + p = Log(p,RT, 'CHOICE_TRIAL_RULE_RESP', rule, phase, block); + fprintf('RULE: %i, ', rule); + end + + + function [p, TimeFeedbackOffset] = show_feedback(p, type, TimeFeedbackOnset, rule, reward, phase, block) + %% Show feedback + % Define rule correctness here. If sample < 0 then obs have to + % respond with Rule 0, if sample > 0 have to respond with rule 1 + if type == 1 + % Feedback about correct vs. wrong answer. + if reward % Rewarded rule + draw_fix(p, [20, 200, 20]); + elseif ~isnan(rule) + draw_fix(p, [200, 20, 20]); + end + fprintf('RULE: %i, GET_REWARD? %i \n', rule, reward); + p = Log(p, GetSecs, 'FEEDBACK', rule, phase, block); + Eyelink('message', sprintf('RULE %i', rule)); + + TimeFeedback = Screen('Flip',p.ptb.w, TimeFeedbackOnset, 0); %<----- FLIP + Eyelink('message', sprintf('FEEDBACK %f', reward)); + p = Log(p,TimeFeedback, 'FEEDBACK_TYPE', reward, phase, block); + MarkCED( p.com.lpt.address, p.com.lpt.sample); + + draw_fix(p); + TimeFeedbackOffset = Screen('Flip',p.ptb.w,TimeFeedback+0.4, 0); %<----- FLIP + + Eyelink('message', 'FEEDBACKOFF'); + p = Log(p,TimeFeedbackOffset, 'FEEDBACK_OFF', 0, phase, block); + else + if ~isnan(rule) + draw_fix(p, [220, 220, 220]); + else + draw_fix(p); + end + TimeFeedback = Screen('Flip',p.ptb.w); %<----- FLIP + draw_fix(p); + TimeFeedbackOffset = Screen('Flip',p.ptb.w, TimeFeedback+0.1); %<----- FLIP + end + + end + + + function [TimeSampleOffset, p] = show_one_sample(p, SampleOnset, location) + % Show one sample, such that black and white parts cancel. + r_inner = p.stim.r_inner; + o = p.stim.lumdiff; + p.sample_duration=p.stim.sample_duration; + x_outer = r_inner*(2^.5 -1); + r_outer = (r_inner + x_outer)*p.display.ppd; + r_inner = r_inner*p.display.ppd; + cx = p.ptb.CrossPosition_x; + cy = p.ptb.CrossPosition_y; + + % left, top, right, bottom + location = location*p.display.ppd; + rin = [location-r_inner+cx, cy-r_inner, location+r_inner+cx, r_inner+cy]; + rout = [location-r_outer+cx, cy-r_outer, location+r_outer+cx, r_outer+cy]; + draw_fix(p); + Screen('FillOval', p.ptb.w, [128-o, 128-o, 128-o], rout); + Screen('FillOval', p.ptb.w, [128+o, 128+o, 128+o], rin); + + ActSampleOnset = Screen('Flip',p.ptb.w, SampleOnset, 0); %<----- FLIP + Eyelink('message', sprintf('sample %f', location)); + p = Log(p,ActSampleOnset, 'SAMPLE_ONSET', location, p.phase, p.block); + %MarkCED( p.com.lpt.address, p.com.lpt.event); + draw_fix(p); + + TimeSampleOffset = Screen('Flip',p.ptb.w,ActSampleOnset+p.sample_duration, 0); %<----- FLIP + draw_fix(p); + %TimeSampleOffset = Screen('Flip',p.ptb.w,TimeSampleOffset+(.25), 0); + end + + + + %% ----------------------------------- + % Helper functions + % ----------------------------------- + + function p = dump_keys(p) + %dump the final events + [keycode, secs] = KbQueueDump(p);%this contains both the pulses and keypresses. + %log everything but "pulse keys" as pulses, not as keypresses. + pulses = (keycode == KbName(p.keys.pulse)); + if any(~pulses);%log keys presses if only there is one + p = Log(p,secs(~pulses), 1000,keycode(~pulses), p.phase, p.block); + end + if any(pulses);%log pulses if only there is one + p = Log(p,secs(pulses), 0,keycode(pulses), p.phase, p.block); + end + end + + + function draw_stimulus(p, stim_id, phase) + if nargin==2 + phase = 0; + end + angle = 90*stim_id; + df = p.ptb.rect(3) - p.ptb.rect(4); + rect = [df/2., 0, p.ptb.rect(4)+df/2, p.ptb.rect(4)]; + draw_fix(p); + Screen('DrawTexture', p.ptb.w, p.ptb.gabortex, [], rect, ... + angle, [], [], [], [], [], [phase, p.stim.sf, 150, 100, 1, 0, 0, 0]); + radius = 2.5; + oc = [p.ptb.midpoint(1)-p.display.ppd*radius, p.ptb.midpoint(2)-p.display.ppd*radius,... + p.ptb.midpoint(1)+p.display.ppd*radius, p.ptb.midpoint(2)+p.display.ppd*radius]; + Screen('FillOval', p.ptb.w, p.stim.bg, oc); + %draw also the fixation cross + Screen('FillRect', p.ptb.w, [255,255,255], p.FixCross'); + Screen('DrawingFinished',p.ptb.w,0); + end + + + function draw_very_small_stimulus(p, stim_id) + angle = 90*stim_id; + df = p.ptb.rect(3) - p.ptb.rect(4); + %rect = [df/2., 0, p.ptb.rect(4)+df/2, p.ptb.rect(4)]; + ppd = p.display.ppd*0.5; + oc = [p.ptb.midpoint(1)-ppd, p.ptb.midpoint(2)-ppd, p.ptb.midpoint(1)+ppd, p.ptb.midpoint(2)+ppd]; + Screen('DrawTexture', p.ptb.w, p.ptb.gabortex, [], oc, ... + angle, [], [], [], [], [], [0, p.stim.sf/5, 150, 10, 1, 0, 0, 0]); + + end + + + function draw_fix_bg(p, color) + if nargin==1 + color=[255, 255, 255]; + + end + cx = mean(p.FixCross(2,[1, 3])); + cy = mean(p.FixCross(2,[2, 4])); + r = 0.25*p.display.ppd; + rr = [cx-r, cy-r, cx+r, cy+r]; + Screen('FillOval', p.ptb.w, [128, 128, 128], rr); + Screen('FillRect', p.ptb.w, color, p.FixCross'); + end + + + function draw_fix_bg_angled(p, angle) + cx = mean(p.FixCross(2,[1, 3])); + cy = mean(p.FixCross(2,[2, 4])); + r = 0.25*p.display.ppd; + rr = [cx-r, cy-r, cx+r, cy+r]; + Screen('FillOval', p.ptb.w, [128, 128, 128], rr); + Screen('BlendFunction', p.ptb.w, 'GL_SRC_ALPHA', 'GL_ONE_MINUS_SRC_ALPHA'); + Screen('DrawTexture', p.ptb.w, p.stim.fix, [], [], angle); + Screen('BlendFunction', p.ptb.w, 'GL_ONE', 'GL_ZERO'); + + end + + + function draw_square(p, angle) + Screen('BlendFunction', p.ptb.w, 'GL_SRC_ALPHA', 'GL_ONE_MINUS_SRC_ALPHA'); + Screen('DrawTexture', p.ptb.w, p.stim.square, [], [], angle); + Screen('BlendFunction', p.ptb.w, 'GL_ONE', 'GL_ZERO'); + end + + + function draw_fix(p, color, rule) + if nargin==1 + color=[255, 255, 255]; + rule = nan; + elseif nargin == 2 + if numel(color) == 0; + color = [255, 255, 255]; + end + rule = nan; + end + if ~isnan(rule) + center = mean(p.FixCross(2,[2, 4])); + left = p.ptb.CrossPosition_x - 0.5*p.display.ppd; + right = p.ptb.CrossPosition_x + 0.5*p.display.ppd; + rl = [left-3, center-3, left+3, center+3]; + rr = [right-3, center-3, right+3, center+3]; + if rule == 1 + Screen('FillOval', p.ptb.w, [100, 100, 100], rl); + Screen('FrameOval', p.ptb.w,[10, 10, 10], rl); + Screen('FillOval', p.ptb.w, [100, 100, 100], rr); + else + Screen('FillOval', p.ptb.w, [100, 100, 100], rl); + Screen('FillOval', p.ptb.w, [100, 100, 100], rr); + Screen('FrameOval', p.ptb.w,[10, 10, 10], rr); + end + end + Screen('FillRect', p.ptb.w, color, p.FixCross'); + end + + + function TimeCrossOn= start_prd_trial(p, allow_blink) + %% Start a trial, also allows time for blinks. + Screen('FillRect', p.ptb.w , p.stim.bg, [] ); %always create a gray background + draw_prd_background(p) + + if allow_blink>0 % Give time for blinks. + %Screen('FillRect', p.ptb.w, [0, 55, 200], p.FixCross');%draw the prestimus cross atop + draw_fix_bg(p, [0, 55, 200]); + TimeBlinkOn = Screen('Flip',p.ptb.w, allow_blink+2); %<----- FLIP + draw_fix_bg(p); + %Screen('FillRect', p.ptb.w, [255, 255, 255], p.FixCross');%draw the prestimus cross atop + draw_prd_background(p) + + TimeCrossOn = Screen('Flip',p.ptb.w, TimeBlinkOn+1); %<----- FLIP + else + %Screen('FillRect', p.ptb.w, [255, 255, 255], p.FixCross');%draw the prestimus cross atop + draw_fix_bg(p); + TimeCrossOn = Screen('Flip',p.ptb.w); %<----- FLIP + end + %p = Log(p,TimeCrossOn, 3, nan, p.phase, p.block); + Eyelink('Message', 'FIXON'); + MarkCED(p.com.lpt.address, 3); + end + + + function [TimeFeedbackOffset] = show_prd_sample(p, jitter, duration, sample, prediction) + draw_prd_background(p) + draw_prd_sample(p, prediction) + draw_fix_bg_angled(p, 45); + TimeFeedbackOnset = Screen('Flip',p.ptb.w); %<----- FLIP + draw_prd_background(p) + draw_fix_bg_angled(p, 45); + draw_prd_sample(p, sample) + error = false; + TimeFeedback = Screen('Flip',p.ptb.w, TimeFeedbackOnset+jitter, 0); %<----- FLIP + Eyelink('message', sprintf('FEEDBACK %f', sample)); + p = Log(p,TimeFeedback, 9, sample, p.phase, p.block); + MarkCED( p.com.lpt.address, 130+sample); + + draw_prd_background(p) + draw_fix_bg_angled(p, 45); + draw_prd_sample(p, sample) + eyeused = Eyelink('EyeAvailable')+1; + % Now check eye movements + xc = (p.ptb.rect(3) - p.ptb.rect(1))/2; + yc = (p.ptb.rect(4) - p.ptb.rect(2))/2; + error = false; + while GetSecs() < (TimeFeedback+duration-p.ptb.slack) + if ~NoEyelink && Eyelink('NewFloatSampleAvailable') + esample = Eyelink('NewestFloatSample'); + x = esample.gx(eyeused); + y = esample.gy(eyeused); + distance = (((x-xc)^2 + (y-yc)^2)^.5)/p.display.ppd; + if distance > 1.5 + error = true; + end + + end + end + TimeFeedbackOffset = Screen('Flip',p.ptb.w,TimeFeedback+duration-p.ptb.slack/2, 0); %<----- FLIP + Eyelink('message', 'FEEDBACKOFF'); + p = Log(p,TimeFeedbackOffset, 10, 0, p.phase, p.block); + MarkCED( p.com.lpt.address, 140); + + if error + draw_prd_background(p); + draw_square(p, 45); + draw_prd_sample(p, sample) + TimeErrorOnset = Screen('Flip',p.ptb.w); %<----- FLIP + draw_prd_background(p); + draw_square(p, 45); + draw_prd_sample(p, sample) + TimeErrorOffset = Screen('Flip',p.ptb.w, TimeErrorOnset+1); %<----- FLIP + end + end + + + function [p, TimeFeedbackOffset, prediction, abort] = predict_prd_sample(p, old_prediction, sample) + % Predict sample trial + abort = false; + prediction = nan; + update = nan; + TimeFeedbackOffset = nan; + %% STIMULUS ONSET + [keycode, secs] = KbQueueDump(p); + if numel(keycode) + for iii = 1:length(keycode) + pulses = (keycode(iii) == KbName(p.keys.pulse)); + if any(pulses); + p = Log(p,secs(pulses), 0, keycode(pulses), p.phase, p.block); + else + Log(p, secs(iii), 'NASSAR_PRD_BEFORE_RESP', keycode(iii), p.phase, p.block); + end + end + end + KbQueueFlush(p.ptb.device); + + Screen('FillRect', p.ptb.w, [20,20,255], p.FixCross'); + draw_prd_background(p); + draw_prd_sample(p, old_prediction); + draw_fix_bg_angled(p, 0); + TimeStimOnset = Screen('Flip',p.ptb.w); %<----- FLIP + Eyelink('Message', 'StimOnset'); + Eyelink('Message', 'SYNCTIME'); + MarkCED( p.com.lpt.address, 4); + p = Log(p, GetSecs, 'PRD_PREDICT_SAMPLE_ON', nan, p.phase, p.block); + p = Log(p,TimeStimOnset, 5, nan, p.phase, p.block); + Eyelink('Message', 'StimOff'); + MarkCED( p.com.lpt.address, 5); + + % Now do prediction. + % How do the controls work? Let's treat this thing as if + % If stimulus = 0, then left = x, right = m + % If stimulus = 1, then left = m, right = x + % Needs to be checked for consistency! + prediction = old_prediction; + start = GetSecs; + current = start; + response = nan; + RT = nan; + next_flip = start+p.ptb.slack*2; + modifier = 0; + currentup=GetSecs()-0.02; + while (current-start) < 20 + [evt, n] = KbEventGet(p.ptb.device); + %[keycodes, secs] = KbQueueDump(p); + if numel(evt)>0 + %keys = KbName(keycodes(i)); + keys = KbName(evt.Keycode); + switch keys + case p.keys.quit + abort = true; + return + case {p.keys.answer_a, p.keys.answer_a_train} + if evt.Pressed + modifier = -1; + else + modifier = 0; + end + + case {p.keys.answer_b, p.keys.answer_b_train} + if evt.Pressed + modifier = 1; + else + modifier = 0; + end + case {'space'} + break + case p.keys.pulse + p = Log(p,RT, 0, NaN, p.phase, p.block); + end + end + if GetSecs()-currentup > 0.1 + prediction = prediction + modifier; + currentup = GetSecs(); + end + + + current = GetSecs(); + if (current-next_flip) < (p.ptb.slack/2) + draw_prd_background(p) + draw_prd_sample(p, prediction) + draw_fix_bg_angled(p, 0); + update = Screen('Flip',p.ptb.w); + next_flip = update+p.ptb.slack*2; + end + + end + %draw_prd_background(p) + %draw_prd_sample(p, prediction); + %draw_fix_bg_angled(p, 0); + %lastflip = Screen('Flip',p.ptb.w); + % Now show prediction error + error = sample-prediction; + TimeFeedbackOffset = update; + + Eyelink('message', 'PREDICTION'); + p = Log(p,TimeFeedbackOffset, 10, 0, p.phase, p.block); + MarkCED( p.com.lpt.address, 140); + end + + + function draw_prd_sample(p, sample ) + %text = sprintf('%03i', sample); + %h = p.ptb.rect(2) + (p.ptb.rect(4)-p.ptb.rect(2))/2 + 10; + %Screen('TextSize', p.ptb.w, 75); + %DrawFormattedText(p.ptb.w, text, 'center', h, [168, 168, 168], [],[],[],2,[]); + %Screen('TextSize', p.ptb.w, 72); + %DrawFormattedText(p.ptb.w, text, 'center', h, [88, 88, 88], [],[],[],2,[]); + %Screen('TextSize', p.ptb.w, 70); + %DrawFormattedText(p.ptb.w, text, 'center', h, [128, 128, 128], [],[],[],2,[]); + Screen('BlendFunction', p.ptb.w, 'GL_SRC_ALPHA', 'GL_ONE_MINUS_SRC_ALPHA'); + Screen('DrawTexture', p.ptb.w, p.stim.sample_textures(sample)); + Screen('BlendFunction', p.ptb.w, 'GL_ONE', 'GL_ZERO'); + end + + + function draw_prd_background(p) + %Screen('DrawTexture', p.ptb.w, p.stim.noise_texture, [], p.ptb.rect); + end + + + function vbl = show_block(p, validity, duration, onset_time) + switch validity + case 1 + img=imread('instructions/instruction_A.png', 'BackgroundColor', [.5, .5, .5]); + case 0 + img=imread('instructions/instruction_B.png', 'BackgroundColor', [.5, .5, .5]); + case -1 + img=imread('instructions/instruction_both.png', 'BackgroundColor', [.5, .5, .5]); + end + instructions = Screen('MakeTexture', p.ptb.w, img); + Screen('DrawTexture', p.ptb.w, instructions, [], p.ptb.rect) + draw_fix(p, [], validity); + %text = ['Nochmal die Regeln als Erinnerung. Gleich gehts los']; + %DrawFormattedText(p.ptb.w, text, 'center', round(p.ptb.rect(4)*.1), p.stim.white,[],[],[],2,[]); + vbl = Screen('Flip', p.ptb.w, onset_time); + draw_fix(p); + vbl = Screen('Flip', p.ptb.w, vbl+duration); + end + + + function vbl = show_glaze_block(p, duration) + img=imread('instructions/instruction_glaze.png', 'BackgroundColor', [.5, .5, .5]); + instructions = Screen('MakeTexture', p.ptb.w, img); + Screen('DrawTexture', p.ptb.w, instructions, [], p.ptb.rect) + + Screen('DrawTexture', p.ptb.w, p.stim.left_txt, [], p.stim.left_rect); + Screen('DrawTexture', p.ptb.w, p.stim.right_txt, [], p.stim.right_rect); + + draw_fix(p); + vbl = Screen('Flip', p.ptb.w); + draw_fix(p); + if duration > 0 + vbl = Screen('Flip', p.ptb.w, vbl+duration); + end + end + + + function vbl = explain_retino_block(p) + %Screen('DrawTexture', p.ptb.w, instructions, [], p.ptb.rect) + text = ['Im naechsten Block musst du auf kleine Muster mit einem Knopfdruck reagieren.\n',... + 'Welcher Knopf gedrueckt werden muss haengt von der aktiven Regel ab.\n',... + 'Die aktive Regel wird durch Punkte neben dem Fixationskreuz angezeigt.\n']; + DrawFormattedText(p.ptb.w, text, 'center', round(p.ptb.rect(4)*.1), p.stim.white,[],[],[],2,[]); + draw_fix(p); + vbl = Screen('Flip', p.ptb.w); + KbStrokeWait(p.ptb.device); + DrawFormattedText(p.ptb.w, text, 'center', round(p.ptb.rect(4)*.1), p.stim.white,[],[],[],2,[]); + draw_fix(p, [], 1); + DrawFormattedText(p.ptb.w, ['Jetzt ist die Linke Regel aktiv!'], 'center', round(p.ptb.rect(4)*.75), p.stim.white,[],[],[],2,[]); + vbl = Screen('Flip', p.ptb.w); + KbStrokeWait(p.ptb.device); + + DrawFormattedText(p.ptb.w, text, 'center', round(p.ptb.rect(4)*.1), p.stim.white,[],[],[],2,[]); + draw_fix(p, [], 0); + DrawFormattedText(p.ptb.w, ['Jetzt ist die Rechte Regel aktiv!'], 'center', round(p.ptb.rect(4)*.75), p.stim.white,[],[],[],2,[]); + vbl = Screen('Flip', p.ptb.w); + KbStrokeWait(p.ptb.device); + + + Screen('DrawTexture', p.ptb.w, p.stim.left, [], p.ptb.rect) + draw_fix(p, [], 0); + draw_very_small_stimulus(p, 1) + text = ['Wenn die rechte Regel aktiv ist und ein\n',... + 'horizontales Muster erscheint muss die linke Taste gedrueckt werden.']; + DrawFormattedText(p.ptb.w, text, 'center', round(p.ptb.rect(4)*.1), p.stim.white,[],[],[],2,[]); + vbl = Screen('Flip', p.ptb.w); + KbStrokeWait(p.ptb.device); + + Screen('DrawTexture', p.ptb.w, p.stim.right, [], p.ptb.rect) + draw_fix(p, [], 0); + draw_very_small_stimulus(p, 0) + text = ['Wenn die rechte Regel aktiv ist und ein\n',... + 'vertikales Muster erscheint muss die rechte Taste gedrueckt werden.']; + DrawFormattedText(p.ptb.w, text, 'center', round(p.ptb.rect(4)*.1), p.stim.white,[],[],[],2,[]); + vbl = Screen('Flip', p.ptb.w); + KbStrokeWait(p.ptb.device); + + Screen('DrawTexture', p.ptb.w, p.stim.right, [], p.ptb.rect) + draw_fix(p, [], 1); + draw_very_small_stimulus(p, 1) + text = ['Wenn die linke Regel aktiv ist und ein\n',... + 'horizontales Muster erscheint muss die rechte Taste gedrueckt werden.']; + DrawFormattedText(p.ptb.w, text, 'center', round(p.ptb.rect(4)*.1), p.stim.white,[],[],[],2,[]); + vbl = Screen('Flip', p.ptb.w); + KbStrokeWait(p.ptb.device); + + Screen('DrawTexture', p.ptb.w, p.stim.left, [], p.ptb.rect) + draw_fix(p, [], 0); + draw_very_small_stimulus(p, 0) + text = ['Wenn die linke Regel aktiv ist und ein\n',... + 'vertikales Muster erscheint muss die linke Taste gedrueckt werden.']; + DrawFormattedText(p.ptb.w, text, 'center', round(p.ptb.rect(4)*.1), p.stim.white,[],[],[],2,[]); + vbl = Screen('Flip', p.ptb.w); + KbStrokeWait(p.ptb.device); + + Screen('DrawTexture', p.ptb.w, p.stim.instruction_both, [], p.ptb.rect) + text = ['Hier noch einmal eine Uebersicht:']; + DrawFormattedText(p.ptb.w, text, 'center', round(p.ptb.rect(4)*.1), p.stim.white,[],[],[],2,[]); + vbl = Screen('Flip', p.ptb.w); + KbStrokeWait(p.ptb.device); + + + text = ['Du hast jetzt die Moeglichkeit diese Regeln zu ueben.\n\n'... + 'Das Fixationskreuz wird gruen nach einer richtigen Regelanwendung\n'... + 'und rot nach einer falschen Regelanwendung.\n\n'... + 'Nicht vergessen: So wenig wie moeglich bewegen und immer (!) auf das\n'... + 'Fixationskreuz schauen. Das sich bewegende Zeug im Hintergrund einfach ignorieren...']; + DrawFormattedText(p.ptb.w, text, 'center', round(p.ptb.rect(4)*.1), p.stim.white,[],[],[],2,[]); + vbl = Screen('Flip', p.ptb.w); + KbStrokeWait(p.ptb.device); + + end + + + function vbl = explain_instructed_rule(p) + %Screen('DrawTexture', p.ptb.w, instructions, [], p.ptb.rect) + text = ['Im naechsten Block musst du auf grosze Muster mit einem Knopfdruck reagieren.\n',... + 'Welcher Knopf gedrueckt werden muss haengt wieder von der aktiven Regel ab.\n',... + 'Welche Regel aktiv ist zeigen wir dir bevor sie sich aendert.\n']; + DrawFormattedText(p.ptb.w, text, 'center', round(p.ptb.rect(4)*.1), p.stim.white,[],[],[],2,[]); + vbl = Screen('Flip', p.ptb.w); + KbStrokeWait(p.ptb.device); + + Screen('DrawTexture', p.ptb.w, p.stim.rule_left, [], p.ptb.rect) + draw_fix(p, [], 1); + text = ['Mit diesem Symbol zeigen wir dir, dass die linke Regel aktiv wird.']; + DrawFormattedText(p.ptb.w, text, 'center', round(p.ptb.rect(4)*.1), p.stim.white,[],[],[],2,[]); + vbl = Screen('Flip', p.ptb.w); + KbStrokeWait(p.ptb.device); + + Screen('DrawTexture', p.ptb.w, p.stim.rule_right, [], p.ptb.rect) + draw_fix(p, [], 0); + text = ['Mit diesem Symbol zeigen wir dir, dass die rechte Regel aktiv wird.']; + DrawFormattedText(p.ptb.w, text, 'center', round(p.ptb.rect(4)*.1), p.stim.white,[],[],[],2,[]); + vbl = Screen('Flip', p.ptb.w); + KbStrokeWait(p.ptb.device); + + text = ['Bereit?\n\n'... + 'Ach, in diesem Block wirst du uebrigens fuer richtige Antworten bezahlt.\nWie viel du verdient hast erfaehrst du am Ende vom Block.\n\n',... + 'Nicht vergessen: So wenig wie moeglich bewegen\n'... + 'und immer (!) auf das Fixationskreuz schauen.']; + DrawFormattedText(p.ptb.w, text, 'center', round(p.ptb.rect(4)*.1), p.stim.white,[],[],[],2,[]); + vbl = Screen('Flip', p.ptb.w); + KbStrokeWait(p.ptb.device); + + end + + + function vbl = explain_glaze_rule(p) + %Screen('DrawTexture', p.ptb.w, instructions, [], p.ptb.rect) + text = ['Im naechsten Block musst du auf grosze Muster mit einem Knopfdruck reagieren.\n',... + 'Welcher Knopf gedrueckt werden muss haengt wieder von der aktiven Regel ab.\n',... + 'Welche Regel aktiv ist musst du dieses mal selber herrausfinden.\n\n',... + 'Du wirst gleich in schneller Reihenfolge Punkte aufblinken sehen, deren seitlicher\n'... + 'Verschub Rueckschluesse auf die aktive Regel zulaesst.']; + DrawFormattedText(p.ptb.w, text, 'center', round(p.ptb.rect(4)*.1), p.stim.white,[],[],[],2,[]); + vbl = Screen('Flip', p.ptb.w); + KbStrokeWait(p.ptb.device); + + Screen('DrawTexture', p.ptb.w, p.stim.rule_left, [], p.ptb.rect) + Screen('DrawTexture', p.ptb.w, p.stim.left_txt, [], p.stim.left_rect) + draw_fix(p, [], 1); + text = ['Wenn z.B. die linke Regel aktiv ist folgen die Punkte der unten angezeigten Verteilung.\n']; + DrawFormattedText(p.ptb.w, text, 'center', round(p.ptb.rect(4)*.1), p.stim.white,[],[],[],2,[]); + vbl = Screen('Flip', p.ptb.w); + KbStrokeWait(p.ptb.device); + + Screen('DrawTexture', p.ptb.w, p.stim.rule_right, [], p.ptb.rect) + Screen('DrawTexture', p.ptb.w, p.stim.right_txt, [], p.stim.right_rect) + draw_fix(p, [], 1); + text = ['Wenn z.B. die rechte Regel aktiv ist folgen die Punkte dieser Verteilung.\n']; + DrawFormattedText(p.ptb.w, text, 'center', round(p.ptb.rect(4)*.1), p.stim.white,[],[],[],2,[]); + vbl = Screen('Flip', p.ptb.w); + KbStrokeWait(p.ptb.device); + + + Screen('DrawTexture', p.ptb.w, p.stim.right_txt, [], p.stim.right_rect) + Screen('DrawTexture', p.ptb.w, p.stim.left_txt, [], p.stim.left_rect) + draw_fix(p); + text = ['Wie du siehst sind beide Verteilungen stark ueberlappend!\n',... + 'Deswegen reicht ein einzelner Punkt nicht aus um die richtige Regel zu bestimmen.\n']; + DrawFormattedText(p.ptb.w, text, 'center', round(p.ptb.rect(4)*.1), p.stim.white,[],[],[],2,[]); + text = ['Stattdessen solltest du kontinuierlich ueberlegen welche Regel am besten mit der\n Position der letzten Punkte uebereinstimmt.\n',... + 'Auch wichtig: Die aktive Regel aendert sich unvorhersehbar!']; + DrawFormattedText(p.ptb.w, text, 'center', round(p.ptb.rect(4)*.75), p.stim.white,[],[],[],2,[]); + vbl = Screen('Flip', p.ptb.w); + KbStrokeWait(p.ptb.device); + + end + + + function text = RewardText(reward, reward_rate, earned_money, total_money) + text = [sprintf('Im letzten Block haben Sie %d Belohnungen erhalten (%2.0f%%)\n', reward, 100*reward_rate)... + sprintf('Das entspricht %1.2f EUR!\n', earned_money)... + sprintf('Insgesamt haben sich damit %1.2f EUR Bonus angesammelt!', total_money)]; + end + + + function text = NassarRewardText(error, reward_rate, earned_money, total_money) + text = [sprintf('Im letzten Block war ihr mittlerer Fehler %3.1f.\n', roundn(error, -1))... + sprintf('Damit bekommen Sie %2.0d%% der Belohung ausgezahlt\n', reward_rate*100),... + sprintf('Das entspricht %1.2f EUR!\n', earned_money)... + sprintf('Insgesamt haben sich damit %1.2f EUR Bonus angesammelt!', total_money)]; + end + + + function ShowInstruction(waitforkeypress, text) + %ShowInstruction(nInstruct,waitforkeypress) + %if waitforkeypress is 1, ==> subject presses a button to proceed + %if waitforkeypress is 2, ==> show text and immediately return + %if waitforkeypress is <0, ==> text is shown for -waitforkeypress seconds. + + + ShowText(text); + + if waitforkeypress==1 %and blank the screen as soon as the key is pressed + KbStrokeWait(p.ptb.device); + elseif waitforkeypress==2 + return + else + WaitSecs(-waitforkeypress); + end + Screen('FillRect',p.ptb.w,p.var.current_bg); + Screen('Flip',p.ptb.w); + end + + + function ShowText(text, onset) + + Screen('FillRect',p.ptb.w,p.var.current_bg); + DrawFormattedText(p.ptb.w, text, 'center', 'center', p.stim.white,[],[],[],2,[]); + if nargin==1 + Screen('Flip',p.ptb.w); + else + Screen('Flip',p.ptb.w, onset); + end + %show the messages at the experimenter screen + end + + + function ShowImage(image, onset) + + Screen('FillRect',p.ptb.w,p.var.current_bg); + DrawFormattedText(p.ptb.w, text, 'center', 'center', p.stim.white,[],[],[],2,[]); + if nargin==1 + Screen('Flip',p.ptb.w); + else + Screen('Flip',p.ptb.w, onset); + end + %show the messages at the experimenter screen + end + + + function [text]=GetText(nInstruct, train) + if nInstruct == 1 %Retinotopy. + text = ['Im n�chsten Block hast du die Gelegenheit beide Regeln zu �ben.\n'... + '']; + + + elseif nInstruct == 2 %Task. + text = ['Nun beginnt ein weitere Block des Experimentes.\n'... + 'Finden Sie herraus welche Regel gerade korrekt ist!\n'... + 'Zur Erinnerung:\n Regel I -> ANSWERA: || ANSWERB: =\n'... + ' Regel II -> ANSWERA: = ANSWERB: ||\n'... + 'Druecken Sie einen Knopf um weiter zu machen.\n']; + + elseif nInstruct == 3 %Q Rule I. + text = ['Im naechsten Block ist Regel I die richtige.\n'... + 'Zur Erinnerung:\n ANSWERA: ||\n ANSWERB: = \n'... + 'Druecken Sie einen Knopf um weiter zu machen.\n']; + + elseif nInstruct == 4 %Q Rule B. + text = ['Im naechsten Block ist Regel II die richtige.\n'... + 'Zur Erinnerung:\n ANSWERA: =\n ANSWERB: ||\n'... + 'Druecken Sie einen Knopf um weiter zu machen.\n']; + else + text = {''}; + end + if ~train + text = strrep(text, 'ANSWERA', '1'); + text = strrep(text, 'ANSWERB', '2'); + else + text = strrep(text, 'ANSWERA', 'x'); + text = strrep(text, 'ANSWERB', 'm'); + end + end + + + function SetParams + %mrt business + p.mrt.dummy_scan = 5; %this will wait until the 6th image is acquired. + p.mrt.LastScans = 5; %number of scans after the offset of the last stimulus + p.mrt.tr = 2; %in seconds. + + %will count the number of events to be logged + p.var.event_count = 0; + + + %% relative path to stim and experiments + %Path Business. + [~, hostname] = system('hostname'); + p.hostname = deblank(hostname); + + if strcmp(p.hostname, 'larry.local') + p.display.resolution = [1920 1200]; %For the EliteDisplay in the office + p.display.dimension = [28, 17.5]; %Macbook display + p.display.dimension = [52, 33]; % + p.display.distance = [62, 59]; + p.path.baselocation = '/Users/nwilming/u/flexible_rule/experiment/data/'; + elseif strcmp(p.hostname, 'donnerlab-Precision-T1700') + p.display.resolution = [1920 1080]; + p.display.dimension = [52, 29.5]; + p.display.distance = [62, 59]; + p.path.baselocation = '/home/donnerlab/experiments/flexrule/data'; + else + p.display.resolution = [1920 1080]; + p.display.dimension = [52, 29.5]; + p.display.distance = [62, 59]; + p.path.baselocation = 'C:\USER\wilming\experiment\data'; + end + %p.path.baselocation = 'C:\Users\...\Documents\Experiments\immuno/data'; + + p.display.ppd = ppd(mean(p.display.distance), p.display.resolution(1),... + p.display.dimension(1)); + p.stim.bar_width = 400; + p.stim.bar_separation = 50; + p.stim.r_inner = .1; + p.stim.lumdiff = 50; + p.stim.sample_duration = .1; + p.stim.threshold = .5; + p.stim.sigma = 1; + %create the base folder if not yet there. + if exist(p.path.baselocation) == 0 %#ok + mkdir(p.path.baselocation); + end + + p.subject = subject; %subject id + p.timestamp = datestr(now, 30); %the time_stamp of the current experiment. + + %% %%%%%%%%%%%%%%%%%%%%%%%%% + p.stim.bg = [128, 128, 128]; + p.stim.white = get_color('white'); + p.text.fontname = 'Times New Roman'; + p.text.fontsize = 18; + p.text.fixsize = 60; + + + %% keys to be used during the experiment: + %This part is highly specific for your system and recording setup, + %please enter the correct key identifiers. You can get this information calling the + %KbName function and replacing the code below for the key below. + %1, 6 ==> Right + %2, 7 ==> Left + %3, 8 ==> Down + %4, 9 ==> Up (confirm) + %5 ==> Pulse from the scanner + + KbName('UnifyKeyNames'); + p.keys.confirm = '4$';% + p.keys.answer_a = {'1!', '2@', '3#', '4$'}; + p.keys.answer_a_train = 'x'; + p.keys.answer_b = {'6^', '7&', '8*', '9('}; + p.keys.answer_b_train = 'm'; + p.keys.pulse = '5%'; + p.keys.el_calib = 'v'; + p.keys.el_valid = 'c'; + p.keys.escape = 'ESCAPE'; + p.keys.enter = 'return'; + p.keys.quit = 'q'; + p.keylist = {p.keys.confirm,... + p.keys.answer_a{1}, p.keys.answer_a{2},p.keys.answer_a{3},p.keys.answer_a{4},... + p.keys.answer_b{1}, p.keys.answer_b{2},p.keys.answer_b{3},p.keys.answer_b{4},... + p.keys.answer_a_train,... + p.keys.answer_b_train, p.keys.pulse,... + p.keys.el_calib, p.keys.el_valid, p.keys.enter}; + %% %%%%%%%%%%%%%%%%%%%%%%%%% + %Communication business + %parallel port + p.com.lpt.address = 888;%parallel port of the computer. + %codes for different events that are sent for logging in the + %physiological computer. + p.com.lpt.resp0 = 128; + p.com.lpt.resp1 = 64; + p.com.lpt.stim = 32; + p.com.lpt.sample = 16; + %Record which Phase are we going to run in this run. + p.stim.phase = phase; + p.out.log = cell(1000000,1);%Experimental LOG. + + %% + p.var.current_bg = p.stim.bg;%current background to be used. + %save(p.path.path_param,'p'); + end + + + function SetPTB + %Sets the parameters related to the PTB toolbox. Including + %fontsizes, font names. + %Default parameters + Screen('Preference', 'SkipSyncTests', 1); + Screen('Preference', 'DefaultFontSize', p.text.fontsize); + Screen('Preference', 'DefaultFontName', p.text.fontname); + Screen('Preference', 'TextAntiAliasing',2);%enable textantialiasing high quality + Screen('Preference', 'VisualDebuglevel', 0); + Screen('Preference', 'SkipSyncTests', 1); + Screen('Preference', 'SuppressAllWarnings', 1); + %%Find the number of the screen to be opened + screens = Screen('Screens'); + if strcmp(p.hostname, 'larry.local') + p.ptb.screenNumber = min(screens);%the maximum is the second monitor + [idx, names, ~] = GetKeyboardIndices; + p.ptb.device = nan; + for iii = 1:length(idx) + if strcmp(names{iii}, '') + p.ptb.device = idx(iii); + break + elseif strcmp(names{iii}, 'Apple Internal Keyboard / Trackpad') && isnan(p.ptb.device) + p.ptb.device = idx(iii); + break + end + end + fprintf('Device name is: %s\n', names{iii}) + gamma = load('dell241i_calibration.mat'); + p.ptb.gamma = gamma.gTmp; + elseif strcmp(p.hostname, 'donnerlab-Precision-T1700') + p.ptb.screenNumber = 0; + [idx, names, ~] = GetKeyboardIndices; + p.ptb.device = nan; + for iii = 1:length(idx) + if strcmp(names{iii}, 'DELL Dell USB Entry Keyboard') + p.ptb.device = idx(iii); + break + end + end + p.ptb.device + gamma = load('vpixx_gamma_table.mat'); + p.ptb.gamma = gamma.table; + else + p.ptb.screenNumber = max(screens);%the maximum is the second monitor + p.ptb.device = -1; + gamma = load('nne_uke_scanner.mat'); + gamma = [0 0 0; gamma.gammaTable]; + p.ptb.gamma = gamma; + end + p.ptb.screenNumber + %Make everything transparent for debugging purposes. + + if debug + commandwindow; + PsychDebugWindowConfiguration; + end + %set the resolution correctly + res = Screen('resolution', p.ptb.screenNumber); + HideCursor(p.ptb.screenNumber);%make sure that the mouse is not shown at the participant's monitor + %spit out the resolution, + fprintf('Resolution of the screen is %dx%d...\n',res.width,res.height); + + %Open a graphics window using PTB + if ~small_window + [p.ptb.w, p.ptb.rect] = Screen('OpenWindow', p.ptb.screenNumber, [128, 128, 128]); + else + [p.ptb.w, p.ptb.rect] = Screen('OpenWindow', p.ptb.screenNumber, [128, 128, 128], [0, 0, 900, 700]); + end + + BackupCluts(); + if numel(p.ptb.gamma, 2) > 0 + [old_table] = Screen('LoadNormalizedGammaTable', p.ptb.w, p.ptb.gamma); + p.ptb.gamma_loaded = true; + p.ptb.old_gamma = old_table; + p.ptb.gamma_loaded = false; + else + p.ptb.gamma_loaded=false + end + Screen('Flip',p.ptb.w);%make the bg + + p.ptb.slack = Screen('GetFlipInterval',p.ptb.w)./2; + [p.ptb.width, p.ptb.height] = Screen('WindowSize', p.ptb.screenNumber); + + %find the mid position on the screen. + x = p.ptb.rect(1) + (p.ptb.rect(3)/2); + y = p.ptb.rect(2) + (p.ptb.rect(4)/2); + + p.ptb.midpoint = [x, y]; % p.ptb.width./2 p.ptb.height./2]; + %NOTE about RECT: + %RectLeft=1, RectTop=2, RectRight=3, RectBottom=4. + p.ptb.CrossPosition_x = p.ptb.midpoint(1); + p.ptb.CrossPosition_y = p.ptb.midpoint(2); + %cross position for the eyetracker screen. + p.ptb.fc_size = 10; + + Priority(MaxPriority(p.ptb.w)); + + + if IsWindows + LoadPsychHID; + end + %%%%%%%%%%%%%%%%%%%%%%%%%%%Prepare the keypress queue listening. + + %get all the required keys in a vector + p.ptb.keysOfInterest = []; + for i = fields(p.keys)'; + p.ptb.keysOfInterest = [p.ptb.keysOfInterest KbName(p.keys.(i{1}))]; + end + RestrictKeysForKbCheck(p.ptb.keysOfInterest); + KbQueueCreate(p.ptb.device);%, p.ptb.keysOfInterest);%default device. + %%%%%%%%%%%%%%%%%%%%%%%%%%% + %prepare parallel port communication. This relies on cogent i + %think. We could do it with PTB as well.options + if IsWindows + config_io; + outp(p.com.lpt.address,0); + if( cogent.io.status ~= 0 ) + error('inp/outp installation failed'); + end + end + + %% Build a procedural gabor texture for a gabor with a support of tw x th + % pixels, and a RGB color offset of 0.5 -- a 50% gray. + p.stim.radius = p.ptb.rect(4)/2; + p.stim.radius_deg = (p.ptb.rect(4)/2)/p.display.ppd; + p.stim.sf = 1.2/p.display.ppd; + fprintf('R and SF: %f %f', p.stim.radius, p.stim.sf) + %p.ptb.gabortex = CreateProceduralGabor(p.ptb.w, p.ptb.width, p.ptb.height, 0, [0.5 0.5 0.5 0.0]); + p.ptb.gabortex = CreateProceduralSineGrating(p.ptb.w, 2*p.stim.radius, 2*p.stim.radius,... + [], p.stim.radius); + + %% %%%%%%%%%%%%%%%%%%%%%%%%% + %Make final reminders to the experimenter to avoid false starts, + %which are annoying. Here I specifically send test pulses to the + %physio computer and check if everything OK. + % k = 0; + % while ~(k == p.keys.el_calib);%press V to continue + % pause(0.1); + % outp(p.com.lpt.address,244);%244 means all but the UCS channel (so that we dont shock the subject during initialization). + % fprintf('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'); + % fprintf('1/ Red cable has to be connected to the Cogent BOX\n'); + % fprintf('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'); + % fprintf('2/ D2 Connection not to forget on the LPT panel\n'); + % fprintf('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'); + % fprintf('3/ Switch the SCR cable\n'); + % fprintf('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'); + % fprintf('4/ Button box has to be on\n'); + % fprintf('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'); + % fprintf('5/ Did the trigger test work?\n!!!!!!You MUST observe 5 pulses on the PHYSIOCOMPUTER!!!!!\n\n\nPress V(alidate) to continue experiment or C to continue sending test pulses...\n') + % [~, k] = KbStrokeWait(p.ptb.device); + % k = find(k); + % end + + + fix = [p.ptb.CrossPosition_x p.ptb.CrossPosition_y]; + + d = (p.ptb.fc_size(1)^2/2)^.5; + p.square = [fix(1)-d, fix(2)-d, fix(1)+d, fix(2)+d]; + p.FixCross = [fix(1)-1,fix(2)-p.ptb.fc_size,fix(1)+1,fix(2)+p.ptb.fc_size;fix(1)-p.ptb.fc_size,fix(2)-1,fix(1)+p.ptb.fc_size,fix(2)+1]; + p.FixCross_s = [fix(1)-1,fix(2)-p.ptb.fc_size/2,fix(1)+1,fix(2)+p.ptb.fc_size/2;fix(1)-p.ptb.fc_size/2,fix(2)-1,fix(1)+p.ptb.fc_size/2,fix(2)+1]; + p = make_dist_textures(p); + l = p.ptb.rect(1); t = p.ptb.rect(2); r = p.ptb.rect(3); b = p.ptb.rect(4); + p.stim.left_rect = [l, (b-t)/2-5-20, r, (b-t)/2+5-20]; + p.stim.right_rect = [l, 20+(b-t)/2-5, r, 20+(b-t)/2+5]; + end + + + function [t]=StartEyelinkRecording(nTrial, phase, rewarded_rule, stim, block_id, type) + if ~NoEyelink + Eyelink('Message', sprintf('TRIALID: %04d, PHASE: %04d, REWRULE: %04d, STIM: %04d, BLOCK %04d, TYPE %04d', nTrial, phase, rewarded_rule, stim, block_id, type)); + Eyelink('Command', 'record_status_message "Trial: %i"', nTrial); + t = GetSecs; + else + t = GetSecs; + end + end + + + function [t]=StartGlazeEyelinkRecording(nTrial, phase) + if ~NoEyelink + Eyelink('Message', 'GLAZEBLOCK: %04d, phase:%04d', nTrial, phase); + t = GetSecs; + else + t = GetSecs; + end + end + + + function [t]=StarRetinoEyelinkRecording(type, reverse) + if ~NoEyelink + str = sprintf( 'RETINO_BLOCK_START %s %i', type, reverse); + Eyelink('Message', str); + t = GetSecs; + else + t = GetSecs; + end + end + + + function p=InitEyeLink(p) + % + if EyelinkInit(NoEyelink)%use 0 to init normaly + fprintf('=================\nEyelink initialized correctly...\n') + else + fprintf('=================\nThere is problem in Eyelink initialization\n') + keyboard; + end + % + WaitSecs(0.5); + [~, vs] = Eyelink('GetTrackerVersion'); + fprintf('=================\nRunning experiment on a ''%s'' tracker.\n', vs ); + + % + el = EyelinkInitDefaults(p.ptb.w); + %update the defaults of the eyelink tracker + el.backgroundcolour = p.stim.bg; + el.msgfontcolour = WhiteIndex(el.window); + el.imgtitlecolour = WhiteIndex(el.window); + el.targetbeep = 0; + el.calibrationtargetcolour = WhiteIndex(el.window); + el.calibrationtargetsize = 1.5; + el.calibrationtargetwidth = 0.5; + el.displayCalResults = 1; + el.eyeimgsize = 50; + el.waitformodereadytime = 25;%ms + el.msgfont = 'Times New Roman'; + el.cal_target_beep = [0 0 0];%[1250 0.6 0.05]; + %shut all sounds off + el.drift_correction_targetp.ptb.wid_beep = [0 0 0]; + el.calibration_failed_beep = [0 0 0]; + el.calibration_success_beep = [0 0 0]; + el.drift_correction_failed_beep = [0 0 0]; + el.drift_correction_success_beep= [0 0 0]; + EyelinkUpdateDefaults(el); + PsychEyelinkDispatchCallback(el); + + % open file. + if p.subject <= -100 + p.edffile = 'samptest.edf'; + else + p.edffile = sprintf('%d%d%d.edf', p.subject, p.phase, p.block); + end + res = Eyelink('Openfile', p.edffile); %#ok + + %Eyelink('command', 'add_file_preamble_text ''Recorded by EyelinkToolbox FearAmy Experiment (Selim Onat)'''); + Eyelink('command', 'screen_pixel_coords = %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); + Eyelink('message', 'DISPLAY_COORDS %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); + + pw = p.display.dimension(1); + ph = p.display.dimension(2); + phys_coord = sprintf('screen_phys_coords = %ld, %ld, %ld, %ld'... + , -floor(10*pw/2)... %half width + , floor(10*ph/2)... %half height + , floor(10*pw/2)... %half width + , -floor(10*ph/2)); %half height %rv 2 + Eyelink('command', phys_coord); + + Eyelink('command', 'screen_distance = %ld %ld', ... + 10*p.display.distance(2), 10*p.display.distance(2)); %rv 3 + + % set calibration type. + Eyelink('command','auto_calibration_messages = YES'); + Eyelink('command', 'calibration_type = HV13'); + Eyelink('command', 'select_parser_configuration = 1'); + %what do we want to record + Eyelink('command', 'file_sample_data = LEFT,RIGHT,GAZE,HREF,AREA,GAZERES,STATUS,INPUT,HTARGET'); + Eyelink('command', 'file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON,INPUT'); + Eyelink('command', 'use_ellipse_fitter = no'); + % set sample rate in camera setup screen + Eyelink('command', 'sample_rate = %d',1000); + + end + + + function StopEyelink(filename, path_edf) + if ~NoEyelink + try + fprintf('Trying to stop the Eyelink system with StopEyelink\n'); + Eyelink('StopRecording'); + WaitSecs(0.5); + Eyelink('Closefile'); + display('receiving the EDF file...'); + Eyelink('ReceiveFile', filename, path_edf); + display('...finished!') + % Shutdown Eyelink: + Eyelink('Shutdown'); + catch + display('StopEyeLink routine didn''t really run well'); + end + end + end + + + function cleanup + % Close window: + RestoreCluts() + %Screen('flip', p.ptb.w) + sca; + %set back the old resolution + if strcmp(p.hostname,'triostim1') + % Screen('Resolution',p.ptb.screenNumber, p.ptb.oldres.width, p.ptb.oldres.height ); + %show the cursor + ShowCursor(p.ptb.screenNumber); + end + % + commandwindow; + KbQueueStop(p.ptb.device); + KbQueueRelease(p.ptb.device); + end + + + function CalibrateEL + fprintf('=================\n=================\nEntering Eyelink Calibration\n') + p.var.ExpPhase = 0; + EyelinkDoTrackerSetup(el); + %Returns 'messageString' text associated with result of last calibration + [~, messageString] = Eyelink('CalMessage'); + Eyelink('Message','%s', messageString);% + WaitSecs(0.05); + fprintf('=================\n=================\nNow we are done with the calibration\n') + if numel(p.ptb.gamma, 2) > 0 + [old_table] = Screen('LoadNormalizedGammaTable', p.ptb.w, p.ptb.gamma); + p.ptb.gamma_loaded = true; + p.ptb.old_gamma = old_table; + p.ptb.gamma_loaded = false; + else + p.ptb.gamma_loaded=false; + end + end + + + function p = Log(p, ptb_time, event_type, event_info, phase, block) + for iii = 1:length(ptb_time) + p.var.event_count = p.var.event_count + 1; + p.out.log{p.var.event_count} = {ptb_time(iii) event_type event_info(iii) phase block}; + %fprintf('LOG: %2.2f, %i, %s, %s, %i \n', ptb_time, event_type, event_info, phase, block) + end + + end + + + function [secs, p]=WaitPulse(p, keycode,n) + %[secs]=WaitPulse(keycode,n) + % + % This function waits for the Nth upcoming pulse. If N=1, it will wait for + % the very next pulse to arrive. 1 MEANS NEXT PULSE. So if you wish to wait + % for 6 full dummy scans, you should use N = 7 to be sure that at least 6 + % full acquisitions are finished. + % + % The function avoids KbCheck, KbWait functions, but relies on the OS + % level event queues, which are much less likely to skip short events. A + % nice discussion on the topic can be found here: + % http://ftp.tuebingen.mpg.de/pub/pub_dahl/stmdev10_D/Matlab6/Toolboxes/Psychtoolbox/PsychDocumentation/KbQueue.html + KbQueueStop(p.ptb.device); + KbQueueRelease(p.ptb.device); + fprintf('Will wait for %i dummy pulses...\n',n); + if n ~= 0 + secs = nan(1,n); + pulse = 0; + %dummy = []; + while pulse < n + dummy = KbTriggerWait(KbName(keycode), p.ptb.device); + pulse = pulse + 1; + fprintf('.') + secs(pulse+1) = dummy; + p = Log(p, dummy, 0, NaN, 0, 0); + end + else + secs = GetSecs; + end + fprintf('\n') + end + + + function [keycode, secs] = KbQueueDump(p) + %[keycode, secs] = KbQueueDump + % Will dump all the events accumulated in the queue. + keycode = []; + secs = []; + pressed = []; + while KbEventAvail(p.ptb.device) + [evt, n] = KbEventGet(p.ptb.device); + n = n + 1; + keycode(n) = evt.Keycode; %#ok + pressed(n) = evt.Pressed; %#ok + secs(n) = evt.Time; %#ok + end + i = pressed == 1; + keycode(~i) = []; + secs(~i) = []; + + end + + + function [keyIsDown, firstPress] = check_kbqueues(devices) %#ok + firstPress = boolean(zeros(1, 256)); + keyIsDown = false; + for device = devices + [kD, fP] = PsychHID('KbQueueCheck', device); + keyIsDown = keyIsDown | kD; + firstPress = firstPress | boolean(fP); + end + end + + + function p = save_data(p, all_rewards) %#ok + p.save_time = datestr(now, 'dd-mmm-yyyy HH:MM:SS'); + rst = randstr(5); + p.random_stirng = rst; + path = fullfile(p.path.baselocation, sprintf('SUB_%i', p.subject), sprintf('PH_%d', p.phase, p.block)); + if ~exist(path) %#ok + mkdir(path) + end + + path_reward = fullfile(p.path.baselocation, sprintf('SUB_%i', p.subject)); + if ~exist(path) %#ok + mkdir(path) + end + + path_edf = fullfile(path, sprintf('S%d_P%d_B%d_%s_%s.edf', p.subject, p.phase, p.block, p.start_time, rst)) + path_data = fullfile(path, sprintf('S%d_P%d_B%d_%s_%s_data.mat', p.subject, p.phase, p.block, p.start_time, rst)) + path_rewards = fullfile(path_reward,'rewards_latest.mat'); + path_rewards_ts = fullfile(path_reward, sprintf('rewards_%s_%s.mat', p.start_time, rst)); + %get the eyelink file back to this computer + StopEyelink(p.edffile, path_edf); + %trim the log file and save + p.out.log = p.out.log(1:p.var.event_count); + + %shift the time so that the first timestamp is equal to zero + %p.out.log(:,1) = p.out.log(:,1) - p.out.log(1); + %p.out.log = p.out.log;%copy it to the output variable. + save(path_data, 'p'); + save(path_rewards, 'all_rewards') + save(path_rewards_ts, 'all_rewards') + + end + + + function r = randstr(n) + symbols = ['a':'z' 'A':'Z' '0':'9']; + stLength = randi(n); + nums = randi(numel(symbols),[1 stLength]); + r = symbols (nums); + end + + + function ppd = ppd(distance, x_px, width) + o = tan(0.5*pi/180) * distance; + ppd = 2 * o*x_px/width; + end + + + function MarkCED(socket,port) + %send pulse to SCR# + outp(socket,port); + WaitSecs(0.01); + outp(socket,0); + end + + + function p = make_dist_textures(p) + ppd = p.display.ppd; + w = p.ptb.rect(3)-p.ptb.rect(1); + h = p.ptb.rect(4)-p.ptb.rect(2); + x = (1:w)/ppd; + x = x- ((w/2)/ppd); + left = (normpdf(x, -p.stim.threshold, p.stim.sigma)); + left = left-min(left); + right = (normpdf(x, p.stim.threshold, p.stim.sigma)); + right = right-min(right); + left = 128+128*(left/max(left)); + right = 128+128*(right/max(right)); + + p.stim.left_txt = Screen('MakeTexture', p.ptb.w, left); + p.stim.right_txt = Screen('MakeTexture', p.ptb.w, right); + + img=imread('instructions/left.png', 'BackgroundColor', [.5, .5, .5]); + p.stim.left = Screen('MakeTexture', p.ptb.w, img); + + img=imread('instructions/right.png', 'BackgroundColor', [.5, .5, .5]); + p.stim.right = Screen('MakeTexture', p.ptb.w, img); + + img=imread('instructions/instruction_both.png', 'BackgroundColor', [.5, .5, .5]); + p.stim.instruction_both = Screen('MakeTexture', p.ptb.w, img); + + img=imread('instructions/instruction_A.png', 'BackgroundColor', [.5, .5, .5]); + p.stim.rule_left = Screen('MakeTexture', p.ptb.w, img); + + img=imread('instructions/instruction_B.png', 'BackgroundColor', [.5, .5, .5]); + p.stim.rule_right = Screen('MakeTexture', p.ptb.w, img); + + img=imread('instructions/instruction_connectivity_B_S1.png', 'BackgroundColor', [.5, .5, .5]); + p.stim.instruction_B1S1 = Screen('MakeTexture', p.ptb.w, img); + + img=imread('instructions/instruction_connectivity_B_S2.png', 'BackgroundColor', [.5, .5, .5]); + p.stim.instruction_B1S2 = Screen('MakeTexture', p.ptb.w, img); + + + noise = round(rand(round(h), round(w))*255); + %noise = imresize(noise, [h, w], 'nearest'); + %noise = 255*(noise>mean(noise(:))); + p.stim.noise_texture = Screen('MakeTexture', p.ptb.w, noise); + + I = cat(3, ones(h, w)*128, ones(h, w)*0); + p.stim.fix = Screen('MakeTexture', p.ptb.w, I); + Screen('FillRect', p.stim.fix, [255, 255, 255], p.FixCross') + %cross = cat(3, [[0, 255, 0]; [255, 255, 255]; [0, 255, 0]], [[0, 255, 0]; [255, 255, 255]; [0, 255, 0]]); + %p.stim.fix = Screen('MakeTexture', p.ptb.w, cross); + %cx = w/2; + %cy = h/2; + %d = p.display.ppd*0.5; + %p.stim.fix_rect = [cx-d, cy-d, cx+d, cy+d]; + I = cat(3, ones(h, w)*128, ones(h, w)*0); + p.stim.square = Screen('MakeTexture', p.ptb.w, I); + Screen('FrameRect', p.stim.square, [255, 255, 255], p.square, 2); + end + + + function p = make_sample_textures(p, noise) + if nargin==1 + noise = true; + end + tic; + [~, hostname] = system('hostname'); + hostname = hostname(1:end-1); + cachefile = sprintf('%s_nassar_sample_spec.mat', hostname); + stimuli = {}; + if exist(cachefile, 'file') + stimuli = load(cachefile); + stimuli = stimuli.stimuli; + else + w = p.ptb.rect(3)-p.ptb.rect(1); + h = p.ptb.rect(4)-p.ptb.rect(2); + + I = cat(3, ones(h, w)*0); + if noise + noise = (double(rand(round(h), round(w))>0.5))*255; + else + noise = ones(round(h), round(w))*255; + end + fprintf('Uniques....\n') + for ii = 1:300 + txt = Screen('MakeTexture', p.ptb.w, I); + Screen('TextSize', txt, 50); + Screen('TextFont', txt, 'Courier'); + Screen('TextStyle', txt, 1); + hpos = p.ptb.rect(2) + (p.ptb.rect(4)-p.ptb.rect(2))/2 + 10; + %Screen('FillRect', txt , p.stim.bg, [] ); + DrawFormattedText(txt, sprintf('%03d', ii), 'center', hpos, [255, 255, 255], [],[],[],2,[]); + imageArray= double(Screen('GetImage', txt)); + + b = double(mean(imageArray, 3)>128); + [w, h] = size(b); + cx = w/2; + cy = h/2; + b = b(cx-200:cx+200, cy-200:cy+200); + + img_incl_alpha = cat(3, b.*noise(cx-200:cx+200, cy-200:cy+200), b*255); + stimuli{ii} = img_incl_alpha; %#ok + end + + save(cachefile, 'stimuli', '-v7.3'); + end + %noise = (noise>mean(noise(:))); + textures = []; + target_rect = [1960/2-200, 1080/2-200, 1960/2+200, 1080/2+200]; + for ii = 1:300 + if mod(ii, 10)==0 + fprintf('.') + end + stim = stimuli{ii}; + %stim = cat(3, stim, (~(stim==128))*255); + txt = Screen('MakeTexture', p.ptb.w, stim); + textures = [textures, txt]; %#ok + end + fprintf('\n') + p.stim.sample_textures = textures; + p.stim.sample_stimuli=stimuli; + toc; + end + +end diff --git a/exp_Discrimination.m b/exp_Discrimination.m deleted file mode 100755 index b52964a..0000000 --- a/exp_Discrimination.m +++ /dev/null @@ -1,185 +0,0 @@ -function [p]=Discrimination(name,repetition) - -p = [];%information to be saved to the disk -st = [];%stimulus properties -stim = [];%will store the stimulus -stimPink = [];%will store the pink noise images -SetParams; -% -ConfigCogent; -CreateSprites(st.fam_path2stim, st.fam_files , (1:st.fam_tStim) +100 ); -CreateSprites(st.path2stim, st.files , 1:st.tStim ); - -clearpict(20); -drawpict(20); -% -%familiarization runs%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - cgtext('Bewertung der Gesichterpaare ("identisch" und "verschieden") mit STRG-links und STRG-rechts',0,0); - cgflip(st.bg); - waitkeydown(inf); - cgtext('Zuerst einige Probedurchgänge... Bitte Taste drücken um anzufangen',0,0); - cgflip(st.bg); - waitkeydown(inf); - for np = sub2ind([st.tStim st.tStim],[1 2 3 4 5 3], [1 6 3 7 5 8])% - [y x] = ind2sub([st.tStim,st.tStim],np); - y = y + 100; - x = x + 100; - clearkeys; - %show stimulus - Trial; - end -% -%main experiment.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -cgtext('Probedurchgänge abgeschlossen... Nun beginnt das echte Experiment... Bitte beliebige Taste drücken',0,0); - -%%% cgtext('Info zum Experiment, CTRL -cgflip(st.bg); -waitkeydown(inf); -% -p.results.count_mat = zeros(st.tStim); -p.results.response = zeros(st.tStim); -counter = 0; -tTrial = length(p.presentation.order'); -for np = p.presentation.order' - counter = counter + 1; - [y x] = ind2sub([st.tStim,st.tStim],np); - clearkeys; - %show stimulus - Trial; - if key == 60 - p.results.response(y,x) = p.results.response(y,x) + 1; - elseif key == 91 - p.results.response(y,x) = p.results.response(y,x) + 0; - end - p.results.time(counter) = t; - p.results.pair(:,counter) = [y;x]; - p.results.count_mat(y,x) = p.results.count_mat(y,x) + 1; - save(savefilename,'p') - - if counter == round(tTrial/2) - cgtext('Pause, Taste drücken um fortzufahren',0,0); - cgflip(st.bg); - [key,t,n] = waitkeydown( inf ); - end - -end -stop_cogent; -% - function Trial - GetPinkNoise; - %add the fixation cross - %Show the pink noise - cgdrawsprite(17,0,0); - cgflip(st.bg); - wait(p.duration.pn_prestim*(rand(1)+1));%duration changes between [pn_prestim 2*pn_prestim]; - %Show the face 1 - cgdrawsprite(x,0,0); - cgflip(st.bg); - wait(p.duration.stim); - %Show the pink noise - cgdrawsprite(18,0,0); - cgflip(st.bg); - wait(p.duration.isi*(rand(1)+1)); - %Show the face 2 - cgdrawsprite(y,0,0); - cgflip(st.bg); - wait(p.duration.stim); - %Show text - cgtext('Identisch Verschieden',0,0); - cgflip(st.bg); - %91: right control (different) - %60: left control (same) - [key,t,n] = waitkeydown( inf , [60 91] ); - - end - function GetPinkNoise - res = st.resolution(1); - tPix = st.resolution(1).*st.resolution(2); - for n = 1:3 - stimPink(:,:,:,n) = repmat(maskit(Image2PinkNoise(stim(:,:,y)),st.win,st.bg(1)),[1 1 3]); - cgloadarray(16+n,res,res,reshape(double(imrotate(stimPink(:,:,:,n),90)),[tPix 3]),res,res); - cgsetsprite(16+n); - end - cgsetsprite(0); - end - function im = maskit(im,win,bg) - m = mean2(im); - im = (im - repmat(m,size(im))).*win + bg; - end - function CreateSprites(root, files, sprite_index) - %cgopen(1,32,0,0); - res = st.resolution(1); - tPix = st.resolution(1).*st.resolution(2); - % - for nStim = 1:size(files) - filename = [files(nStim).name]; - cgmakesprite(sprite_index(nStim),res,res,st.bg); - im = imread([root filename]); - stim(:,:,sprite_index(nStim)) = rgb2gray(double(imread([st.path2stim files(nStim).name]))./255);%save it for pink noise generation - cgloadarray(sprite_index(nStim),res,res,reshape(double(imrotate(im,90))./255,[tPix 3]),res,res); - end - cgflip([st.bg]); - cgflip([st.bg]); - %create the window - st.win = tukeywin(st.resolution(1),st.tukey)*tukeywin(st.resolution(2),st.tukey)'; - - end - function SetParams - %st: for stimulus information to be passed to other functions - %p: important information to be saved at the end of the experiment. - path2experiment = 'C:\Users\onat\Documents\Experiments\DiscriminationExperiment\'; - stimfolder = 'Circle11_08Face_Frontal_SkinModerated_Transparent_Normalized'; - st.path2stim = ['C:\Users\onat\Documents\Experiments\Stimuli\Gradients\' stimfolder '\']; - %get paths of stim files - st.files = dir([st.path2stim '*.bmp']); - st.tStim = length(st.files); - % - %name of the file to be written. - savefilename = [path2experiment '\data\' datestr(now,30) '_' stimfolder '_' name]; - st.tukey = 0.1; - dummy_im = imread([st.path2stim st.files(1).name]); - st.resolution = [size(dummy_im,1) size(dummy_im,2)]; - %durations in millisecond - p.duration.pn_prestim = 1500; - p.duration.isi = 1000; - p.duration.stim = 750; - % - st.bg = repmat(double(dummy_im(1))./255,1,3); - %Presentation randomization - p.presentation.repetition = repetition; - Pairs = find(tril(ones(st.tStim)));%all possible pairs - tPairs = length(Pairs);%total number of pairs - % - %replicate as required by REPETITION - ri = [];%random indices. - for nRep = 1:p.presentation.repetition; - %shuffle pairs, that is stimulus order. - ri = [ri randperm(tPairs)]; - end - p.presentation.order = Pairs(ri); - %add the familiarization trials - %load the familiarization faces. - % - testfolder = 'Circle09_FaceFrontal_4IDnogender'; - st.fam_path2stim = ['C:\Users\onat\Documents\Experiments\Stimuli\Gradients\' testfolder '\']; - - st.fam_files = dir([st.fam_path2stim '*.bmp']); - st.fam_tStim = size(st.fam_files,1); - - %make 3 additional sprites for the pink noise images - cgmakesprite(17:20,st.resolution(1),st.resolution(1),st.bg); - cgsetsprite(0); - end - function ConfigCogent - % - fs = 1; - res = 0; - config_display( fs, res, st.bg, [1 1 1], 'Arial', 40, 20,0 ); - config_keyboard(1, 5,'exclusive' ); - start_cogent; - cgfont('Arial',20) - cgpencol([1 1 1]) - cgflip(st.bg); - cgflip(st.bg); - end -end \ No newline at end of file diff --git a/exp_FearAmy.m b/exp_FearAmy.m deleted file mode 100644 index 5524902..0000000 --- a/exp_FearAmy.m +++ /dev/null @@ -1,1238 +0,0 @@ -function [p]=exp_FearAmy(subject,phase,csp,PainThreshold) -%[p]=FearGen_eyelab(subject,phase,csp,PainThreshold) -% -%Used for fearamy project, based on the FearGen_eyelab code. It increments -%it by adding scanner pulse communications. -% -% - -debug = 0;%debug mode -%replace parallel port function with a dummy function -if ismac -% outp = @(x,y) fprintf('[%i %i]\n',x,y); -end -if nargin ~= 4 - fprintf('Wrong number of inputs\n'); - keyboard; -end - -csn = mod( csp + 8/2-1, 8)+1; -commandwindow; -%clear everything -clear mex global functions -if ~ismac - cgshut; - global cogent; -end -%%%%%%%%%%%load the GETSECS mex files so call them at least once -GetSecs; -WaitSecs(0.001); -% -el = []; -p = []; -SetParams; -SetPTB; -% -%init all the variables -t = []; -nTrial = 0; -%% -%Time Storage -TimeEndStim = []; -TimeStartShock = []; -TimeTrackerOff = []; -TimeCrossOn = []; -p.var.event_count = 0; -%% -InitEyeLink; -WaitSecs(2); -KbQueueStop(p.ptb.device); -KbQueueRelease(p.ptb.device); -%save again the parameter file -save(p.path.path_param,'p'); -if phase == 0 - % - p.mrt.dummy_scan = 0;%for the training we don't want any pulses - p.var.ExpPhase = phase; - %UCS check - ShowInstruction(4,1); - ConfirmIntensity; - %test - ShowInstruction(1,1); - ShowInstruction(2,1); - PresentStimuli; - -elseif phase == 1 - % - CalibrateEL; - p.var.ExpPhase = phase;%set this after the calibration; - ShowInstruction(299,0,5); - %% Vormessung - k = 0; - while ~(k == 25 | k == 86 ); - pause(0.1); - fprintf('Experimenter!! press V key when the vormessung is finished.\n'); - [~, k] = KbStrokeWait(p.ptb.device); - k = find(k); - end - fprintf('Continuing...\n'); - %% - for ninst = [3 301:306] - ShowInstruction(ninst,1); - end - PresentStimuli; - WaitSecs(2.5); - AskStimRating;%make sure that scanner doesnt stop prematurely asa the stim offset - CalibrateEL; - AskDetection; - AskDetectionSelectable; -end - -%get the eyelink file back to this computer -StopEyelink(p.path.edf); -%trim the log file and save -p.out.log = p.out.log(sum(isnan(p.out.log),2) ~= size(p.out.log,2),:); -%shift the time so that the first timestamp is equal to zero -p.out.log(:,1) = p.out.log(:,1) - p.out.log(1); -p.out.log = p.out.log;%copy it to the output variable. -save(p.path.path_param,'p'); -% -%move the file to its final location. -movefile(p.path.subject,p.path.finalsubject); -%close everything down -try - addpath('/USER/onat/Code/globalfunctions/ssh2_v2_m1_r6/ssh2_v2_m1_r6/') - p.path.tarname = [p.path.finalsubject(1:end-1) '.tar']; - tar(p.path.tarname,p.path.finalsubject); - [a b c] = fileparts( p.path.tarname); - cd(a) - scp_simple_put('sanportal','onat','',[b c]); - fprintf('Copying to neuronass succesfull...\n'); -catch - fprintf('Copying to neuronass failed...\n'); -end -cleanup; - - function AskDetectionSelectable - %asks subjects to select the face that was associated with a shocks - positions = circshift(1:8,[1 PsychRandSample(1:8,[1 1])]);%position of the marker - p.var.ExpPhase = 4; - ShowInstruction(8,1); - %% - increment([p.keys.increase p.keys.decrease]) = [1 -1];%key to increment mapping - %% - ok = 1; - while ok - DrawCircle; - Screen('FrameOval', p.ptb.w, [1 1 0], p.stim.circle_rect(positions(1),:), 2);%draw the marker circle somewhere random initially. - Screen('Flip',p.ptb.w); - [~, keyCode, ~] = KbStrokeWait(p.ptb.device);%observe key presses - keyCode = find(keyCode); - if length(keyCode) == 1%this loop avoids crashes to accidential presses of meta keys - if (keyCode == p.keys.increase) || (keyCode == p.keys.decrease) - positions = circshift(positions,[0 increment(keyCode)]); - elseif keyCode == p.keys.confirm - WaitSecs(0.1); - ok = 0; - end - end - end - %% - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.imrect ); - Screen('Flip',p.ptb.w); - ShowInstruction(14,0,10); - p.out.selectedface = p.stim.circle_order(positions(1)); - end - function DrawCircle - for npos = 1:p.stim.tFace - Screen('DrawTexture', p.ptb.w, p.ptb.stim_sprites_cut(p.stim.circle_file_id(npos)),[],p.stim.circle_rect(npos,:)); - %Screen('DrawText', p.ptb.w, sprintf('%i_%i_%i',p.stim.circle_order(npos),p.stim.circle_file_id(npos),npos),mean(p.stim.circle_rect(npos,[1 3])) ,mean(p.stim.circle_rect(npos,[2 4]))); - end - end - - function [myrect]=angle2rect(A) - factor = 1.9;%factor resize the images - [x y] = pol2cart(A./180*pi,280);%randomly shift the circle - left = x+p.ptb.midpoint(1)-p.stim.width/2/factor; - top = y+p.ptb.midpoint(2)-p.stim.height/2/factor; - right = left+p.stim.width/factor; - bottom = top+p.stim.height/factor; - myrect = [left top right bottom]; - end - - function AskDetection - % - p.var.ExpPhase = 3; - ShowInstruction(801,1); - %% show a fixation cross - fix = [p.ptb.CrossPosition_x p.ptb.CrossPosition_y(1)];%show the fixation cross at the lip position to ease the subsequent drift correction. - FixCross = [fix(1)-1,fix(2)-p.ptb.fc_size,fix(1)+1,fix(2)+p.ptb.fc_size;fix(1)-p.ptb.fc_size,fix(2)-1,fix(1)+p.ptb.fc_size,fix(2)+1]; - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.imrect ); %always create a gray background - Screen('FillRect', p.ptb.w, [255,255,255], FixCross');%draw the prestimus cross atop - - Screen('DrawingFinished',p.ptb.w,0); - Screen('Flip',p.ptb.w); - StartEyelinkRecording(1,0,p.var.ExpPhase,0,0,0,fix,0); - WaitSecs(1.5); - %% - DrawCircle; - %Stimulus onset - Screen('Flip',p.ptb.w); - Eyelink('Message', 'Stim Onset'); - Eyelink('Message', 'SYNCTIME'); - %% - WaitSecs(30); - Screen('Flip',p.ptb.w); - Eyelink('Message', 'Stim Offset'); - Eyelink('Message', 'BLANK_SCREEN'); - StopEyelinkRecording; - end - - function ConfirmIntensity - %Compute the intensity we want to deliver to the subject. - p.var.ShockIntensity = p.out.PainThreshold*p.out.ShockFactor; - % - ShowInstruction(9,1); - % - fprintf([repmat('=',1,50) '\n']); - fprintf('TEST SHOCK:\n'); - fprintf('!!! ADJUST THE SHOCK INTENSITY ON THE DIGITIMER !!!\n'); - fprintf(' The intensity is now: %g mA\n',p.var.ShockIntensity); - fprintf(' Experimenter: Press any key to deliver a shock.\n'); - fprintf([repmat('=',1,50) '\n']); - % - [secs, keyCode, deltaSecs] = KbStrokeWait(p.ptb.device); - ShowInstruction(10,0,1+rand(1));%shock is coming message... - t = GetSecs + p.duration.shock; - while GetSecs < t; - Buzz; - end - % - message = 'Bewege den "Zeiger" mit der rechten und linken Pfeiltaste\n und bestätige deine Einschätzung mit der mit der oberen Pfeiltaste.'; - rect = [p.ptb.width*0.2 p.ptb.midpoint(2) p.ptb.width*0.6 100]; - response = RatingSlider(rect,2,1,p.keys.increase,p.keys.decrease,p.keys.confirm,{ 'nicht\nerträglich' 'erträglich'},message,0); - if response == 2 - fprintf('All is fine :)\n'); - fprintf('Subject confirmed the shock intensity inside the scanner...\n'); - fprintf('INTENSITY TO BE USED FOR THE MAIN EXPERIMENT: %g mA\n',p.var.ShockIntensity); - p.out.ShockIntensity = p.var.ShockIntensity; - return; - elseif response == 1 - fprintf('Shit... :(, %g is too much for the subject\n',p.var.ShockIntensity); - fprintf('We will try a little milder intensity.\n'); - p.out.ShockFactor = p.out.ShockFactor - 0.05; - ConfirmIntensity; - end - - - end - function PresentStimuli - %Enter the presentation loop and wait for the first pulse to - %arrive. - %wait for the dummy scans - [secs] = WaitPulse(p.keys.pulse,p.mrt.dummy_scan);%will log it - KbQueueStop(p.ptb.device); - WaitSecs(.05); - KbQueueCreate(p.ptb.device); - KbQueueStart(p.ptb.device);%this means that from now on we are going to log pulses. - %If the scanner by mistake had been started prior to this point - %those pulses would have been not logged. - %log the pulse timings. - mblock_jumps = logical([1 diff(p.presentation.mblock)]); - TimeEndStim = secs(end)- p.ptb.slack;%take the first valid pulse as the end of the last stimulus. - for nTrial = 1:p.presentation.tTrial; - - %Get the variables that Trial function needs. - stim_id = p.presentation.stim_id(nTrial); - fix_y = p.presentation.CrossPosition(nTrial); - ISI = p.presentation.isi(nTrial); - ucs = p.presentation.ucs(nTrial); - oddball = p.presentation.oddball(nTrial); - prestimdur = p.duration.prestim+rand(1)*.25; - dist = p.presentation.dist(nTrial); - mblock_jump = mblock_jumps(nTrial); - block_id = p.presentation.mblock(nTrial); - %prestimdur = p_presentation_prestim_dur(nTrial); - % - OnsetTime = TimeEndStim + ISI-p.duration.stim - p.ptb.slack; - fprintf('%d of %d, S: %d, ISI: %d, UCS: %d, ODD: %d, OnsetTime: %05.8gs, ',nTrial,p.presentation.tTrial,stim_id,ISI,ucs,oddball, OnsetTime); - - %Start with the trial, here is time-wise sensitive must be - %optimal - [TimeEndStim] = Trial(nTrial,OnsetTime, prestimdur, stim_id , ucs , fix_y, oddball,dist,mblock_jump,block_id); - %(nTrial,TimeStimOnset , prestimdur, stim_id , ucs , fix_i, oddball, dist ) - fprintf('OffsetTime: %05.8gs, Difference of %05.8gs\n',TimeEndStim,TimeEndStim-OnsetTime-p.duration.stim); - % - %dump it - [keycode, secs] = KbQueueDump;%this contains both the pulses and keypresses. - %log everything but "pulse keys" as pulses, not as keypresses. - pulses = (keycode == p.keys.pulse); - if any(~pulses);%log keys presses if only there is one - Log(secs(~pulses),7,keycode(~pulses)); - end - if any(pulses);%log pulses if only there is one - Log(secs(pulses),0,keycode(pulses)); - end - %now we have to detect if the subject has pressed the CONFIRM - %key while the ODDBALL stimulus was on the screen. - if any((keycode == p.keys.confirm) & (secs > OnsetTime) & (secs <= TimeEndStim)) - p.out.response(nTrial) = 1; - fprintf('Subject Pressed the Hit Key!!\n'); - end - end - %wait 6 seconds for the BOLD signal to come back to the baseline... - KbQueueStop(p.ptb.device); - KbQueueRelease(p.ptb.device); - - if p.var.ExpPhase > 0 - WaitPulse(p.keys.pulse,p.mrt.dummy_scan);% - fprintf('OK!! Stop the Scanner\n'); - end - %dump the final events - [keycode, secs] = KbQueueDump;%this contains both the pulses and keypresses. - %log everything but "pulse keys" as pulses, not as keypresses. - pulses = (keycode == p.keys.pulse); - if any(~pulses);%log keys presses if only there is one - Log(secs(~pulses),7,keycode(~pulses)); - end - if any(pulses);%log pulses if only there is one - Log(secs(pulses),0,keycode(pulses)); - end - %stop the queue - KbQueueStop(p.ptb.device); - KbQueueRelease(p.ptb.device); - WaitSecs(10); - end - function [TimeEndStim]=Trial(nTrial,TimeStimOnset , prestimdur, stim_id , ucs , fix_i, oddball, dist,microblock_jump,mblock_id) - %get all the times - TimeCrossOnset = TimeStimOnset - prestimdur; - TimeCrossJump = TimeStimOnset + p.duration.stim/2; - TimeEndStim = TimeStimOnset + p.duration.stim- p.ptb.slack; - TimeStartShock = TimeStimOnset + p.duration.onset2shock; - TimeTrackerOff = TimeStimOnset + p.duration.keep_recording; - - %% Fixation Onset - fix = [p.ptb.CrossPosition_x p.ptb.CrossPosition_y(fix_i)]; - FixCross = [fix(1)-1,fix(2)-p.ptb.fc_size,fix(1)+1,fix(2)+p.ptb.fc_size;fix(1)-p.ptb.fc_size,fix(2)-1,fix(1)+p.ptb.fc_size,fix(2)+1]; - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.imrect ); %always create a gray background - Screen('FillRect', p.ptb.w, [255,255,255], FixCross');%draw the prestimus cross atop - - Screen('DrawingFinished',p.ptb.w,0); - TimeCrossOn = Screen('Flip',p.ptb.w,TimeCrossOnset,0); - Log(TimeCrossOn,1,fix_i);%cross onset. - %turn the eye tracker on - StartEyelinkRecording(nTrial,stim_id,n,dist,oddball,ucs,fix,mblock_id);%I would be cautious here, the first trial is never recorded in the EDF file, reason yet unknown. - %% Draw the stimulus to the buffer - if ~stim_id==0 - Screen('DrawTexture', p.ptb.w, p.ptb.stim_sprites(stim_id)); - end - %draw also the fixation cross - Screen('FillRect', p.ptb.w, [255,255,255], FixCross'); - Screen('DrawingFinished',p.ptb.w,0); - %% STIMULUS ONSET - TimeStimOnset = Screen('Flip',p.ptb.w,TimeStimOnset,0);%asap and dont clear - %send eyelink and ced a marker asap - Eyelink('Message', 'Stim Onset'); - Eyelink('Message', 'SYNCTIME'); - MarkCED( p.com.lpt.address, p.com.lpt.StimOnset );%this actually didn't really work nicely. - %the first stim onset pulse is always missing. This could be due to - %the fact that the state of the port was already 1 and thus CED - %didn't realize this command. - if oddball - MarkCED( p.com.lpt.address, p.com.lpt.oddball ); - end - if ucs - MarkCED(p.com.lpt.address, p.com.lpt.ucs); - end - if microblock_jump - MarkCED( p.com.lpt.address, p.com.lpt.mBlock ); - Log(TimeStimOnset,9,mblock_id) - end - Log(TimeStimOnset,3,dist);%log the stimulus onset - - %% CROSS JUMPS (same as before but with a different fix position) - if ~stim_id==0 - Screen('DrawTexture', p.ptb.w, p.ptb.stim_sprites(stim_id)); - end - fix = [p.ptb.CrossPosition_x p.ptb.CrossPosition_y(setdiff(1:2,fix_i))];%take the other position - %draw also the fixation cross - FixCross = [fix(1)-1,fix(2)-p.ptb.fc_size,fix(1)+1,fix(2)+p.ptb.fc_size;fix(1)-p.ptb.fc_size,fix(2)-1,fix(1)+p.ptb.fc_size,fix(2)+1]; - Screen('FillRect', p.ptb.w, [255,255,255], FixCross'); - Screen('DrawingFinished',p.ptb.w,0); - TimeCrossJump = Screen('Flip',p.ptb.w,TimeCrossJump,0);%asap and dont clear - Log(TimeCrossJump,4,0);%log the stimulus onset - %% - if ucs == 1 - %%%%%%%%%%%%%%%%%%%%%%% - %Deliver shock and stim off immediately - TimeStartShock = WaitSecs('UntilTime',TimeStartShock); - Eyelink('Message', 'UCS Onset'); - - while GetSecs < TimeEndStim; - Buzz;%this is anyway sent to CED. - end - end - - %% STIM OFF immediately - TimeEndStim = Screen('Flip',p.ptb.w,TimeEndStim,0); - %send eyelink and ced a marker - Log(TimeEndStim,6,stim_id);%log the stimulus offset - % - %% record some more eye data after stimulus offset. - WaitSecs('UntilTime',TimeTrackerOff); - Eyelink('Message', 'Stim Offset'); - Eyelink('Message', 'BLANK_SCREEN'); - TimeTrackerOff = StopEyelinkRecording; - - - if oddball == 1 - fprintf('This was an oddball trial!\n'); - end - if ucs == 1 - fprintf('This was a UCS trial!\n'); - Log(TimeStartShock,5,NaN);%UCS delivery...This is done here to not waste time there - end - - end - - function SetParams - %mrt business - p.mrt.dummy_scan = 7;%this will wait until the 6th image is acquired. - p.mrt.LastScans = 5;%number of scans after the offset of the last stimulus - p.mrt.tr = 1;%in seconds. - %will count the number of events to be logged - p.var.event_count = 0; - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %% relative path to stim and experiments - %Path Business. - [~, hostname] = system('hostname'); - p.hostname = deblank(hostname); - if strcmp(p.hostname,'triostim1') - p.path.baselocation = 'C:\USER\onat\Experiments\fearamy'; - elseif strcmp(p.hostname,'etpc') - p.path.baselocation = 'C:\Users\onat\Documents\Experiments\'; - elseif ismac - p.path.baselocation = '/Users/onat/Desktop/fearamy'; - end - - p.path.experiment = [p.path.baselocation filesep]; - p.path.stim = [p.path.baselocation filesep 'stimuli' filesep]; - p.path.stim24 = [p.path.stim '24bit' filesep]; - p.path.stim_cut = [p.path.stim 'cut' filesep]; - % - p.subID = sprintf('s%02d',subject); - timestamp = datestr(now,30); - p.path.subject = [p.path.experiment 'tmp' filesep p.subID '_' timestamp filesep ]; - p.path.finalsubject = [p.path.experiment p.subID '_' timestamp filesep ]; - p.path.path_edf = [p.path.subject 'eye' filesep]; - p.path.edf = sprintf([p.subID 'p%02d.edf' ],phase); - p.path.path_param = [p.path.subject 'stimulation' filesep 'data.mat']; - %create folder hierarchy - mkdir(p.path.subject); - mkdir([p.path.subject 'scr']); - mkdir([p.path.subject 'eye']); - mkdir([p.path.subject 'stimulation']); - mkdir([p.path.subject 'midlevel']); - %% %%%%%%%%%%%%%%%%%%%%%%%%% - %get stim files - [p.stim.files p.stim.label] = FileMatrix([p.path.stim '*.bmp']); - [p.stim.files_cut p.stim.label] = FileMatrix([p.path.stim_cut '*.bmp']); - p.stim.tFile = size(p.stim.files,1);%number of different files (including the UCS symbol) - p.stim.tFace = 8;%number of faces. - % - display([mat2str(p.stim.tFile) ' found in the destination.']); - %set the background gray according to the background of the stimuli - for i = 1:p.stim.tFace; - im = imread(p.stim.files(i,:)); - bg(i) = im(1,1,1); - end - %is all the captured bg values the same? - if sum(diff(bg))==0; - %if so take it as the bg color - p.stim.bg = double([bg(1) bg(1) bg(1)]); - else - fprintf('background luminance was not successfully detected...\n') - keyboard; - end - %bg of the rating screen. - p.stim.bg_rating = p.stim.bg; - p.stim.white = [255 255 255]; - %% font size and background gray level - p.text.fontname = 'Times New Roman'; - p.text.fontsize = 18;%30; - p.text.fixsize = 60; - %rating business - p.rating.division = 10;%number of divisions for the rating slider - p.rating.repetition = 2;%how many times a given face has to be repeated... - %% get the actual stim size (assumes all the same) - info = imfinfo(p.stim.files(1,:)); - p.stim.width = info.Width; - p.stim.height = info.Height; - %% keys to be used during the experiment - %1, 6 ==> Right - %2, 7 ==> Left - %3, 8 ==> Down - %4, 9 ==> Up (confirm) - %5 ==> Pulse from the scanner - p.keys.confirm = KbName('4$'); - p.keys.increase = KbName('1!'); - p.keys.decrease = KbName('3#'); - p.keys.pulse = KbName('5%'); - p.keys.el_calib = KbName('v'); - p.keys.el_valid = KbName('c'); - if ismac - p.keys.escape = KbName('escape'); - else - p.keys.escape = KbName('esc'); - end - p.keys.enter = KbName('return'); - - %% %%%%%%%%%%%%%%%%%%%%%%%%% - %Communication business - %parallel port - p.com.lpt.address = 888; - %codes for different events - p.com.lpt.digitimer = 12;%8 - p.com.lpt.mBlock = 128; - p.com.lpt.StimOnset = 64; - p.com.lpt.oddball = 32; - p.com.lpt.ucs = 16; - - % - %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %timing business - %these are the intervals of importance - %time2fixationcross->cross2onset->onset2shock->shock2offset - %these (duration.BLA) are average duration values: - p.duration.stim = 1.5;%2;%s - p.duration.shock = 0.1;%s;x - p.duration.shockpulse = 0.005;%ms; duration of each individual pulses - p.duration.intershockpulse = 0.01;%ms; and the time between each pulse - p.duration.onset2shock = p.duration.stim - p.duration.shock; - p.duration.crossmoves = p.duration.stim./2; - p.duration.keep_recording = 0.25;%this is the time we will keep recording (eye data) after stim offset. - p.duration.prestim = .85; - %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %stimulus sequence - if phase == 0 - seq(subject,csp).cond_id = Shuffle([0 1 2 3 4 5 6 7 8 10]); - seq(subject,csp).tTrial = length(seq(subject,csp).cond_id); - seq(subject,csp).ucs = zeros(1,seq(subject,csp).tTrial); - seq(subject,csp).oddball = seq(subject,csp).cond_id == 10; - seq(subject,csp).isi = PsychRandSample([3 4.5],[1 seq(subject,csp).tTrial]); - seq(subject,csp).stim_id = seq(subject,csp).cond_id; - seq(subject,csp).stim_id(seq(subject,csp).cond_id == 10) = 9; - seq(subject,csp).dist = 1:10; - seq(subject,csp).CrossPosition = ones(1,seq(subject,csp).tTrial); - seq(subject,csp).mblock = ones(1,seq(subject,csp).tTrial); - elseif phase == 1 - load([fileparts(which('exp_FearAmy.m')) '/bin/fearamy_seq.mat']); - end - %this will deal all the presentation sequence related information - p.presentation = seq(subject,csp); - clear seq - %% create the randomized design - p.stim.cs_plus = csp;%index of cs stimulus, this is the one paired to shock - p.stim.cs_neg = csn; - %Record which Phase are we going to run in this run. - p.stim.phase = phase; - - - p.out.rating = []; - p.out.log = zeros(1000000,4).*NaN; - p.out.response = zeros(p.presentation.tTrial,1); - p.out.ShockFactor = 2; - %% - p.out.PainThreshold = PainThreshold; - p.var.current_bg = p.stim.bg;%current background to be used. - %Save the stuff - save(p.path.path_param,'p'); - % - function [FM labels] = FileMatrix(path) - %Takes a path with file extension associated to regexp (e.g. - %C:\blabl\bla\*.bmp) returns the file matrix - dummy = dir(path); - FM = [repmat([fileparts(path) filesep],length(dummy),1) vertcat(dummy(:).name)]; - labels = {dummy(:).name}; - end - end - function AskStimRating - - - p.var.ExpPhase = 5; - p.var.current_bg = p.stim.bg_rating; - %% create the order of presentation and balance the position of fixation cross - nseq = 0; - rating_seq = []; - pos1_seq = []; - idx = []; - face_order = 1:p.stim.tFace; - while nseq < p.rating.repetition - nseq = nseq + 1; - [dummy idx] = Shuffle( face_order ); - rating_seq = [rating_seq dummy]; - %this balances both directions - pos1_seq = [pos1_seq ones(1,p.stim.tFace)];%+1 to make [0 1] --> [1 2] - end - rating_seq = rating_seq(:); - pos1_seq = pos1_seq(:); - %% - message = GetText(11); - SliderTextL = GetText(13); - SliderTextR = GetText(12); - % set the background to different color - Screen('FillRect', p.ptb.w , p.var.current_bg ); - Screen('Flip',p.ptb.w); - WaitSecs(2); - % - ShowInstruction(7,1); - rect = [p.ptb.width*0.2 p.ptb.midpoint(2) p.ptb.width*0.6 100];%for the rating slider - tRatend = length(rating_seq); - %save the rating sequence just for security - p.out.rating_seq = rating_seq; - p.out.pos1_seq = pos1_seq; - - %run over all the pictures to be rated. - for nRatend = 1:tRatend; - % - %the variable that are used by Trial function - stim_id = rating_seq(nRatend); - fix_y = pos1_seq(nRatend); - % - next_stim_id = [];%this is a trick, otherwise a fixation cross appears right before the rating :( - next_pos1 = []; - % - %to send know the distance here, little dummy setup: - dummy = -135:45:180; - dist = dummy(stim_id); - % show the picture - %Trial(nTrial ,TimeStimOnset , prestimdur, stim_id , ucs , fix_i, oddball, dist,microblock_jump,mblock_id) - Trial(1000+nRatend,GetSecs+1,p.duration.prestim,stim_id,0,fix_y,0,dist,0,0); - % show the slider - rate(nRatend,1) = RatingSlider(rect, p.rating.division, Shuffle(1:p.rating.division,1), p.keys.increase, p.keys.decrease, p.keys.confirm, {SliderTextL{1} SliderTextR{1}},message,1); - - %%%%%%%%%%%%%%%%%%%%%%%%%%%% - %Verbose the rating of the subject - fprintf('============\nRating Results %d (%d/%d):\n', stim_id, nRatend, tRatend); - dummy = rating_seq(1:nRatend);%trials shown so far - for iii = 1:p.stim.tFace - r = round(mean(rate(dummy == iii))); - if isnan(r) - r = 0; - end - if iii == p.stim.cs_plus - fprintf('Stimulus %02d: * %s \n',iii,repmat('+',1,1+r)); - else - fprintf('Stimulus %02d: %s \n',iii,repmat('+',1,1+r)); - end - end - end - %sort the stim_ids and then sort the same the rates and make a - %matrix out of that to store - [~, i] = sort(rating_seq); - rate = reshape(rate(i),p.rating.repetition,p.stim.tFace)'; - p.out.rating = rate; - save(p.path.path_param,'p'); - Screen('FillRect',p.ptb.w,p.var.current_bg); - % - save(p.path.path_param,'p'); - end - function [rating] = RatingSlider(rect,tSection,position,up,down,confirm,labels,message,numbersOn) - % - %Detect the bounding boxes of the labels. - for nlab = 1:2 - [~ , ~, bb(nlab,:)]=DrawFormattedText(p.ptb.w,labels{nlab}, 'center', 'center', p.stim.white,[],[],[],2); - Screen('FillRect',p.ptb.w,p.var.current_bg); - end - bb = max(bb); - bb_size = bb(3)-bb(1);%vertical size of the bb. - % - DrawSkala; - ok = 1; - while ok == 1 - [secs, keyCode, ~] = KbStrokeWait(p.ptb.device); - keyCode = find(keyCode); - Log(secs,7,keyCode); - if length(keyCode) == 1%this loop avoids crashes to accidential presses of meta keys - if (keyCode == up) || (keyCode == down) - next = position + increment(keyCode); - if next < (tSection+1) && next > 0 - position = position + increment(keyCode); - end - DrawSkala; - elseif keyCode == confirm - WaitSecs(0.1); - ok = 0; - Screen('FillRect',p.ptb.w,p.var.current_bg); - t=Screen('Flip',p.ptb.w); - end - end - end - - function DrawSkala - %rating = tSection - position + 1; - rating = position ; - increment([up down]) = [1 -1];%delta - tick_x = linspace(rect(1),rect(1)+rect(3),tSection+1);%tick positions - tick_size = rect(3)./tSection; - ss = tick_size/5*0.9;%slider size. - % - for tick = 1:length(tick_x)%draw ticks - Screen('DrawLine', p.ptb.w, [255 0 0], tick_x(tick), rect(2), tick_x(tick), rect(2)+rect(4) , 3); - if tick <= tSection && numbersOn - Screen('TextSize', p.ptb.w,p.text.fontsize); - DrawFormattedText(p.ptb.w, mat2str(tick) , tick_x(tick)+ss/2, rect(2)+rect(4), p.stim.white); - Screen('TextSize', p.ptb.w,p.text.fontsize); - end - if tick == 1 - DrawFormattedText(p.ptb.w, labels{1},tick_x(tick)-bb_size*1.4,rect(2), p.stim.white); - elseif tick == tSection+1 - DrawFormattedText(p.ptb.w, labels{2},tick_x(tick)+bb_size*0.4,rect(2), p.stim.white); - end - end - %slider coordinates - slider = [ tick_x(position)+tick_size*0.1 rect(2) tick_x(position)+tick_size*0.9 rect(2)+rect(4)]; - %draw the slider - Screen('FillRect',p.ptb.w, p.stim.white, round(slider)); - Screen('TextSize', p.ptb.w,p.text.fontsize); - DrawFormattedText(p.ptb.w,message, 'center', p.ptb.midpoint(2)*0.2, p.stim.white,[],[],[],2); - Screen('TextSize', p.ptb.w,p.text.fontsize); - t = Screen('Flip',p.ptb.w); - Log(t,-2,NaN); - end - end - function ShowInstruction(nInstruct,waitforkeypress,varargin) - %ShowInstruction(nInstruct,waitforkeypress) - %if waitforkeypress is 1, ==> subject presses a button to proceed - %if waitforkeypress is 0, ==> text is shown for VARARGIN seconds. - - - [text]= GetText(nInstruct); - ShowText(text); - if waitforkeypress %and blank the screen as soon as the key is pressed - KbStrokeWait(p.ptb.device); - else - WaitSecs(varargin{1}); - end - Screen('FillRect',p.ptb.w,p.var.current_bg); - t = Screen('Flip',p.ptb.w); - - function ShowText(text) - - Screen('FillRect',p.ptb.w,p.var.current_bg); - DrawFormattedText(p.ptb.w, text, 'center', 'center',p.stim.white,[],[],[],2,[]); - t=Screen('Flip',p.ptb.w); - Log(t,-1,nInstruct); - %show the messages at the experimenter screen - fprintf('=========================================================\n'); - fprintf('Text shown to the subject:\n'); - fprintf(text); - fprintf('=========================================================\n'); - - end - end - function [text]=GetText(nInstruct) - if nInstruct == 0%Eyetracking calibration - - text = ['Wir kalibrieren jetzt den Eye-Tracker.\n\n' ... - 'Bitte fixieren Sie die nun folgenden weißen Kreise und \n' ... - 'bleiben so lange darauf, wie sie zu sehen sind.\n\n' ... - 'Nach der Kalibrierung dürfen Sie Ihren Kopf nicht mehr bewegen.\n'... - 'Sollten Sie Ihre Position noch verändern müssen, tun Sie dies jetzt.\n'... - 'Die beste Position ist meist die bequemste.\n\n'... - 'Bitte drücken Sie jetzt den oberen Knopf, \n' ... - 'um mit der Kalibrierung weiterzumachen.\n' ... - ]; - - elseif nInstruct == 1%first Instr. of the training phase. - text = ['Wir werden nun als erstes einen Übungsdurchgang machen,\n' ... - 'damit Sie sich an Ihre Aufgabe gewöhnen können.\n' ... - 'In diesem Durchgang können Sie sich vollkommen sicher fühlen,\n' ... - 'es werden keine elektrischen Reize verabreicht.\n' ... - 'Eine wichtige grundsätzliche Regel ist, dass Sie das Fixationskreuz (das „+“)\n' ... - 'wenn es zu sehen ist, mit Ihren Augen fixieren. \n' ... - '\n'... - 'Drücken Sie die obere Taste um fortzufahren.\n' ... - ]; - elseif nInstruct == 2%second Instr. of the training phase. - text = ['Ein paar Bemerkungen zu den Zielreizen: \n' ... - 'Zur Erinnerung: Zielreize sind die verschwommenen Gesichter.\n' ... - 'Sobald ein solcher Zielreiz erscheint, \n' ... - 'sollen Sie schnellstmöglich die obere Taste drücken, \n' ... - 'und zwar bevor der Zielreiz wieder verschwunden ist \n' ... - '(Sie müssen also sehr schnell und aufmerksam sein).\n\n' ... - 'Drücken Sie die obere Taste um fortzufahren.\n' ... - ]; - elseif nInstruct == 299%short instruction before localizer - text = ['Die Kalibrierung war erfolgreich.\n'... - 'Es startet nun eine kurze Vormessung (~2 min), während der Sie nichts tun müssen.\n\n'... - ]; - elseif nInstruct == 3%third Instr. of the training phase. - text = ['Wir sind jetzt kurz vor Beginn des Experiments.\n'... - 'Wir möchten Sie nun noch einmal an die wichtigsten Punkte erinnern.\n\n'... - 'Drücken Sie jeweils die obere Taste um fortzufahren.\n' ... - ]; - elseif nInstruct == 301%third Instr. of the training phase. - text = ['1/ Folgen Sie immer streng den Fixationskreuzen.\n'... - ]; - elseif nInstruct == 302%third Instr. of the training phase. - text = ['2/ Drücken Sie die Taste, sobald Sie den Zielreiz entdecken.\n'... - ]; - elseif nInstruct == 303%third Instr. of the training phase. - text = ['3/ Bewegen Sie sich nicht.\n'... - ]; - elseif nInstruct == 304%third Instr. of the training phase. - text = ['4/ Lassen Sie sich vom Scannergeschehen nicht stören.\n'... - ]; - elseif nInstruct == 305%third Instr. of the training phase. - text = ['5/ Nur eines der Gesichter wird mit elektrischen Reizen gepaart.\n'... - ]; - elseif nInstruct == 306%third Instr. of the training phase. - text = ['Drücken Sie jetzt die obere Taste, das Experiment startet dann in wenigen Sekunden.\n' ... - ]; - - - elseif nInstruct == 4%third Instr. of the training phase. - text = ['Vor dem Experiment legen wir nun \n' ... - 'die Schockintensität für den Rest des Experiments fest. \n' ... - 'Drücken Sie die obere Taste um fortzufahren.\n' ... - ]; - - elseif nInstruct == 7;%rating - text = ['In dieser Phase hätten wir gerne, dass Sie die Gesichter\n'... - 'im Hinblick auf folgende Frage bewerten:\n'... - '„Wie wahrscheinlich ist es, bei dem gerade gesehenen Gesicht \n'... - 'einen elektrischen Schock zu erhalten?“\n'... - 'Bewegen Sie den Zeiger mit der rechten und linken Taste\n'... - 'und bestätigen Sie Ihre Einschätzung mit der oberen Taste.\n'... - ]; - elseif nInstruct == 8;%AskDetectionSelectable - text = ['Sie sehen nun noch einmal eine Übersicht der verschiedenen Gesichter.\n'... - 'Bitte geben Sie an, welches der Gesichter Ihrer Meinung nach\n mit dem Schock gepaart wurde.\n\n'... - 'Nutzen Sie die linke und rechte Taste, um die Markierung\n zum richtigen Gesicht zu navigieren,\n'... - 'und drücken Sie die obere Taste zum Bestätigen.\n\n'... - 'Bitte zum Starten die obere Taste drücken.\n'... - ]; - elseif nInstruct == 801;%AskDetectionSelectable - text = ['Sie sehen nun eine Übersicht der verschiedenen Gesichter.\n'... - 'Bitte schauen Sie sich die Gesichter aufmerksam an.\n'... - 'Bitte drücken Sie zum Start die obere Taste und\n' ... - 'fixieren Sie das anschließend erscheinende Fixationskreuz.\n'... - ]; - - elseif nInstruct == 9% - %=================================================================================================================% - text = ['Bitte geben Sie an, ob die Reizstärke des folgenden Schocks\n für Sie erträglich ist.\n'... - '\n'... - 'Drücken Sie bitte die obere Taste um den Reiz zu bekommen.\n'... - ]; - - elseif nInstruct == 10%just before the shock - text = ['Reiz kommt...\n']; - elseif nInstruct == 11%this is the rating question - text = ['Wie wahrscheinlich ist es, bei dem gerade gesehenen Gesicht \n'... - 'einen elektrischen Schock zu erhalten?“\n' ... - 'Bewegen Sie den "Zeiger" mit der rechten und linken Taste\n' ... - 'und bestätigen Sie Ihre Einschätzung mit der mit der oberen Taste'... - ]; - elseif nInstruct == 12 %These two below are the possible responses to the question in 11 - text = {'Sehr\nwahrscheinlich'}; - elseif nInstruct == 13 - text = {'Überhaupt\nnicht\nwahrscheinlich'}; - elseif nInstruct == 14 - text = ['Danke. Den aktiven Teil des Experiment haben Sie nun geschafft.\n'... - 'Es folgt nun noch eine strukturelle Messung, die ca. 7 Minuten dauert.\n'... - 'Sie können dabei ruhig die Augen schließen und sich entspannen.\n']; - else - text = {''}; - end - end - function SetPTB - %KbName('UnifyKeyNames'); - %Sets the parameters related to the PTB toolbox. Including - %fontsizes, font names. - %Default parameters - Screen('Preference', 'SkipSyncTests', 1); - Screen('Preference', 'DefaultFontSize', p.text.fontsize); - Screen('Preference', 'DefaultFontName', p.text.fontname); - Screen('Preference', 'TextAntiAliasing',2);%enable textantialiasing high quality - Screen('Preference', 'VisualDebuglevel', 0); - Screen('Preference', 'SkipSyncTests', 1); - Screen('Preference', 'SuppressAllWarnings', 1); - %%Find the number of the screen to be opened - screens = Screen('Screens'); - p.ptb.screenNumber = max(screens);%the maximum is the second monitor - %Make everything transparent for debugging purposes. - if debug - commandwindow; - PsychDebugWindowConfiguration; - end - %set the resolution correctly - res = Screen('resolution',p.ptb.screenNumber); - HideCursor(p.ptb.screenNumber); - %spit out the resolution - fprintf('Resolution of the screen is %dx%d...\n',res.width,res.height); - - %Open a graphics window using PTB - [p.ptb.w p.ptb.rect] = Screen('OpenWindow', p.ptb.screenNumber, p.var.current_bg); - %Screen('BlendFunction', p.ptb.w, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - Screen('Flip',p.ptb.w);%make the bg - p.ptb.slack = Screen('GetFlipInterval',p.ptb.w)./2; - [p.ptb.width, p.ptb.height] = Screen('WindowSize', p.ptb.screenNumber); - - %find the mid position on the screen. - p.ptb.midpoint = [ p.ptb.width./2 p.ptb.height./2]; - %NOTE about RECT: - %RectLeft=1, RectTop=2, RectRight=3, RectBottom=4. - p.ptb.imrect = [ p.ptb.midpoint(1)-p.stim.width/2 p.ptb.midpoint(2)-p.stim.height/2 p.ptb.midpoint(1)-p.stim.width/2+p.stim.width p.ptb.midpoint(2)-p.stim.height/2+p.stim.height]; - p.ptb.cross_shift = [180 -120]./2.5;%incremental upper and lower cross positions - p.ptb.CrossPosition_x = p.ptb.midpoint(1);%bb(1);%always the same - p.ptb.CrossPosition_y = p.ptb.midpoint(2)+p.ptb.cross_shift;%bb(1);%always the same - %cross position for the eyetracker screen. - p.ptb.CrossPositionET_x = [p.ptb.midpoint(1) p.ptb.midpoint(1)]; - p.ptb.CrossPositionET_y = [p.ptb.midpoint(2)-p.ptb.cross_shift(2) p.ptb.midpoint(2)+p.ptb.cross_shift(2)]; - p.ptb.fc_size = 10; - % - %% - %priorityLevel=MaxPriority(['GetSecs'],['KbCheck'],['KbWait'],['GetClicks']); - Priority(MaxPriority(p.ptb.w)); - %this is necessary for the Eyelink calibration - %InitializePsychSound(0) - %sound('Open') - % Beeper(1000) - LoadPsychHID - %%%%%%%%%%%%%%%%%%%%%%%%%%%Prepare the keypress queue listening. - p.ptb.device = []; - %get all the required keys in a vector - p.ptb.keysOfInterest = [];for i = fields(p.keys)';p.ptb.keysOfInterest = [p.ptb.keysOfInterest p.keys.(i{1})];end - fprintf('Key listening will be restricted to %d\n',p.ptb.keysOfInterest) - RestrictKeysForKbCheck(p.ptb.keysOfInterest); - - p.ptb.keysOfInterest=zeros(1,256); - p.ptb.keysOfInterest(p.keys.confirm) = 1; - %create a queue sensitive to only relevant keys. - % KbQueueCreate(p.ptb.device,p.ptb.keysOfInterest);%default device. - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %prepare parallel port communication. This relies on cogent i - %think. We could do it with PTB as well. - if ~ismac - config_io; - outp(p.com.lpt.address,0); - if( cogent.io.status ~= 0 ) - error('inp/outp installation failed'); - end - end - - %CORRECT - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %test whether CED receives the triggers correctly... - k = 0; - while ~(k == 25 | k == 86 ); - pause(0.1); - outp(p.com.lpt.address,244);%244 means all but the UCS channel (so that we dont shock the subject during initialization). - fprintf('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'); - fprintf('1/ Red cable has to be connected to the Cogent BOX\n'); - fprintf('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'); - fprintf('2/ D2 Connection not to forget on the LPT panel\n'); - fprintf('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'); - fprintf('3/ Switch the SCR cable\n'); - fprintf('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'); - fprintf('4/ Button box has to be on\n'); - fprintf('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'); - fprintf('5/ Did the trigger test work?\n!!!!!!You MUST observe 5 pulses on the PHYSIOCOMPUTER!!!!!\n\n\nPress c to send it again, v to continue...\n') - [~, k] = KbStrokeWait(p.ptb.device); - k = find(k); - end - fprintf('Continuing...\n'); - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %load the pictures to the memory. - p.ptb.stim_sprites = CreateStimSprites(p.stim.files);% - p.ptb.stim_sprites_cut = CreateStimSprites(p.stim.files_cut);% - %% take care of the circle presentation - %order of faces on the circle that will be shown at the end. - if phase ~= 0 - circle_order = Shuffle(unique(p.presentation.dist(p.presentation.dist < 500)));% - circle_order(end+1)=circle_order(1); - while any(abs(diff(circle_order)) < 50);%check that neighbors will not be neighbors in the next order. - circle_order = Shuffle(unique(p.presentation.dist(p.presentation.dist < 500))); - circle_order(end+1) = circle_order(1);%to be successful the check has to consider the circularity. - end - p.stim.circle_order = circle_order(1:end-1);%conditions in distances from CSP, 0 = CS+, randomized - p.stim.circle_angles = sort(p.stim.circle_order);%this is just angles with steps of 45 - %transform the angles to rects - for nc = 1:p.stim.tFace - p.stim.circle_rect(nc,:) = angle2rect(p.stim.circle_angles(nc)); - p.stim.circle_file_id(nc) = unique(p.presentation.stim_id(p.presentation.dist == p.stim.circle_order(nc)));%the file that corresponds to different conditions - end - %one to one mappings: - %now we have: circle_order ==> file_id - %circle_angles ==> circle_rect - end - - %% - function [out]=CreateStimSprites(files) - %loads all the stims to video memory - for nStim = 1:p.stim.tFile - filename = files(nStim,:); - [im , ~, ~] = imread(filename); - out(nStim) = Screen('MakeTexture', p.ptb.w, im ); - end - end - end - function [t]=StopEyelinkRecording - Eyelink('StopRecording'); - t = GetSecs; - %this is the end of the trial scope. - WaitSecs(0.01); - Eyelink('Message', 'TRIAL_RESULT 0'); - % - WaitSecs(0.01); - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('Command', 'clear_screen %d', 0); - Screen('Textsize', p.ptb.w,p.text.fontsize); - Log(t,8,NaN); - end - - function [t]=StartEyelinkRecording(nTrial,nStim,phase,dist,oddball,ucs,fix,block_id) - t = []; - if isnan(dist) - dist=3000; - end - nStim = double(nStim); - Eyelink('Message', 'TRIALID: %04d, PHASE: %04d, FILE: %04d, DELTACSP: %04d, ODDBALL: %04d, UCS: %04d, FIXX: %04d, FIXY %04d, MBLOCK %04d', nTrial, phase, nStim, dist, double(oddball), double(ucs),fix(1),fix(2),block_id); - Eyelink('Message', 'FX Onset at %d %d',fix(1),fix(2)); - % an integration message so that an image can be loaded as - % overlay background when performing Data Viewer analysis. - WaitSecs(0.01); - %return - if nStim~=0 - Eyelink('Message', '!V IMGLOAD CENTER %s %d %d', p.stim.files(nStim,:), p.ptb.midpoint(1), p.ptb.midpoint(2)); - end - % This supplies the title at the bottom of the eyetracker display - Eyelink('Command', 'record_status_message "Stim: %02d, Phase: %d"', nStim, phase); - % - %Put the tracker offline and draw the stimuli. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - % clear tracker display and draw box at center - Eyelink('Command', 'clear_screen %d', 0); - %draw the image on the screen but also the two crosses - if (nStim <= 16 && nStim>0) - Eyelink('ImageTransfer',p.stim.files24(nStim,:),p.ptb.imrect(1),p.ptb.imrect(2),p.stim.width,p.stim.height,p.ptb.imrect(1),p.ptb.imrect(2),0); - end - Eyelink('Command', 'draw_cross %d %d 15',fix(1),fix(2)); - Eyelink('Command', 'draw_cross %d %d 15',fix(1),fix(2)+diff(p.ptb.cross_shift)); - - % - %drift correction - %EyelinkDoDriftCorrection(el,crosspositionx,crosspositiony,0,0); - %start recording following mode transition and a short pause. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('StartRecording'); - t = GetSecs; - Log(t,2,NaN); - end - function [shuffled idx] = Shuffle(vector,N) - %takes first N from the SHUFFLED before outputting. This function - %could be used as a replacement for randsample - if nargin < 2;N = length(vector);end - [~, idx] = sort(rand([1 length(vector)])); - shuffled = vector(idx(1:N)); - shuffled = shuffled(:); - end - function Buzz - outp(p.com.lpt.address, p.com.lpt.digitimer ); - WaitSecs(p.duration.shockpulse); - outp(p.com.lpt.address, 0); - WaitSecs(p.duration.intershockpulse); - end - function MarkCED(socket,port) - %send pulse to SCR# - outp(socket,port); - WaitSecs(0.01); - outp(socket,0); - end - function InitEyeLink - % - if EyelinkInit(0)%use 0 to init normaly - fprintf('=================\nEyelink initialized correctly...\n') - else - fprintf('=================\nThere is problem in Eyelink initialization\n') - keyboard; - end - % - WaitSecs(0.5); - [~, vs] = Eyelink('GetTrackerVersion'); - fprintf('=================\nRunning experiment on a ''%s'' tracker.\n', vs ); - - %load 24bits pictures for eyelink... - dummy = dir([p.path.stim24 '*.bmp']); - p.stim.files24 = [repmat([fileparts(p.path.stim24) filesep],length(dummy),1) vertcat(dummy(:).name)]; - % - el = EyelinkInitDefaults(p.ptb.w); - %update the defaults of the eyelink tracker - el.backgroundcolour = p.stim.bg; - el.msgfontcolour = WhiteIndex(el.window); - el.imgtitlecolour = WhiteIndex(el.window); - el.targetbeep = 0; - el.calibrationtargetcolour = WhiteIndex(el.window); - el.calibrationtargetsize = 1.5; - el.calibrationtargetwidth = 0.5; - el.displayCalResults = 1; - el.eyeimgsize = 50; - el.waitformodereadytime = 25;%ms - el.msgfont = 'Times New Roman'; - el.cal_target_beep = [0 0 0];%[1250 0.6 0.05]; - %shut all sounds off - el.drift_correction_target_beep = [0 0 0]; - el.calibration_failed_beep = [0 0 0]; - el.calibration_success_beep = [0 0 0]; - el.drift_correction_failed_beep = [0 0 0]; - el.drift_correction_success_beep= [0 0 0]; - EyelinkUpdateDefaults(el); - PsychEyelinkDispatchCallback(el); - - % open file. - res = Eyelink('Openfile', p.path.edf); - % - Eyelink('command', 'add_file_preamble_text ''Recorded by EyelinkToolbox FearAmy Experiment (Selim Onat)'''); - Eyelink('command', 'screen_pixel_coords = %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - Eyelink('message', 'DISPLAY_COORDS %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - % set calibration type. - Eyelink('command','auto_calibration_messages = YES'); - Eyelink('command', 'calibration_type = HV13'); - Eyelink('command', 'select_parser_configuration = 1'); - %what do we want to record - Eyelink('command', 'file_sample_data = LEFT,RIGHT,GAZE,HREF,AREA,GAZERES,STATUS,INPUT,HTARGET'); - Eyelink('command', 'file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON,INPUT'); - Eyelink('command', 'use_ellipse_fitter = no'); - % set sample rate in camera setup screen - Eyelink('command', 'sample_rate = %d',1000); - end - function StopEyelink(filename) - try - fprintf('Trying to stop the Eyelink system with StopEyelink\n'); - Eyelink('StopRecording'); - Log(t,8,NaN); - WaitSecs(0.5); - Eyelink('Closefile'); - display('receiving the EDF file...'); - Eyelink('ReceiveFile',filename,p.path.path_edf,1); - display('...finished!') - % Shutdown Eyelink: - Eyelink('Shutdown'); - catch - display('StopEyeLink routine didn''t really run well'); - end - end - function cleanup - % Close window: - sca; - %set back the old resolution - if strcmp(p.hostname,'triostim1') - % Screen('Resolution',p.ptb.screenNumber, p.ptb.oldres.width, p.ptb.oldres.height ); - %show the cursor - ShowCursor(p.ptb.screenNumber); - end - % - commandwindow; - KbQueueStop(p.ptb.device); - KbQueueRelease(p.ptb.device); - end - function CalibrateEL - fprintf('=================\n=================\nEntering Eyelink Calibration\n') - p.var.ExpPhase = 0; - ShowInstruction(0,1); - EyelinkDoTrackerSetup(el); - %Returns 'messageString' text associated with result of last calibration - [~, messageString] = Eyelink('CalMessage'); - Eyelink('Message','%s',messageString);% - WaitSecs(0.05); - fprintf('=================\n=================\nNow we are done with the calibration\n') - end - function Log(ptb_time, event_type, event_info) - %Phases: - %Instruction : 0 - %Test : 1 - %Rating : 5 - %Calibration : 0 - % - %event types are as follows: - % - %Pulse Detection : 0 info: NaN; - %Tracker Onset : 1 - %Cross Onset : 2 info: position - %Stimulus Onset : 3 info: dist_id - %Cross Movement : 4 info: NaN; - %UCS Delivery : 5 info: NaN; - %Stimulus Offset : 6 info: NaN; - %Key Presses : 7 info: NaN; - %Tracker Offset : 8 info: NaN; - %MicroBlock : 9 info:rank - % - %Text on the screen : -1 info: Which Text? - %RatingScreen Onset : -2 info: NaN; - for iii = 1:length(ptb_time) - p.var.event_count = p.var.event_count + 1; - p.out.log(p.var.event_count,:) = [ptb_time(iii) event_type event_info(iii) p.var.ExpPhase]; - end -% plot(p.out.log(1:p.var.event_count,1) - p.out.log(1,1),p.out.log(1:p.var.event_count,2),'o','markersize',10); -% ylim([-2 8]); -% set(gca,'ytick',[-2:8],'yticklabel',{'Rating On','Text','Pulse','Tracker+','Cross+','Stim+','CrossMov','UCS','Stim-','Key+','Tracker-'}); -% grid on -% drawnow; - - end - function [secs]=WaitPulse(keycode,n) - %[secs]=WaitPulse(keycode,n) - % - % This function waits for the Nth upcoming pulse. If N=1, it will wait for - % the very next pulse to arrive. 1 MEANS NEXT PULSE. So if you wish to wait - % for 6 full dummy scans, you should use N = 7 to be sure that at least 6 - % full acquisitions are finished. - % - % The function avoids KbCheck, KbWait functions, but relies on the OS - % level event queues, which are much less likely to skip short events. A - % nice discussion on the topic can be found here: - % http://ftp.tuebingen.mpg.de/pub/pub_dahl/stmdev10_D/Matlab6/Toolboxes/Psychtoolbox/PsychDocumentation/KbQueue.html - - %KbQueueFlush;KbQueueStop;KbQueueRelease;WaitSecs(1); - fprintf('Will wait for %i dummy pulses...\n',n); - if n ~= 0 - secs = nan(1,n); - pulse = 0; - dummy = []; - while pulse < n - dummy = KbTriggerWait(keycode,p.ptb.device); - pulse = pulse + 1; - secs(pulse+1) = dummy; - Log(dummy,0,NaN); - end - else - secs = GetSecs; - end - end - function [keycode, secs] = KbQueueDump; - %[keycode, secs] = KbQueueDump - % Will dump all the events accumulated in the queue. - - keycode = []; - secs = []; - pressed = []; - %fprintf('there are %03d events\n',KbEventAvail(p.ptb.device)); - while KbEventAvail(p.ptb.device) - [evt, n] = KbEventGet(p.ptb.device); - n = n + 1; - keycode(n) = evt.Keycode; - pressed(n) = evt.Pressed; - secs(n) = evt.Time; - % fprintf('Event is: %d\n',keycode(n)); - end - i = pressed == 1; - keycode(~i) = []; - secs(~i) = []; - %fprintf('there are %03d events found...\n',length(keycode)); - end -end diff --git a/exp_FearGen.m b/exp_FearGen.m deleted file mode 100755 index f2edbf2..0000000 --- a/exp_FearGen.m +++ /dev/null @@ -1,1285 +0,0 @@ -function [p]=FearGen(subject,NthSeq,CSpface,phase,PainThreshold) -%[p]=Conditioning(subject,NthSeq,CSpface,phase,PainThreshold) -% -%IMPORTANT: -% -%Logging implies stimulus kind and not condition kind. This is important -%because there is no information what so ever wrt the oddball and ucs -%trials in the logged information :( -% -%Add scan index to each logged event -if nargin ~= 5 - fprintf('Wrong number of inputs\n'); - keyboard; -end - - -ListenChar(2);%disable pressed keys to be spitted around -commandwindow; -%clear everything -clear mex global functions -cgshut; -global cogent; -%%%%%%%%%%%load the GETSECS mex files so call them at least once -GetSecs; -WaitSecs(0.001); -% -el = []; -p = []; -SetParams; -debug = 1;%debug mode -%never set the debugging mode on if we are in the scanner computer. -if strcmp(p.hostname,'triostim1') - debug = 0; -end -SetPTB; -% - -%init all the variables -t = []; -nTrial = 0; -slice_index = []; -value = []; -%Time Storage -TimePulse1 = []; -TimePulse2 = []; -TimeStimOnset = []; -TimeCrossJumpTime = []; -TimeEndStim = []; -TimeStartShock = []; -TimeTrackerOff = []; -TimeTrackerOn = []; -TimeCrossOn = []; -p_mrt_on = []; -p_var_ExpPhase = []; -p_var_event_count = 0; -p_out_log = p.out.log; -p_ptb_w = p.ptb.w; -p_ptb_stim_sprites = p.ptb.stim_sprites; -p_ptb_CrossPosition_x = p.ptb.CrossPosition_x; -p_ptb_imrect = p.ptb.imrect; -p_ptb_CrossPositionET_x = p.ptb.CrossPositionET_x; -p_ptb_CrossPositionET_y = p.ptb.CrossPositionET_y; -p_ptb_slack = p.ptb.slack; -p_stim_white = p.stim.white; -p_ptb_midpoint = p.ptb.midpoint; -p_com_lpt_address = p.com.lpt.address; -p_com_lpt_StimOnset = p.com.lpt.StimOnset; -p_com_lpt_UCS = p.com.lpt.UCS; -p_com_lpt_FixOnset = p.com.lpt.FixOnset; -p_com_lpt_FixMove = p.com.lpt.FixMove; -p_com_lpt_StimOffset = p.com.lpt.StimOffset; - -p_duration_shockpulse = p.duration.shockpulse; -p_duration_crossmoves = p.duration.crossmoves; -p_duration_stim = p.duration.stim; -p_duration_onset2shock = p.duration.onset2shock; -p_duration_keep_recording = p.duration.keep_recording; -p_duration_prestim = p.duration.prestim; -p_stim_files = p.stim.files; -p_duration_prestim_ori = p.duration.prestim_ori; -p.com.serial = p.com.serial; -% -p_presentation_cross_position = p.presentation.cross_position; -p_ptb_device = p.ptb.device; -p_keys_confirm = p.keys.confirm; -% -InitEyeLink; -WaitSecs(2); -%calibrate if we are at the scanner computer. -if strcmp(p.hostname,'triostim1') - CalibrateEL; -end -%save again the parameter file -save(p.path.path_param,'p'); -% -if phase == 1 %training part... - - p.mrt.LastScans = 0;%scanner is off here, otherwise we will wait forever - p_mrt_on = 0; - p_var_ExpPhase = phase; - % - ShowInstruction(4,1); - ConfirmIntensity; - % - ShowInstruction(1,1); - ShowInstruction(2,1); - ShowInstruction(3,1); - PresentStimuli; - - -elseif phase == 2 - % - - p_mrt_on = 1; - p_var_ExpPhase = phase; - - WaitForPulseZero; - - ShowInstruction(5,1);%will wait for keypresses - fprintf('=================\n=================\nWill wait %d volumes for dummy...\n Tell MTA to turn the machine ON...\n',p.mrt.dummy_scan ); - - t = WaitPulseStrictlyAfterNow(p.mrt.dummy_scan); - PresentStimuli; - %make sure that scanner doesnt stop prematurely asa the stim offset - fprintf('Finished with all the trials, will wait %03d scans now\n', p.mrt.LastScans); - WaitPulseStrictlyAfterNow(p.mrt.LastScans); - % - StopScanner; - % - p_mrt_on = 0; - AskStimRating;%make sure that scanner doesnt stop prematurely asa the stim offset - fprintf('Finished with the rating\n'); - - % -elseif phase == 3 - % - p_mrt_on = 1; - p_var_ExpPhase = phase; - % - WaitForPulseZero; - % - ShowInstruction(6,1);%will not wait for keypresses - fprintf('=================\n=================\nWill wait %d volumes for dummy...\n Tell MTA to turn the machine ON...\n',p.mrt.dummy_scan ); - % - t = WaitPulseStrictlyAfterNow(p.mrt.dummy_scan); - PresentStimuli; - %make sure that scanner doesnt stop prematurely asa the stim offset - fprintf('Finished with all the trials, will wait %03d scans now\n', p.mrt.LastScans); - WaitPulseStrictlyAfterNow(p.mrt.LastScans) - % - StopScanner; - % - p_mrt_on = 0; - AskStimRating; - %makee sure that scanner doesnt stop prematurely asa the stim offset - fprintf('Finished with the rating\n'); - -elseif phase == 4 - p_mrt_on = 1; - p_var_ExpPhase = phase; - % - WaitForPulseZero; - % - ShowInstruction(6,1);%will not wait for keypresses - fprintf('=================\n=================\nWill wait %d volumes for dummy...\n Tell MTA to turn the machine ON...\n',p.mrt.dummy_scan ); - t = WaitPulseStrictlyAfterNow(p.mrt.dummy_scan); - % - PresentStimuli; - %makee sure that scanner doesnt stop prematurely asa the stim offset - fprintf('Finished with all the trials, will wait %03d scans now\n', p.mrt.LastScans); - WaitPulseStrictlyAfterNow(p.mrt.LastScans) - % - StopScanner; - % - p_mrt_on = 0; - AskStimRating; - %makee sure that scanner doesnt stop prematurely asa the stim offset - fprintf('Finished with the rating\n'); - %AskWhichFace; -end - -%get the eyelink file back to this computer -StopEyelink(p.path.edf); -%trim the log file and save -p_out_log = p_out_log(sum(isnan(p_out_log),2) ~= size(p_out_log,2),:); -%shift the time so that the first timestamp is equal to zero -p_out_log(:,1) = p_out_log(:,1) - p_out_log(1); -p.out.log = p_out_log;%copy it to the output variable. -save(p.path.path_param,'p'); -% -%move the file to its final location. -movefile(p.path.subject,p.path.finalsubject); -%close everything down -cleanup; - - function ConfirmIntensity - %Compute the intensity we want to deliver to the subject. - - p.var.ShockIntensity = p.out.PainThreshold*p.out.ShockFactor; - - % - ShowInstruction(9,1); - % - fprintf([repmat('=',1,50) '\n']); - fprintf('TEST SHOCK:\n'); - fprintf('!!! ADJUST THE SHOCK INTENSITY ON THE DIGITIMER !!!\n'); - fprintf(' The intensity is now: %g mA\n',p.var.ShockIntensity); - fprintf(' Experimenter: Press any key to deliver a shock.\n'); - fprintf([repmat('=',1,50) '\n']); - % - [secs, keyCode, deltaSecs] = KbStrokeWait; - ShowInstruction(10,0);%shock is coming message... - t = GetSecs + p.duration.shock; - while GetSecs < t; - Buzz; - end - % - message = 'Bewege den "Zeiger" mit der rechten und linken Pfeiltaste\n und besttige deine Einsch�tzung mit der mit der oberen Pfeiltaste.'; - rect = [p.ptb.width*0.2 p_ptb_midpoint(2) p.ptb.width*0.6 100]; - response = RatingSlider(rect,2,1,p.keys.increase,p.keys.decrease,p.keys.confirm,{ 'nicht\nertr�glich' 'ertr�glich'},message,0); - if response == 2 - fprintf('All is fine :)\n'); - fprintf('Subject confirmed the shock intensity inside the scanner...\n') - fprintf('INTENSITY TO BE USED FOR THE MAIN EXPERIMENT: %g mA\n',p.var.ShockIntensity); - p.out.ShockIntensity = p.var.ShockIntensity; - return; - elseif response == 1 - fprintf('Shit... :(, %g is too much for the subject\n',p.var.ShockIntensity); - fprintf('We will try a little milder intensity.\n'); - p.out.ShockFactor = p.out.ShockFactor - 0.05; - ConfirmIntensity; - end - - - end - function PresentStimuli - %Enter the presentation loop and wait for the first pulse to - %arrive. - p_presentation_stim_id = p.presentation.stim_id; - p_ptb_CrossPosition_y = p.ptb.CrossPosition_y; - p_presentation_isi = p.presentation.isi; - p_presentation_ucs = p.presentation.ucs; - p_presentation_oddball = p.presentation.oddball; - % - for nTrial = 1:p.presentation.tTrial; - % - %Get the variables that Trial function needs. - stim_id = p_presentation_stim_id(nTrial); - pos1 = p_ptb_CrossPosition_y(p_presentation_cross_position(nTrial)); - pos2 = p_ptb_CrossPosition_y(3-p_presentation_cross_position(nTrial)); - InNPulse = p_presentation_isi(nTrial); - ucs = p_presentation_ucs(nTrial); - oddball = p_presentation_oddball(nTrial); - % - fprintf('%d of %d, S: %d, ISI: %d, UCS: %d, ODD: %d.\n',nTrial,p.presentation.tTrial,stim_id,InNPulse,ucs,oddball); - % - if nTrial == p.presentation.tTrial%if last trial, then no next trial - next_pos1 = []; - next_stim_id = []; - else%get info about the next trial - next_pos1 = p_ptb_CrossPosition_y(p_presentation_cross_position(nTrial+1)); - next_stim_id = p_presentation_stim_id(nTrial+1); - if nTrial == 1%first trial. - %We will start the tracker and turn on the fixation cross - %for the first trial. These have to be done before the main - %for loop. - Screen('DrawText', p_ptb_w, double('+'), p_ptb_CrossPosition_x, pos1, p_stim_white); - TimeCrossOn = Screen('Flip',p_ptb_w); - % - TimeTrackerOn = StartEyelinkRecording(p_presentation_stim_id(nTrial),p_var_ExpPhase,oddball,ucs);%logs inside - % - %Mark the onset - MarkCED(p_com_lpt_address,p_com_lpt_FixOnset); - Eyelink('Message', 'FX Onset at %03d',pos1); - Log(TimeCrossOn, 1, pos1);%log the mark onset... - end - end - KbQueueStart(p_ptb_device);%monitor keypresses... - - %Start with the trial, here is time-wise sensitive must be - %optimal - Trial(stim_id,InNPulse,ucs,next_stim_id,pos1,pos2,next_pos1,oddball); - % - [keypressed, firstPress]=KbQueueCheck(p_ptb_device); - %if the press was after stimulus onset and before stimulus - %offset - if keypressed && (firstPress(p_keys_confirm) > TimeStimOnset) && (firstPress(p_keys_confirm) < TimeEndStim) - p.out.response(nTrial) = 1; - Log(firstPress(p_keys_confirm),7,NaN);%log the key press for hit detection. - fprintf('Subject Pressed the Hit Key!!\n'); - end - end - end - function Trial(stim_id,InNPulse,ucs,next_stim_id,pos1,pos2,next_pos1,oddball) - - %% Draw the stimulus to the buffer - Screen('DrawTexture', p_ptb_w, p_ptb_stim_sprites(stim_id)); - Screen('DrawText' , p_ptb_w, double('+'), p_ptb_CrossPosition_x,pos1, p_stim_white); - if oddball%add freckles to the face - x = randn(1,100)*35; - y = randn(1,100)*10; - s = rand(1,100);%[0 1] - Screen('DrawDots',p_ptb_w,[x;y],1+s.*1.5,[180 0 0 160],p_ptb_midpoint,1); - %the dots size - end - Screen('DrawingFinished',p_ptb_w,1); - - %% STIMULUS ONSET - %Here we wait only for the next pulse. - %The proper amount is obtained with the second call of WaitPulse - %below, before the onset of the fixation cross. - %fprintf('Will Wait for the pulse to Stim Onset\n'); - TimePulse1 = WaitPulseStrictlyAfterNow(1); - TimeStimOnset = Screen('Flip',p_ptb_w,0,1);%asap and dont clear - %send eyelink and ced a marker asap - Eyelink('Message', 'Stim Onset'); - Eyelink('Message', 'SYNCTIME'); - MarkCED( p_com_lpt_address, p_com_lpt_StimOnset ); - Log(TimeStimOnset,2,stim_id);%log the stimulus onset - - %% Now we have 750 ms to make all the variables ready for us later use... - - TimeCrossJumpTime = TimePulse1 + p_duration_crossmoves - p_ptb_slack; - TimeEndStim = TimePulse1 + p_duration_stim; - TimeStartShock = TimePulse1 + p_duration_onset2shock; - TimeTrackerOff = TimeEndStim + p_duration_keep_recording; - - %% CROSS JUMPS - %Update the image on the buffer with the new cross_pos - Screen('DrawTexture', p_ptb_w, p_ptb_stim_sprites(stim_id)); - Screen('DrawText' , p_ptb_w, double('+'), p_ptb_CrossPosition_x, pos2, p_stim_white); - if oddball == 1 - Screen('DrawDots',p_ptb_w,[x;y],1+s.*1.5,[180 0 0 160],p_ptb_midpoint,2); - end - Screen('DrawingFinished',p_ptb_w,0); - - %present it after 750 ms following Pulse Detection. - %why pulse detection and not stimulus onset. Because we don't want - %additional variability, everything should be defined with respect - %to the arrival... - TimeCrossJumpTime = Screen('Flip', p_ptb_w, TimeCrossJumpTime , 0); - - %send eyelink and ced a marker - MarkCED(p_com_lpt_address,p_com_lpt_FixMove); - Eyelink('Message', 'FX Moves to %03d' ,pos2); - Log(TimeCrossJumpTime,3,NaN);%log the fixation cross move - - %% UCS - Screen('DrawingFinished',p_ptb_w,0); - - if ucs == 1 - %%%%%%%%%%%%%%%%%%%%%%% - %Deliver shock and stim off immediately - TimeStartShock = WaitSecs('UntilTime',TimeStartShock); - Eyelink('Message', 'UCS Onset'); - while GetSecs < TimeEndStim; - Buzz;%this is anyway sent to CED. - end - Eyelink('Message', 'UCS Offset'); - end - - %% STIM OFF immediately - TimeEndStim = Screen('Flip',p_ptb_w,TimeEndStim); - %send eyelink and ced a marker - MarkCED(p_com_lpt_address,p_com_lpt_StimOffset); - Eyelink('Message', 'Stim Offset'); - Eyelink('Message', 'BLANK_SCREEN'); - Log(TimeEndStim,-2,stim_id);%log the stimulus offset - % - %% record some more eye data after stimulus offset. - WaitSecs('UntilTime',TimeTrackerOff); - TimeTrackerOff = StopEyelinkRecording; - - %% PRESTIMULUS - %turn on the fixation cross and start recording eye data for - %the next stimulus if there is any - if ~isempty(next_stim_id) - % - %% Fixation Onset - Screen('DrawText', p_ptb_w, double('+'), p_ptb_CrossPosition_x,next_pos1, p_stim_white); - %wait for the necessarily ISI amount - %fprintf('Will Wait for the necessary ISI amount\n'); - TimePulse2 = WaitPulseStrictlyAfterNow(InNPulse); - TimeCrossOn = Screen('Flip',p_ptb_w,TimePulse2+p_duration_prestim); - - MarkCED(p_com_lpt_address,p_com_lpt_FixOnset); - Eyelink('Message', 'FX Onset at %03d',pos1); - Log(TimeCrossOn,1,stim_id);%cross onset. - - %% TURN the Eye tracker on again - StartEyelinkRecording(next_stim_id,p_var_ExpPhase,oddball,ucs); - - %Verbose some information - %fprintf('StimulusID: %3d, Phase: %3d\n%0.10g Pulse Detected\n%0.10g (%0.10g) Stim Onset\n%0.10g (%0.10g) Cross Jumped\n%0.10g (%0.10g) StimOff\n%0.10g (%0.10g) Eyelink stops\n%0.10g (%0.10g) Cross Onset\n%0.10g (%0.10g) Start Eyelink\n',... - %stim_id,p_var_ExpPhase,TimePulse1,TimeStimOnset,TimeStimOnset-TimePulse1,TimeCrossJumpTime,TimeCrossJumpTime-TimePulse1,TimeEndStim, TimeEndStim-TimePulse1,TimeTrackerOff,TimeTrackerOff-TimePulse1,TimeCrossOn,TimeCrossOn-TimeEndStim,TimeTrackerOn,TimeTrackerOn-TimeEndStim); - %fprintf('Waited already %d TRs\n',InNPulse); - % - if oddball == 1 - fprintf('This was an oddball trial!\n'); - end - if ucs == 1 - fprintf('This was a UCS trial!\n'); - Log(TimeStartShock,4,NaN);%UCS delivery...This is done here to not waste time there - end - end - end - - function SetParams - %%%%%%%%%%%%%%%%%%%%%%%%%%% - p.mrt.dummy_scan = 7; - p.mrt.LastScans = 5;%number of scans after the offset of the last stimulus - p.mrt.tr = 2; - % - p.var.timings = zeros(1,10); - p_var_event_count = 0; - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %relative path to stim and experiments - %Path Business. - [~, hostname] = system('hostname'); - p.hostname = deblank(hostname); - if strcmp(p.hostname,'triostim1') - p.path.baselocation = 'C:\USER\onat\Experiments\'; - elseif strcmp(p.hostname,'etpc') - 1111 - p.path.baselocation = 'C:\Users\PsychToolbox\Documents\onat\Experiments\'; - else - p.path.baselocation = 'C:\Users\onat\Documents\Experiments\'; - end - - p.path.experiment = [p.path.baselocation 'FearGeneralization_Scanner\']; - p.path.stimfolder = 'Circle11_08Face_Frontal_SkinModerated_Transparent_Normalized'; - p.path.stim = [p.path.baselocation 'Stimuli\Gradients\' p.path.stimfolder '\']; - % - p.subID = sprintf('sub%02d',subject); - p.path.edf = sprintf([p.subID 'p%02d' ],phase); - timestamp = datestr(now,30); - p.path.subject = [p.path.experiment 'data\tmp\' p.subID '_' timestamp '\']; - p.path.finalsubject = [p.path.experiment 'data\' p.subID '_' timestamp '\' ]; - %create folder hierarchy - mkdir(p.path.subject); - mkdir([p.path.subject 'scr']); - mkdir([p.path.subject 'eye']); - mkdir([p.path.subject 'quadruplet']); - mkdir([p.path.subject 'stimulation']); - mkdir([p.path.subject 'midlevel']); - p.path.path_param = sprintf([regexprep(p.path.subject,'\\','\\\') 'stimulation\\param_phase_%02d'],phase); - - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %get stim files - [p.stim.files p.stim.label] = FileMatrix([p.path.stim '*.bmp']); - p.stim.tFile = size(p.stim.files,1);%number of different files (including the UCS symbol) - p.stim.tFace = p.stim.tFile - 1;%number of faces. - % - display([mat2str(p.stim.tFile) ' found in the destination.']); - %set the background gray according to the background of the stimuli - for i = 1:p.stim.tFile; - im = imread(p.stim.files(i,:)); - bg(i) = im(1,1,1); - end - %is all the captured bg values the same? - if sum(diff(bg))==0; - %if so take it as the bg color - p.stim.bg = double([bg(1) bg(1) bg(1)]); - else - fprintf('background luminance was not successfully detected...\n') - keyboard; - end - %bg of the rating screen. - p.stim.bg_rating = [0 128 0]; - % - %font size and background gray level - p.text.fontname = 'Times New Roman'; - p.text.fontsize = 18;%30; - %rating business - p.rating.division = 10;%number of divisions for the rating slider - p.rating.repetition = 2;%how many times a given face has to be repeated... - % - p.stim.white = [255 255 255]; - %get the actual stim size (assumes all the same) - info = imfinfo(p.stim.files(1,:)); - p.stim.width = info.Width; - p.stim.height = info.Height; - - if strcmp(p.hostname,'triostim1') - p.keys.confirm = KbName('7'); - p.keys.increase = KbName('8'); - p.keys.decrease = KbName('6'); - p.keys.space = KbName('space'); - p.keys.esc = KbName('esc'); - else - %All settings for laptop computer. - p.keys.confirm = KbName('up'); - p.keys.increase = KbName('right'); - p.keys.decrease = KbName('left'); - p.keys.space = KbName('space'); - p.keys.esc = KbName('esc'); - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %Communication business - %parallel port - p.com.lpt.address = 888; - %codes for different events - p.com.lpt.FixOnset = 1; - %2 is empty because - p.com.lpt.StimOnset = 4; - p.com.lpt.FixMove = 16; - p.com.lpt.UCS = 8;%2^5 - p.com.lpt.StimOffset = 32; - p.com.lpt.CS_plus = 64; - p.com.lpt.CS_neg = 128; - % - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %timing business - %these are the intervals of importance - %time2fixationcross->cross2onset->onset2shock->shock2offset - %these (duration.BLA) are average duration values: - p.duration.stim = 1.5;%s - p.duration.shock = 0.1;%s;x - p.duration.shockpulse = 0.005;%ms; duration of each individual pulses - p.duration.intershockpulse = 0.01;%ms; and the time between each pulse - p.duration.onset2shock = p.duration.stim - p.duration.shock; - p.duration.crossmoves = p.duration.stim./2; - p.duration.keep_recording = 0.1;%this is the time we will keep recording (eye data) after stim offset. - p.duration.prestim_ori = .95; - p.duration.prestim = 2-p.duration.prestim_ori;%that is 0.95 seconds - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %stimulus sequence - d = dir([p.path.experiment '*.mat']); - s = load([p.path.experiment d(end).name]); - s = s.sub; - - %create the randomized design - p.stim.cs_plus = s(NthSeq,CSpface).cs_plus;%index of cs stimulus, this is the one paired to shock - p.stim.cs_neg = s(NthSeq,CSpface).cs_neg; - %Record which Phase are we going to run in this run. - p.stim.phase = phase; - %this will deal all the presentation sequence related information - p.presentation = s(NthSeq,CSpface).phase(phase).presentation; - %make them non-logical otherwise Eyelink('Message') gives errors... - p.presentation.ucs = double(p.presentation.ucs); - p.presentation.oddball = double(p.presentation.oddball); - % - p.presentation.tTrial = length(p.presentation.stim_id); - % - p.out.rating = []; - p.out.log = zeros(1000000,4).*NaN; - p.out.response = zeros(p.presentation.tTrial,1); - p.out.PainThreshold = PainThreshold; - p.out.ShockFactor = 1.5; - %Save the stuff - save(p.path.path_param,'p'); - % - function [FM labels] = FileMatrix(path) - %Takes a path with file extension associated to regexp (e.g. - %C:\blabl\bla\*.bmp) returns the file matrix - dummy = dir(path); - FM = [repmat([fileparts(path) filesep],length(dummy),1) vertcat(dummy(:).name)]; - labels = {dummy(:).name}; - end - end - function AskStimRating - % - p_var_ExpPhase = 5; - BG = p.stim.bg;% - p.stim.bg = p.stim.bg_rating; - nseq = 0; - rating_seq = []; - pos1_seq = []; - % - while nseq < p.rating.repetition - nseq = nseq + 1; - rating_seq = [ rating_seq Shuffle(1:8)']; - end - message = GetText(11); - SliderTextL = GetText(13); - SliderTextR = GetText(12); - % - Screen('FillRect', p_ptb_w , p.stim.bg); - Screen('Flip',p_ptb_w); - WaitSecs(2); - % - ShowInstruction(7,1); - rect = [p.ptb.width*0.2 p_ptb_midpoint(2) p.ptb.width*0.6 100]; - tRatend = length(rating_seq); - %save the rating sequence just for security - p.out.rating_seq = rating_seq; - - for nRatend = 1:tRatend; - % - %the variable that are used by Trial function - stim_id = rating_seq(nRatend); - pos1 = p.ptb.CrossPosition_y(2); - pos2 = p.ptb.CrossPosition_y(1); - % - next_stim_id = [];%this is a trick, otherwise a fixation cross appears right before the rating :( - next_pos1 = []; - - %We will start the tracker and turn on the fixation cross - %for the first trial. These have to be done before the main - %for loop. - StartEyelinkRecording(stim_id,p_var_ExpPhase,0,0); - Screen('DrawText', p_ptb_w, double('+'), p.ptb.CrossPosition_x, pos1, p_stim_white); - t = Screen('Flip',p_ptb_w); - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %Mark the onset - MarkCED(p_com_lpt_address,p_com_lpt_FixOnset); - Eyelink('Message', 'FX Onset at %03d',pos1); - Log(t,1,pos1);%log the mark onset... - - % - Trial(stim_id,1,0,next_stim_id,pos1,pos2,next_pos1,0); - rate(nRatend,1) = RatingSlider(rect, p.rating.division, Shuffle(1:p.rating.division,1), p.keys.increase, p.keys.decrease, p.keys.confirm, {SliderTextL{1} SliderTextR{1}},message,1); - - %%%%%%%%%%%%%%%%%%%%%%%%%%%% - %Verbose the rating of the subject - fprintf('============\nRating Results %d (%d/%d):\n', stim_id, nRatend, tRatend); - dummy = rating_seq(1:nRatend);%trials shown so far - for iii = 1:8 - r = round(mean(rate(dummy == iii))); - if isnan(r) - r = 0; - end - if iii == p.stim.cs_plus - fprintf('Stimulus %02d: * %s \n',iii,repmat('+',1,1+r)); - else - fprintf('Stimulus %02d: %s \n',iii,repmat('+',1,1+r)); - end - end - end - %sort the stim_ids and then sort the same the rates and make a - %matrix out of that to store - [~, i] = sort(rating_seq); - rate = reshape(rate(i),p.rating.repetition,p.stim.tFace)'; - p.out.rating = rate; - save(p.path.path_param,'p'); - Screen('FillRect',p_ptb_w,p.stim.bg); - p.stim.bg = BG; - % - save(p.path.path_param,'p'); - end - function [rating] = RatingSlider(rect,tSection,position,up,down,confirm,labels,message,numbersOn) - % - %Detect the bounding boxes of the labels. - for nlab = 1:2 - [~ , ~, bb(nlab,:)]=DrawFormattedText(p_ptb_w,labels{nlab}, 'center', 'center', p_stim_white,[],[],[],2); - Screen('FillRect',p_ptb_w,p.stim.bg); - end - bb = max(bb); - bb_size = bb(3)-bb(1);%vertical size of the bb. - % - DrawSkala; - ok = 1; - while ok == 1 - [secs, keyCode, ~] = KbStrokeWait; - keyCode = find(keyCode); - Log(secs,7,keyCode); - if length(keyCode) == 1%this loop avoids crashes to accidential presses of meta keys - if (keyCode == up) || (keyCode == down) - next = position + increment(keyCode); - if next < (tSection+1) && next > 0 - position = position + increment(keyCode); - %rating = tSection - position + 1; - end - DrawSkala; - elseif keyCode == confirm - WaitSecs(0.1); - ok = 0; - Screen('FillRect',p_ptb_w,p.stim.bg); - t=Screen('Flip',p_ptb_w); - end - end - end - - function DrawSkala - %rating = tSection - position + 1; - rating = position ; - increment([up down]) = [1 -1];%delta - tick_x = linspace(rect(1),rect(1)+rect(3),tSection+1);%tick positions - tick_size = rect(3)./tSection; - ss = tick_size/5*0.9;%slider size. - % - for tick = 1:length(tick_x)%draw ticks - Screen('DrawLine', p_ptb_w, [255 0 0], tick_x(tick), rect(2), tick_x(tick), rect(2)+rect(4) , 3); - if tick <= tSection && numbersOn - Screen('TextSize', p_ptb_w,p.text.fontsize./2); - DrawFormattedText(p_ptb_w, mat2str(tick) , tick_x(tick)+ss/2, rect(2)+rect(4), p_stim_white); - Screen('TextSize', p_ptb_w,p.text.fontsize); - end - if tick == 1 - DrawFormattedText(p_ptb_w, labels{1},tick_x(tick)-bb_size*1.4,rect(2), p_stim_white); - elseif tick == tSection+1 - DrawFormattedText(p_ptb_w, labels{2},tick_x(tick)+bb_size*0.4,rect(2), p_stim_white); - end - end - %slider coordinates - slider = [ tick_x(position)+tick_size*0.1 rect(2) tick_x(position)+tick_size*0.9 rect(2)+rect(4)]; - %draw the slider - Screen('FillRect',p_ptb_w, p_stim_white, round(slider)); - Screen('TextSize', p_ptb_w,p.text.fontsize./2); - DrawFormattedText(p_ptb_w,message, 'center', p_ptb_midpoint(2)*0.2, p_stim_white,[],[],[],2); - Screen('TextSize', p_ptb_w,p.text.fontsize); - t = Screen('Flip',p_ptb_w); - Log(t,6,NaN); - end - end - function ShowInstruction(nInstruct,waitforkeypress) - %ShowInstruction(nInstruct,waitforkeypress) - %if waitforkeypress is 1, then subject has to press a button to - %make the instruction text dissappear. Otherwise you have to take - %care of it later - - [text]= GetText(nInstruct); - ShowText(text); - %let subject read it and ask confirmation to proceed. But we don't - %need that in the case of INSTRUCT = 5; - if waitforkeypress - if nInstruct ~= 10%this is for the Reiz kommnt - KbStrokeWait; - else - WaitSecs(2.5+rand(1)); - end - Screen('FillRect',p_ptb_w,p.stim.bg); - t = Screen('Flip',p_ptb_w); - Log(t,-5,nInstruct); - else - if nInstruct ~= 10%this is for the Reiz kommnt - KbStrokeWait; - else - WaitSecs(1+rand(1)); - end - end - - - function ShowText(text) - - Screen('FillRect',p_ptb_w,p.stim.bg); - %DrawFormattedText(p_ptb_w, text, p.text.start_x, 'center',p_stim_white,[],[],[],2,[]); - DrawFormattedText(p_ptb_w, text, 'center', 'center',p_stim_white,[],[],[],2,[]); - t=Screen('Flip',p_ptb_w); - Log(t,5,nInstruct); - %show the messages at the experimenter screen - fprintf('=========================================================\n'); - fprintf('Text shown to the subject:\n'); - fprintf('=========================================================\n'); - fprintf(text); - fprintf('=========================================================\n'); - - end - end - function [text]=GetText(nInstruct) - if nInstruct == 0%Eyetracking calibration - - text = ['Um Deine Augenbewegungen zu messen, \n' ... - 'm�ssen wir jetzt den Eye-Tracker kalibrieren.\n' ... - 'Dazu zeigen wir Dir einige Punkte auf dem Bildschirm, \n' ... - 'bei denen Du Dich entsprechend der eben genannten Regel verh�lst:\n' ... - 'Bitte fixiere das Fixationskreuz und \n' ... - 'bleibe so lange darauf, wie es zu sehen ist.\n' ... - 'Bitte dr�cke jetzt den mittleren Knopf, \n' ... - 'um mit der Kalibrierung weiterzumachen.\n' ... - ]; - - elseif nInstruct == 1%first Instr. of the training phase. - text = ['Wir werden nun als erstes einen �bungsdurchgang machen,\n' ... - 'damit Du Dich im Scanner an Deine Aufgabe gew�hnen kannst.\n' ... - 'In diesem Durchgang kannst Du Dich vollkommen sicher f�hlen,\n' ... - 'es werden keine elektrischen Reize verabreicht.\n' ... - 'Eine wichtige grunds�tzliche Regel ist, dass Du das Fixationskreuz (das �+�)\n' ... - 'sobald es zu sehen ist mit Deinen Augen fixierst UND \n' ... - 'den Blick die ganze Zeit darauf richtest, solange es zu sehen ist.\n' ... - 'Das Fixationskreuz ver�ndert seine Position � immer nach oben � und \n' ... - 'es ist wichtig, dass Du dieser Bewegung so genau wie m�glich \n' ... - 'mit Deinem Blick folgst.\n' ... - 'Dr�cke die mittlere Taste um mit dem n�chsten Abschnitt fortzufahren.\n' ... - ]; - elseif nInstruct == 2%second Instr. of the training phase. - text = ['Ein paar Bemerkungen zu den Zielreizen: \n' ... - 'Zur Erinnerung: Zielreize sind die Gesichter mit Sommersprossen.\n' ... - 'Sobald ein solcher Zielreiz erscheint, \n' ... - 'sollst Du schnellstm�glich die mittlere Taste dr�cken, \n' ... - 'und zwar bevor der Reiz wieder verschwunden ist \n' ... - '(Du musst also sehr schnell und aufmerksam sein).' ... - ]; - elseif nInstruct == 3%third Instr. of the training phase. - text = ['Es ist sehr wichtig, dass Du Deinen Kopf w�hrend \n' ... - 'des Experiments nicht bewegst. \n' ... - 'Das ist besonders wichtig f�r die Qualit�t der Messung.\n' ... - 'Daher sollte Deine Kopfhaltung so bequem wie m�glich sein.\n' ... - 'Wenn es sich jetzt gerade nicht bequem anf�hlt oder \n' ... - 'Du das Gef�hl hast, \n' ... - 'Du m�chtest die Position noch ver�ndern, \n' ... - 'ist jetzt der Moment, in dem Du das tun kannst.\n' ... - ]; - elseif nInstruct == 4%third Instr. of the training phase. - text = ['Vor dem �bungsdurchgang legen wir nun \n' ... - 'die Schockintensit�t f�r den Rest des Experiments fest. \n' ... - 'Dr�cke die mittlere Taste um fortzufahren.' ... - ]; - - elseif nInstruct == 5%Baseline Phase - % - % - %=================================================================================================================% - text = ['Jetzt geht es mit dem Experiment los.\n' ... - 'Deine Aufgabe ist es jetzt, genauso wie im Training die Gesichter, \n' ... - 'die Dir gezeigt werden aufmerksam zu betrachten und \n' ... - 'den mittleren Knopf zu dr�cken, sobald du einen Zielreiz siehst.\n' ... - '\n'... - 'Hin und wieder erscheint ein Symbol (ein Blitzpfeil, der vor Strom warnt), \n' ... - 'das einen elektrischen Reiz ank�ndigt. \n' ... - 'Die Reize erfolgen aber nur bei diesem Symbol, nicht bei den Gesichtern! \n' ... - 'Bei Gesichtern kannst Du Dich also sicher f�hlen.\n' ... - 'Bitte denke daran: 1. Folge immer den Fixationskreuz und 2. nicht bewegen!\n\n' ... - 'Wenn Du noch Fragen hast, kannst du sie jetzt gerne �ber die Sprechanlage stellen. \n' ... - 'Ansonsten kannst Du das Experiment �ber die mittlere Taste starten. \n' ... - ]; - - elseif nInstruct == 6%Test and Conditioning Phase - %=================================================================================================================% - text = ['Auch im nun folgenden Teil des Experiments \n' ... - 'sollst Du die Gesichter aufmerksam betrachten und \n' ... - 'den mittleren Knopf dr�cken, sobald du einen Zielreiz siehst. \n' ... - 'Wie im ersten Teil des Experiments sollst Du \n' ... - 'das Fixationskreuz immer fixieren, \n' ... - 'ihm immer folgen und Deinen Blick nie von ihm abwenden. \n\n' ... - 'In dieser Phase des Experiments wirst du wieder \n' ... - 'gelegentlich elektrische Reize bekommen.\n\n' ... - 'Die elektrischen Reize folgen jetzt jedoch auf eins der Gesichter, \n' ... - 'das elektrische Symbol wirst Du nicht mehr sehen. \n' ... - ]; - - - elseif nInstruct == 7;%rating - text = ['In dieser Phase h�tten wir gerne, dass Du die Gesichter\n'... - 'im Hinblick auf folgende Frage bewertest:\n'... - '�Wie wahrscheinlich ist es, bei dem gerade gesehenen Gesicht \n'... - 'einen elektrischen Schock zu erhalten?�\n'... - 'Bewege den Zeiger mit der rechten und linken Pfeiltaste \n'... - 'und best�tige Deine Einsch�tzung mit der oberen Pfeiltaste.\n'... - ]; - - elseif nInstruct == 8 %CS+ detection - text = ['Du bekommst nun eine Reihe von Gesichtern gezeigt.\n' ... - 'Bitte w�hle das Gesicht aus bei dem der Schock verabreicht wurde.\n'... - 'Dr�cke die mittlere Taste um fortzufahren.\n'... - ]; - elseif nInstruct == 9% - %=================================================================================================================% - text = ['Gib bitte an, ob die Reizst�rke des folgenden Schocks\n f�r Dich ertr�glich ist.\n'... - '\n'... - 'Dr�cke bitte die mittlere Taste um den Reiz zu bekommen.\n'... - ]; - - elseif nInstruct == 10%just before the shock - text = ['Reiz kommt...\n']; - elseif nInstruct == 11%this is the rating question - text = ['Wie wahrscheinlich ist es, bei dem gerade gesehenen Gesicht \n'... - 'einen elektrischen Schock zu erhalten?�\n' ... - 'Bewege den "Zeiger" mit der rechten und linken Pfeiltaste\n' ... - 'und bestaetige deine Einschaetzung mit der mit der oberen Pfeiltaste'... - ]; - elseif nInstruct == 12 %These two below are the possible responses to the question in 11 - text = {'Sehr\nwahrscheinlich'}; - elseif nInstruct == 13 - text = {'�berhaupt\nnicht\nwahrscheinlich'}; - else - text = {''}; - end - end - function SetPTB - %Sets the parameters related to the PTB toolbox. Including - %fontsizes, font names. - %Find the number of the screen to be opened - screens = Screen('Screens'); - p.ptb.screenNumber = max(screens);%the maximum is the second monitor - %Make everything transparent for debugging purposes. - if debug - commandwindow; - PsychDebugWindowConfiguration; - end - - %Default parameters - Screen('Preference', 'SkipSyncTests', 1); - Screen('Preference', 'DefaultFontSize', p.text.fontsize); - Screen('Preference', 'DefaultFontName', p.text.fontname); - Screen('Preference', 'TextAntiAliasing',2);%enable textantialiasing high quality - Screen('Preference', 'VisualDebuglevel', 0); - Screen('Preference', 'SkipSyncTests', 1); - Screen('Preference', 'SuppressAllWarnings', 1); - %set the resolution correctly - if strcmp(p.hostname,'triostim1') - p.ptb.oldres = Screen('resolution',p.ptb.screenNumber,1280,960); - %hide the cursor - HideCursor(p.ptb.screenNumber); - end - - %Open a graphics window using PTB - p.ptb.w = Screen('OpenWindow', p.ptb.screenNumber, p.stim.bg); - Screen('BlendFunction', p.ptb.w, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - Screen('Flip',p.ptb.w);%make the bg - p.ptb.slack = Screen('GetFlipInterval',p.ptb.w)./2; - [p.ptb.width, p.ptb.height] = Screen('WindowSize', p.ptb.screenNumber); - if sum([p.ptb.width p.ptb.height] - [1280 960]) ~= 0 - fprintf('SET THE CORRECT SCREEN RESOLUTION\n'); - end - %find the mid position on the screen. - p.ptb.midpoint = [ p.ptb.width./2 p.ptb.height./2]; - p.ptb.imrect = [ p.ptb.midpoint(1)-p.stim.width/2 p.ptb.midpoint(2)-p.stim.height/2 p.stim.width p.stim.height]; - %compute the cross position. - [~, ny bb] = DrawFormattedText(p.ptb.w,'+','center','center'); - p.ptb.cross_shift = [45 60];%incremental upper and lower cross positions - p.ptb.CrossPosition_y = [ny-p.ptb.cross_shift(1) ny+p.ptb.cross_shift(2) ]; - p.ptb.CrossPosition_x = bb(1);%always the same - %cross position for the eyetracker screen. - p.ptb.CrossPositionET_x = [p.ptb.midpoint(1) p.ptb.midpoint(1)]; - p.ptb.CrossPositionET_y = [p.ptb.midpoint(2)-p.ptb.cross_shift(2) p.ptb.midpoint(2)+p.ptb.cross_shift(2)]; - %% - %priorityLevel=MaxPriority(['GetSecs'],['KbCheck'],['KbWait'],['GetClicks']); - Priority(MaxPriority(p.ptb.w)); - %this is necessary for the Eyelink calibration - %InitializePsychSound(0) - - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %set serial communication channels - IOPort('CloseAll'); -% p.com.serial = IOPort('OpenSerialPort', 'COM1', 'InputBufferSize=51840000 HardwareBufferSizes=32768,32768 Terminator=0 ReceiveLatency=0.0001 BaudRate=9600 ReceiveTimeout=7'); -% IOPort('ConfigureSerialPort', p.com.serial, 'BlockingBackgroundRead=1'); - %because of the BlockingBackgroundRead=1, the flush and close all - %command will wait for the next byte to arrive... -% IOPort('ConfigureSerialPort', p.com.serial, 'StartBackgroundRead=2'); -% IOPort('Flush', p.com.serial); - %2 is the granularity of the data, cogent box sends 2 bytes. - %IOPort('ConfigureSerialPort', p.com.serial, 'ReadTimeout=5'); - - %%%%%%%%%%%%%%%%%%%%%%%%%%%Prepare the keypress queue listening. - p.ptb.device = -1; - p.ptb.keysOfInterest=zeros(1,256); - p.ptb.keysOfInterest(p.keys.confirm) = 1; - KbQueueCreate(p.ptb.device,p.ptb.keysOfInterest);%default device. - - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %prepare parallel port communication. This relies on cogent i - %think. We could do it with PTB as well. - config_io; - outp(p.com.lpt.address,0); - if( cogent.io.status ~= 0 ) - error('inp/outp installation failed'); - end - %test whether CED receives the triggers correctly... - k = 0; - while k ~= 49; - outp(888,255);pause(0.1);outp(888,0); - fprintf('=================\nDid the trigger test work?\nPress 0 to send it again, 1 to continue...\n') - [~, k] = KbStrokeWait; - k = find(k); - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %load the pictures to the memory. - p.ptb.stim_sprites = CreateStimSprites(p.stim.files);% - - function [out]=CreateStimSprites(files) - %loads all the stims to video memory - for nStim = 1:p.stim.tFile - filename = files(nStim,:); - [im , ~, ~] = imread(filename); - out(nStim) = Screen('MakeTexture', p.ptb.w, im ); - end - end - end - function StopScanner - fprintf('=================\nThis was it for this phase!\nTell MTA to turn the machine OFF...\nAnd press RETURN' ); - % - k = 0; - while k ~= 13 - [~, k] = KbStrokeWait; - k = find(k); - end - end - function [t]=StopEyelinkRecording - Eyelink('StopRecording'); - t = GetSecs; - %this is the end of the trial scope. - WaitSecs(0.01); - Eyelink('Message', 'TRIAL_RESULT 0'); - % - WaitSecs(0.01); - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('Command', 'clear_screen %d', 0); - Log(t,-8,NaN); - end - function [t]=StartEyelinkRecording(nStim,phase,oddball,ucs) - nStim = double(nStim); - Eyelink('Message', 'TRIALID: %03d, PHASE: %02d, ODDBALL: %02d, UCS: %02d', nStim, phase,oddball,ucs); - % an integration message so that an image can be loaded as - % overlay background when performing Data Viewer analysis. - WaitSecs(0.01); - Eyelink('Message', '!V IMGLOAD CENTER %s %d %d', p_stim_files(nStim,:), p_ptb_midpoint(1), p_ptb_midpoint(2)); - % This supplies the title at the bottom of the eyetracker display - Eyelink('Command', 'record_status_message "Stim: %02d, Phase: %d"', nStim, phase); - % - %Put the tracker offline and draw the stimuli. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - % clear tracker display and draw box at center - Eyelink('Command', 'clear_screen %d', 0); - %draw the image on the screen but also the two crosses - if nStim <= 9 - Eyelink('ImageTransfer',p_stim_files(nStim,:),p_ptb_imrect(1),p_ptb_imrect(2),p_ptb_imrect(3),p_ptb_imrect(4),p_ptb_imrect(1),p_ptb_imrect(2)); - end - Eyelink('Command', 'draw_cross %d %d 15',p_ptb_CrossPositionET_x(1),p_ptb_CrossPositionET_y(1) ); - Eyelink('Command', 'draw_cross %d %d 15',p_ptb_CrossPositionET_x(2),p_ptb_CrossPositionET_y(2) ); - % - %drift correction - %EyelinkDoDriftCorrection(el,0,0,0,0); - %start recording following mode transition and a short pause. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('StartRecording'); - t = GetSecs; - Log(t,8,NaN); - end - function shuffled = Shuffle(vector,N) - %takes first N from the SHUFFLED before outputting. This function - %could be used as a replacement for randsample - if nargin < 2;N = length(vector);end - [~, idx] = sort(rand([1 length(vector)])); - shuffled = vector(idx(1:N)); - shuffled = shuffled(:); - end - function Buzz - outp(p_com_lpt_address, p_com_lpt_UCS ); - WaitSecs(p_duration_shockpulse); - outp(p_com_lpt_address, 0); - WaitSecs(p.duration.intershockpulse); - end - function MarkCED(socket,port) - %send pulse to SCR# - outp(socket,port); - WaitSecs(0.01); - outp(socket,0); - end - function InitEyeLink - % - WaitSecs(0.5); - [~, vs] = Eyelink('GetTrackerVersion'); - fprintf('=================\nRunning experiment on a ''%s'' tracker.\n', vs ); - % - el = EyelinkInitDefaults(p_ptb_w); - %update the defaults of the eyelink tracker - el.backgroundcolour = p.stim.bg; - el.msgfontcolour = WhiteIndex(el.window); - el.imgtitlecolour = WhiteIndex(el.window); - el.targetbeep = 0; - el.calibrationtargetcolour = WhiteIndex(el.window); - el.calibrationtargetsize = 1.5; - el.calibrationtargetwidth = 0.5; - el.displayCalResults = 1; - el.eyeimgsize = 50; - el.waitformodereadytime = 25;%ms - el.msgfont = 'Times New Roman'; - el.cal_target_beep=[1250 0.6 0.05]; - %shut all sounds off - el.drift_correction_target_beep = [0 0 0]; - el.calibration_failed_beep = [0 0 0]; - el.calibration_success_beep = [0 0 0]; - el.drift_correction_failed_beep = [0 0 0]; - el.drift_correction_success_beep= [0 0 0]; - EyelinkUpdateDefaults(el); - - - if EyelinkInit(0)%use 0 to init normaly - fprintf('=================\nEyelink initialized correctly...\n') - else - fprintf('=================\nThere is problem in Eyelink initialization\n') - keyboard; - end - - % open file. - res = Eyelink('Openfile', p.path.edf); - if res ~= 0 - fprintf('=================\nCannot create EDF file ''%s'' ', p.path.edf); - cleanup; - return; - end - % - Eyelink('command', 'add_file_preamble_text ''Recorded by EyelinkToolbox FearGen2 Experiment'''); - Eyelink('command', 'screen_pixel_coords = %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - Eyelink('message', 'DISPLAY_COORDS %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - % set calibration type. - Eyelink('command', 'calibration_type = HV5'); - Eyelink('command', 'select_parser_configuration = 1'); - %what do we want to record - Eyelink('command', 'file_sample_data = LEFT,RIGHT,GAZE,HREF,AREA,GAZERES,STATUS,INPUT,HTARGET'); - Eyelink('command', 'file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON,INPUT'); - Eyelink('command', 'use_ellipse_fitter = no'); - % set sample rate in camera setup screen - Eyelink('command', 'sample_rate = %d',1000); - end - function StopEyelink(filename) - try - fprintf('Trying to stop the Eyelink system with StopEyelink\n'); - Eyelink('StopRecording'); - WaitSecs(0.5); - Eyelink('Closefile'); - display('receiving the EDF file...'); - Eyelink('ReceiveFile',filename,[p.path.subject '\eye\'],1); - display('...finished!') - % Shutdown Eyelink: - Eyelink('Shutdown'); - catch - display('StopEyeLink routine didn''t really run well'); - end - end - function cleanup - - % Close window: - sca; - %set back the old resolution - if strcmp(p.hostname,'triostim1') - Screen('Resolution',p.ptb.screenNumber, p.ptb.oldres.width, p.ptb.oldres.height ); - %show the cursor - ShowCursor(p.ptb.screenNumber); - end - % - IOPort('ConfigureSerialPort', p.com.serial,' StopBackgroundRead'); - IOPort('Close',p.com.serial); - commandwindow; - ListenChar(0); - KbQueueRelease(p_ptb_device); - end - function CalibrateEL - fprintf('=================\n=================\nEntering Eyelink Calibration\n') - p_var_ExpPhase = 0; - ShowInstruction(0,1); - EyelinkDoTrackerSetup(el); - %Returns 'messageString' text associated with result of last calibration - [~, messageString] = Eyelink('CalMessage'); - Eyelink('Message','%s',messageString);% - WaitSecs(0.05); - fprintf('=================\n=================\nNow we are done with the calibration\n') - end - function AskWhichFace - R=[]; - offset_x = 0; - offset_y = 0; - for i = 1:4 - R = [R ; [offset_x+(i-1)*420 offset_y offset_x+(i-1)*420+400 400 ]]; - end - offset_y = 470; - for i = 1:4 - R = [R ; [offset_x+(i-1)*420 offset_y offset_x+(i-1)*420+400 400+offset_y ]]; - end - R(:,[1 3]) = R(:,[1 3]) + (p.ptb.width - max(R(:,3)))./2; - R(:,[2 4]) = R(:,[2 4]) + (p.ptb.height- max(R(:,4)))./2; - - ShowInstruction(8,1); - Screen('DrawTextures',p_ptb_w,p_ptb_stim_sprites(Shuffle(1:8)),[],R'); - for i = 1:8 - Screen('DrawText', p_ptb_w, double(mat2str(i)), mean(R(i,[1 3])) , R(i,2) , p_stim_white); - end - Screen('Flip',p_ptb_w); - % - ok = 1; - while ok == 1 - [~, keyCode, ~] = KbStrokeWait; - face_i = KbName(find(keyCode)); - if ischar(face_i) == 1 - face_i = str2double(face_i(1)); - if face_i < 9 && face_i > 0 - ok = 0; - end - end - end - p.out.csplus_identification = face_i; - end - function [slice_index]=Value2Slice(value) - slice_index = value(1)*255 + value(2); - end - function [t_pulse,value]=WaitForPulseZero - %[t_pulse,value]=WaitForPulseZero - fprintf('Press cogent box baby\n'); - value = []; - t_now = GetSecs;%this is the time this function is called, we require that the pulse - %which is detected to arrive later than this time. - t_pulse = t_now;%if n=0, that is no wait for pulse, than pulse arrival is now... - ok =1; - while ok - %read data with a granularity of 2 in a blocking way... - [value, t_pulse] = IOPort('Read', p.com.serial,1,2); - if (t_pulse > t_now) && sum(value) == 0%only consider pulses that arrives strictly after the call of this function. - ok = 0; - Log(t_pulse,0,Value2Slice(value)); - end - end - fprintf('Pulse Detected at %g\nValue is [%d %d]\n',t_pulse,value(1),value(2)); - end - function [t_pulse,value]=WaitPulseStrictlyAfterNow(n) - %[t_pulse,value]=WaitPulseStrictlyAfterNow(n) - % - %This function waits for the Nth upcoming pulse. If N=1, it will wait for - %the very next pulse to arrive. 1 MEANS NEXT PULSE. So if you want to wait - %for 6 full dummy scans, you should use N = 7 to be sure that at least 6 - %full scans are finished. T_PULSE is the timestamp of the last - %pulse in case N is >1. - % - %If there are however pulses that were already waiting in the - %buffer before you called this function additional measures has to - %be taken. Therefore this function do not considers all the pulses - %that were received right after the call of this function. This - %costs us an additional IF loop.. - % - %It expects that the serial port handle is a global variable. - % - %Selim Onat, 24-Jan-2013 10:55:53 - if p_mrt_on; - t_now = GetSecs;%this is the time this function is called, we require that the pulse - %which is detected to arrive later than this time. - pulse = 0;%pulse counter - t_pulse = t_now;%if n=0, that is no wait for pulse, than pulse arrival is now... - if n > 0 - while pulse < n - ok =1; - while ok - %read data with a granularity of 2 in a blocking way... - [value, t_pulse] = IOPort('Read', p.com.serial,1,2); - if t_pulse > t_now%only consider pulses that arrives strictly after the call of this function. - ok = 0; - Log(t_pulse,0,Value2Slice(value)); - end - end - %fprintf('Pulse %d is detected at %g \n', Value2Slice(value) , t_pulse ); - pulse = pulse + 1; - end - end - else - %if the scanner is off, it will wait randomly 0.5 to 1 seconds, - %however if the scanner is off AND the input is 0, then it will - %not wait at all. - value = NaN(1,2); - if n ~= 0 - t_pulse = WaitSecs(p_duration_prestim_ori); - else - t_pulse = WaitSecs(0.001); - end - end - %fprintf('now was %g\n',t_now); - end - function Log(ptb_time, event_type, event_info) - %Phases: - %Instruction : 1 - %Baseline : 2 - %Conditioning : 3 - %Test : 4 - %Rating : 5 - %Calibration : 0 - % - %event types are as follows: - % - %Scan Detection : 0 info: NaN; - %Cross Onset : 1 info: position - %Stimulus Onset/Offset: 2/-2 info: stim_id - %Cross Movement : 3 info: NaN; - %Stimulus Offset : -2 info: NaN; - %UCS Delivery : 4 info: NaN; - %Key Presses : 7 info: NaN; - %Tracker Onset/Offset : 8 info: NaN; - % - %Text on the screen : 5 info: Which Text? - %RatingScreen Onset : 6 info: NaN; - - p_var_event_count = p_var_event_count + 1; - p_out_log(p_var_event_count,:) = [ptb_time event_type event_info p_var_ExpPhase]; - % % p_out_log(p.out.event_counter,:) - %logstring([ 'Logged: ' mat2str(p_out_log(p.out.event_counter,:)) ' - Type: ' p.verbose.eventtype{abs(event_type)} ' - Phase: ' p.verbose.eventphase{CurrentExperimentalPhase}]) - %for i = 1:3;subplot(3,1,i);plot(p_out_log(1:p.out.event_counter ,i),'o-');drawnow;end - % - - end - - -end diff --git a/exp_FearGen_ForAll.m b/exp_FearGen_ForAll.m deleted file mode 100644 index 5ca0eb6..0000000 --- a/exp_FearGen_ForAll.m +++ /dev/null @@ -1,1365 +0,0 @@ -function [p]=exp_FearGen_ForAll(subject,Nseq,phase,csp,PainThreshold) -%[p]=exp_FearGen_ForAll(subject,phase,csp,PainThreshold) - -% -% -% This code is based on the exp_FearAmy.m, adapted to run the initial FearGen -% experiment (Onat & Buechel, 2015). -% -% When the experiment starts as experimenter you will have to pass through -% few sanity checks (press (V)alidate to continue). Once these are -% passed, some text will be shown to the participant. You can also pass -% these stages by pressing V (normally the subject has to read them and -% press confirm key). These instructions for participants are shown using -% the ShowInstruction function, where you precise instructions by their -% id number. All instructions are stored in the GetText function by these -% ids. So if you would like to change instructions you will need to -% modify that function. -% -% The experiment starts with PHASE = 1. Here I set the shock intensity -% while the participant is in the scanner. The shock threshold is -% measured outside the scanner. This is here just to validate the shock -% intensity that will be used during the experiment, it is obtained by -% the PAINTHRESHOLD (given as input) times P.OUT.SHOCKFACTOR (defined -% below). PAINTHRESHOLD is only painful half of the time by definition, -% and we would like to give a shock which is more painful but still -% bearable by the participant. That is, I ask the participant to confirm -% the shock is PAINFUL and BEARABLE. If the shock is not bearable the -% program will propose a lower amplitude and the same question will be -% repeated until these two conditions are fulfilled. It is always good to -% stay in oral communication with the participant though. The phase = 1 -% continues with a short presentation of faces, where I evaluate whether -% they 1/ follow the fixation cross as instructed and 2/ detect the -% oddball target. If they fail in any of these, phase 1 is repeated. This -% phase also helps people to familiarize with the faces if no other task -% has yet been carried out befo -% -% The phase 2 is baseline. All faces are shown, but non predicts the -% shock. Instead shocks are delivered after a shock symbol. This phase -% ends with ratings. -% -% Phase 3 is conditioning. Only CS+ and CS- are shown and CS+ is shocked -% at about 30% of the cases. -% -% Phase 4 is similar to baseline, all faces are shown, but shock follows -% the CS+ face to avoid extinction. Following this phase, there is the -% detection task. -% -% -% The current experiment can fully work with the Eyelink -% eye-tracker. This is however now disabled. If you intent to record -% eye-movements turn the EyelinkWanted flag to 1. -% -% The parallel communication currently relies on the cogent's OUTP -% function. It is used to deliver shocks and to send event pulses to the -% physio computer. If you intend to use a Windows systems you can install -% cogent and outp function, then you would be able to directly use this -% code. Or take the extra mile and code the outp equivalent in PTB (that -% would be nice). -% -% To do before you start: -% Set the baselocation for the experiment in SetParams around line 420: -% p.path.baselocation variable. this location will be used to save -% the experiment-related data for the current subject. -% -% -% Example usage: -% exp_FearGen_ForAll(12,3,4,1,8.43); runs the Conditioning paradigm (3) for -% participant 12, using the stimulus sequence 4 where the CS+ face is -% face number 1 for a participant who has a shock intensity of 8.43. -% -% -% Selim Onat - -debug = 1;%debug mode => 1: transparent window enabling viewing the background. -EyelinkWanted = 0;%is Eyelink wanted? -%replace parallel port function with a dummy function -if ~IsWindows - %OUTP.m is used to communicate with the parallel port, mainly to send - %triggers to the physio-computer or Digitimer device (which is used to give - %shocks). OUTP is a cogent function, so it only works with Windows. In - %Unix the same functionality can also be obtained with PTB, but it is not - %coded in this program yet. So to communicate via the parallel port, there - %are two options: 1/install cogent + outp, or 2/ use equivalent of OUTP - %in PTB. This presentation will now replace the OUTP.m function with - %the following code, which simply does nothing but allows the program - %run. - - %% outp = @(x,y) 1; -end -if nargin ~= 5 - fprintf('Wrong number of inputs\n'); - keyboard; -end - -csn = mod( csp + 8/2-1, 8)+1;%obtain CS- from the CS+ faces -commandwindow;%focus on the command window, so that output is not written on the editor -%clear everything -clear mex global functions;%clear all before we start. - -if IsWindows%clear cogent if we are in Windows and rely on Cogent for outp. - cgshut; - global cogent; -end -%%%%%%%%%%%load the GETSECS mex files so call them at least once -GetSecs; -WaitSecs(0.001); -% -el = [];%eye-tracker variable -p = [];%parameter structure that contains all info about the experiment. -s = []; -SetParams;%set parameters of the experiment -SetPTB;%set visualization parameters. -% -%init all the variables -t = []; -nTrial = 0; -%% -%Time Storage -TimeEndStim = []; -TimeStartShock = []; -TimeTrackerOff = []; -TimeCrossOn = []; -p.var.event_count = 0; -%% -InitEyeLink; -WaitSecs(2); -KbQueueStop(p.ptb.device); -KbQueueRelease(p.ptb.device); -%save again the parameter file -save(p.path.path_param,'p'); -if phase == 1 - % - p.mrt.dummy_scan = 0;%for the training we don't want any pulses - p.var.ExpPhase = phase; - %UCS check - ShowInstruction(4,1); - ConfirmIntensity; - %test - ShowInstruction(1,1); - ShowInstruction(2,1); - PresentStimuli; - -elseif phase > 1%baseline, conditioning and test phases - % - if EyelinkWanted - CalibrateEL; - ShowInstruction(299,0,5); - end - %% Vormessung - p.var.ExpPhase = phase;%set this after the calibration; - k = 0; - while ~(k == p.keys.el_calib); - pause(0.1); - fprintf('Experimenter!! press V key when the vormessung is finished.\n'); - [~, k] = KbStrokeWait(p.ptb.device); - k = find(k); - end - fprintf('Continuing...\n'); - %% - for ninst = [3 301:306] - ShowInstruction(ninst,1); - end - PresentStimuli; - WaitSecs(2.5); - AskStimRating;%make sure that scanner doesnt stop prematurely asa the stim offset - if phase == 4 - if EyelinkWanted - CalibrateEL; - AskDetection; - end - AskDetectionSelectable; - end -end - -%get the eyelink file back to this computer -StopEyelink(p.path.edf); -%trim the log file and save -p.out.log = p.out.log(sum(isnan(p.out.log),2) ~= size(p.out.log,2),:); -%shift the time so that the first timestamp is equal to zero -p.out.log(:,1) = p.out.log(:,1) - p.out.log(1); -p.out.log = p.out.log;%copy it to the output variable. -save(p.path.path_param,'p'); -% -%move the file to its final location. -movefile(p.path.subject,p.path.finalsubject); -%close everything down -cleanup; - - function AskDetectionSelectable - %asks subjects to select the face that was associated with a shocks - positions = circshift(1:8,[1 Shuffle(1:8,1)]);%position of the marker - p.var.ExpPhase = 4; - ShowInstruction(8,1); - %% - increment([p.keys.increase p.keys.decrease]) = [1 -1];%key to increment mapping - %% - ok = 1; - while ok - DrawCircle; - Screen('FrameOval', p.ptb.w, [1 1 0], p.stim.circle_rect(positions(1),:), 2);%draw the marker circle somewhere random initially. - Screen('Flip',p.ptb.w); - [~, keyCode, ~] = KbStrokeWait(p.ptb.device);%observe key presses - keyCode = find(keyCode); - if length(keyCode) == 1%this loop avoids crashes to accidential presses of meta keys - if (keyCode == p.keys.increase) || (keyCode == p.keys.decrease) - positions = circshift(positions,[0 increment(keyCode)]); - elseif keyCode == p.keys.confirm - WaitSecs(0.1); - ok = 0; - end - end - end - %% - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.imrect ); - Screen('Flip',p.ptb.w); - ShowInstruction(14,0,10); - p.out.selectedface = p.stim.circle_order(positions(1)); - end - function DrawCircle - for npos = 1:p.stim.tFace - Screen('DrawTexture', p.ptb.w, p.ptb.stim_sprites(p.stim.circle_file_id(npos)),[],p.stim.circle_rect(npos,:)); - %Screen('DrawText', p.ptb.w, sprintf('%i_%i_%i',p.stim.circle_order(npos),p.stim.circle_file_id(npos),npos),mean(p.stim.circle_rect(npos,[1 3])) ,mean(p.stim.circle_rect(npos,[2 4]))); - end - end - - function [myrect]=angle2rect(A) - factor = 1.9;%factor resize the images - [x y] = pol2cart(A./180*pi,280);%randomly shift the circle - left = x+p.ptb.midpoint(1)-p.stim.width/2/factor; - top = y+p.ptb.midpoint(2)-p.stim.height/2/factor; - right = left+p.stim.width/factor; - bottom = top+p.stim.height/factor; - myrect = [left top right bottom]; - end - - function AskDetection - % - p.var.ExpPhase = 3; - ShowInstruction(801,1); - %% show a fixation cross - fix = [p.ptb.CrossPosition_x p.ptb.CrossPosition_y(1)];%show the fixation cross at the lip position to ease the subsequent drift correction. - FixCross = [fix(1)-1,fix(2)-p.ptb.fc_size,fix(1)+1,fix(2)+p.ptb.fc_size;fix(1)-p.ptb.fc_size,fix(2)-1,fix(1)+p.ptb.fc_size,fix(2)+1]; - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.imrect ); %always create a gray background - Screen('FillRect', p.ptb.w, [255,255,255], FixCross');%draw the prestimus cross atop - - Screen('DrawingFinished',p.ptb.w,0); - Screen('Flip',p.ptb.w); - StartEyelinkRecording(1,0,p.var.ExpPhase,0,0,0,fix,0); - WaitSecs(1.5); - %% - DrawCircle; - %Stimulus onset - Screen('Flip',p.ptb.w); - if EyelinkWanted - Eyelink('Message', 'Stim Onset'); - Eyelink('Message', 'SYNCTIME'); - end - %% - WaitSecs(30); - Screen('Flip',p.ptb.w); - if EyelinkWanted - Eyelink('Message', 'Stim Offset'); - Eyelink('Message', 'BLANK_SCREEN'); - end - StopEyelinkRecording; - end - - function ConfirmIntensity - %Compute the intensity we want to deliver to the subject. - p.var.ShockIntensity = p.out.PainThreshold*p.out.ShockFactor; - % - ShowInstruction(9,1); - % - fprintf([repmat('=',1,50) '\n']); - fprintf('TEST SHOCK:\n'); - fprintf('!!! ADJUST THE SHOCK INTENSITY ON THE DIGITIMER !!!\n'); - fprintf(' The intensity is now: %g mA\n',p.var.ShockIntensity); - fprintf(' Experimenter: Press any key to deliver a shock.\n'); - fprintf([repmat('=',1,50) '\n']); - % - [secs, keyCode, deltaSecs] = KbStrokeWait(p.ptb.device); - ShowInstruction(10,0,1+rand(1));%shock is coming message... - t = GetSecs + p.duration.shock; - while GetSecs < t; - Buzz; - end - % - message = 'Bewege den "Zeiger" mit der rechten und linken Pfeiltaste\n und best�tige deine Einsch�tzung mit der mit der oberen Pfeiltaste.'; - rect = [p.ptb.width*0.2 p.ptb.midpoint(2) p.ptb.width*0.6 100]; - response = RatingSlider(rect,2,1,p.keys.increase,p.keys.decrease,p.keys.confirm,{ 'nicht\nertr�glich' 'ertr�glich'},message,0); - if response == 2 - fprintf('All is fine :)\n'); - fprintf('Subject confirmed the shock intensity inside the scanner...\n'); - fprintf('INTENSITY TO BE USED FOR THE MAIN EXPERIMENT: %g mA\n',p.var.ShockIntensity); - p.out.ShockIntensity = p.var.ShockIntensity; - return; - elseif response == 1 - fprintf('Shit... :(, %g is too much for the subject\n',p.var.ShockIntensity); - fprintf('We will try a little milder intensity.\n'); - p.out.ShockFactor = p.out.ShockFactor - 0.05; - ConfirmIntensity; - end - - - end - function PresentStimuli - %Enter the presentation loop and wait for the first pulse to - %arrive. - %wait for the dummy scans - [secs] = WaitPulse(p.keys.pulse,p.mrt.dummy_scan);%will log it - KbQueueStop(p.ptb.device); - WaitSecs(.05); - KbQueueCreate(p.ptb.device); - KbQueueStart(p.ptb.device);%this means that from now on we are going to log pulses. - %If the scanner by mistake had been started prior to this point - %those pulses would have been not logged. - %log the pulse timings. - mblock_jumps = logical([1 diff(p.presentation.mblock)]); - TimeEndStim = secs(end)- p.ptb.slack;%take the first valid pulse as the end of the last stimulus. - for nTrial = 1:p.presentation.tTrial; - - %Get the variables that Trial function needs. - stim_id = p.presentation.stim_id(nTrial); - fix_y = p.presentation.cross_position(nTrial); - ISI = (p.presentation.isi(nTrial)+1)*2; - ucs = p.presentation.ucs(nTrial); - oddball = p.presentation.oddball(nTrial); - prestimdur = p.duration.prestim+rand(1)*.25; - dist = p.presentation.dist(nTrial); - mblock_jump = mblock_jumps(nTrial); - block_id = p.presentation.mblock(nTrial); - %prestimdur = p_presentation_prestim_dur(nTrial); - % - OnsetTime = TimeEndStim + ISI-p.duration.stim - p.ptb.slack; - fprintf('%03d of %03d, S: %d, ISI: %d, UCS: %d, ODD: %d, OnsetTime: %f secs, ',nTrial,p.presentation.tTrial,stim_id,ISI,ucs,oddball, OnsetTime); - - %Start with the trial, here is time-wise sensitive must be - %optimal - [TimeEndStim] = Trial(nTrial,OnsetTime, prestimdur, stim_id , ucs , fix_y, oddball,dist,mblock_jump,block_id); - %(nTrial,TimeStimOnset , prestimdur, stim_id , ucs , fix_i, oddball, dist ) - fprintf('OffsetTime: %f secs, Difference of %f secs\n',TimeEndStim,TimeEndStim-OnsetTime-p.duration.stim); - % - %dump it - [keycode, secs] = KbQueueDump;%this contains both the pulses and keypresses. - %log everything but "pulse keys" as pulses, not as keypresses. - pulses = (keycode == p.keys.pulse); - if any(~pulses);%log keys presses if only there is one - Log(secs(~pulses),7,keycode(~pulses)); - end - if any(pulses);%log pulses if only there is one - Log(secs(pulses),0,keycode(pulses)); - end - %now we have to detect if the subject has pressed the CONFIRM - %key while the ODDBALL stimulus was on the screen. - if any((keycode == p.keys.confirm) & (secs > OnsetTime) & (secs <= TimeEndStim)) - p.out.response(nTrial) = 1; - fprintf('Subject Pressed the Hit Key!!\n'); - end - end - %wait 6 seconds for the BOLD signal to come back to the baseline... - KbQueueStop(p.ptb.device); - KbQueueRelease(p.ptb.device); - - if p.var.ExpPhase > 0 - WaitPulse(p.keys.pulse,p.mrt.dummy_scan);% - fprintf('OK!! Stop the Scanner\n'); - end - %dump the final events - [keycode, secs] = KbQueueDump;%this contains both the pulses and keypresses. - %log everything but "pulse keys" as pulses, not as keypresses. - pulses = (keycode == p.keys.pulse); - if any(~pulses);%log keys presses if only there is one - Log(secs(~pulses),7,keycode(~pulses)); - end - if any(pulses);%log pulses if only there is one - Log(secs(pulses),0,keycode(pulses)); - end - %stop the queue - KbQueueStop(p.ptb.device); - KbQueueRelease(p.ptb.device); - WaitSecs(10); - end - function [TimeEndStim]=Trial(nTrial,TimeStimOnset , prestimdur, stim_id , ucs , fix_i, oddball, dist,microblock_jump,mblock_id) - %get all the times - TimeCrossOnset = TimeStimOnset - prestimdur; - TimeCrossJump = TimeStimOnset + p.duration.stim/2; - TimeEndStim = TimeStimOnset + p.duration.stim- p.ptb.slack; - TimeStartShock = TimeStimOnset + p.duration.onset2shock; - TimeTrackerOff = TimeStimOnset + p.duration.keep_recording; - - %% Fixation Onset - fix = [p.ptb.CrossPosition_x p.ptb.CrossPosition_y(fix_i)]; - FixCross = [fix(1)-1,fix(2)-p.ptb.fc_size,fix(1)+1,fix(2)+p.ptb.fc_size;fix(1)-p.ptb.fc_size,fix(2)-1,fix(1)+p.ptb.fc_size,fix(2)+1]; - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.imrect ); %always create a gray background - Screen('FillRect', p.ptb.w, [255,255,255], FixCross');%draw the prestimus cross atop - Screen('DrawingFinished',p.ptb.w,0); - TimeCrossOn = Screen('Flip',p.ptb.w,TimeCrossOnset,0); - Log(TimeCrossOn,1,fix_i);%cross onset. - %turn the eye tracker on - StartEyelinkRecording(nTrial,stim_id,p.var.ExpPhase,dist,oddball,ucs,fix,mblock_id);%I would be cautious here, the first trial is never recorded in the EDF file, reason yet unknown. - %% Draw the stimulus to the buffer - if ~stim_id==0 - Screen('DrawTexture', p.ptb.w, p.ptb.stim_sprites(stim_id)); - end - %draw also the fixation cross - Screen('FillRect', p.ptb.w, [255,255,255], FixCross'); - %add freckles to the face if oddball - if oddball - x = randn(1,100)*35; - y = randn(1,100)*10; - s = rand(1,100);%[0 1] - Screen('DrawDots',p.ptb.w,[x;y],1+s.*1.5,[180 0 0 160],p.ptb.midpoint,1); - end - Screen('DrawingFinished',p.ptb.w,0); - %% STIMULUS ONSET - TimeStimOnset = Screen('Flip',p.ptb.w,TimeStimOnset,0);%asap and dont clear - %send eyelink and ced a marker asap - if EyelinkWanted - Eyelink('Message', 'Stim Onset'); - Eyelink('Message', 'SYNCTIME'); - end - MarkCED( p.com.lpt.address, p.com.lpt.StimOnset );%this actually didn't really work nicely. - %the first stim onset pulse is always missing. This could be due to - %the fact that the state of the port was already 1 and thus CED - %didn't realize this command. - if oddball - MarkCED( p.com.lpt.address, p.com.lpt.oddball ); - end - if ucs - MarkCED(p.com.lpt.address, p.com.lpt.ucs); - end - if microblock_jump - MarkCED( p.com.lpt.address, p.com.lpt.mBlock ); - Log(TimeStimOnset,9,mblock_id) - end - Log(TimeStimOnset,3,dist);%log the stimulus onset - - %% CROSS JUMPS (same as before but with a different fix position) - if ~stim_id==0 - Screen('DrawTexture', p.ptb.w, p.ptb.stim_sprites(stim_id)); - end - if oddball - Screen('DrawDots',p.ptb.w,[x;y],1+s.*1.5,[180 0 0 160],p.ptb.midpoint,1); - end - fix = [p.ptb.CrossPosition_x p.ptb.CrossPosition_y(setdiff(1:2,fix_i))];%take the other position - %draw also the fixation cross - FixCross = [fix(1)-1,fix(2)-p.ptb.fc_size,fix(1)+1,fix(2)+p.ptb.fc_size;fix(1)-p.ptb.fc_size,fix(2)-1,fix(1)+p.ptb.fc_size,fix(2)+1]; - Screen('FillRect', p.ptb.w, [255,255,255], FixCross'); - Screen('DrawingFinished',p.ptb.w,0); - TimeCrossJump = Screen('Flip',p.ptb.w,TimeCrossJump,0);%asap and dont clear - Log(TimeCrossJump,4,0);%log the stimulus onset - %% - if ucs == 1 - %%%%%%%%%%%%%%%%%%%%%%% - %Deliver shock and stim off immediately - TimeStartShock = WaitSecs('UntilTime',TimeStartShock); - if EyelinkWanted - Eyelink('Message', 'UCS Onset'); - end - - while GetSecs < TimeEndStim; - Buzz;%this is anyway sent to CED. - end - end - - %% STIM OFF immediately - TimeEndStim = Screen('Flip',p.ptb.w,TimeEndStim,0); - %send eyelink and ced a marker - Log(TimeEndStim,6,stim_id);%log the stimulus offset - % - %% record some more eye data after stimulus offset. - WaitSecs('UntilTime',TimeTrackerOff); - if EyelinkWanted - Eyelink('Message', 'Stim Offset'); - Eyelink('Message', 'BLANK_SCREEN'); - end - TimeTrackerOff = StopEyelinkRecording; - - - if oddball == 1 - fprintf('This was an oddball trial!'); - end - if ucs == 1 - fprintf('This was a UCS trial!'); - Log(TimeStartShock,5,NaN);%UCS delivery...This is done here to not waste time there - end - - end - - function SetParams - - %mrt business - p.mrt.dummy_scan = 0;%this will wait until the 6th image is acquired. - p.mrt.LastScans = 0;%number of scans after the offset of the last stimulus - p.mrt.tr = 2;%in seconds. - %will count the number of events to be logged - p.var.event_count = 0; - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %% relative path to stim and experiments - %Path Business. - [~, hostname] = system('hostname'); - p.hostname = deblank(hostname); - p.path.baselocation = 'C:\Users\...\Documents\Experiments\FearGen'; - %create the base folder if not yet there. - if exist(p.path.baselocation) == 0 - mkdir(p.path.baselocation); - end - - p.path.experiment = [p.path.baselocation filesep]; - p.path.stim = [fileparts(which('exp_FearGen_ForAll.m')) filesep 'bin' filesep 'FearGen_Stimuli' filesep]; - p.path.stim24 = [p.path.stim '24bit' filesep];%location of 24bit stimuli, useful only to send it to the eyelink system - p.path.stim_cut = [p.path.stim 'cut' filesep];%stimuli without borders, necessary for the facecircle - % - p.subID = sprintf('s%02d',subject);%subject id - timestamp = datestr(now,30);%the time_stamp of the current experiment. - p.path.subject = [p.path.experiment 'tmp' filesep p.subID '_' timestamp filesep ];%subject folder, first we save it to the temp folder. - p.path.finalsubject = [p.path.experiment p.subID '_' timestamp filesep ];%final location of the subject folder - p.path.path_edf = [p.path.subject 'eye' filesep];%location of the edf file in the eyelink computer - p.path.edf = sprintf([p.subID 'p%02d.edf' ],phase);%EDF file in the stimulus computer - p.path.path_param = [p.path.subject 'stimulation' filesep 'data.mat'];%location of the paradigm file. - %create folder hierarchy for this subject - mkdir(p.path.subject); - mkdir([p.path.subject 'scr']);%location for the SCR data - mkdir([p.path.subject 'eye']);%location for the edf file and eye-movement related data. - mkdir([p.path.subject 'stimulation']);%location of the stimulus presentation paradigm - mkdir([p.path.subject 'midlevel']);%other data. - %% %%%%%%%%%%%%%%%%%%%%%%%%% - %get stim files - [p.stim.files p.stim.label] = FileMatrix([p.path.stim '*.bmp']);%read in the stimlus - p.stim.tFile = size(p.stim.files,1);%number of different files (including the UCS symbol) - p.stim.tFace = 8;%number of faces. - % - display([mat2str(p.stim.tFile) ' found in the destination.']); - %set the background gray according to the background of the stimuli - for i = 1:p.stim.tFace; - im = imread(p.stim.files(i,:)); - bg(i) = im(1,1,1); - end - %is all the captured bg values the same? - if sum(diff(bg))==0; - %if so take it as the bg color - p.stim.bg = double([bg(1) bg(1) bg(1)]); - else - fprintf('background luminance was not successfully detected...\n') - keyboard; - end - %bg of the rating screen. - p.stim.bg_rating = p.stim.bg; - p.stim.white = [255 255 255]; - %% font size and background gray level - p.text.fontname = 'Times New Roman'; - p.text.fontsize = 18;%30; - p.text.fixsize = 60; - %rating business, how many ticks - p.rating.division = 10;%number of divisions for the rating slider - p.rating.repetition = 2;%how many times a given face has to be repeated... - %% get the actual stim size (assumes all the same) - info = imfinfo(p.stim.files(1,:)); - p.stim.width = info.Width; - p.stim.height = info.Height; - %% keys to be used during the experiment: - %This part is highly specific for your system and recording setup, - %please enter the correct key identifiers. You can get this information calling the - %KbName function and replacing the code below for the key below. - %1, 6 ==> Right - %2, 7 ==> Left - %3, 8 ==> Down - %4, 9 ==> Up (confirm) - %5 ==> Pulse from the scanner - KbName('UnifyKeyNames'); - p.keys.confirm = KbName('4$');% - p.keys.increase = KbName('1!'); - p.keys.decrease = KbName('3#'); - p.keys.pulse = KbName('5%'); - p.keys.el_calib = KbName('v'); - p.keys.el_valid = KbName('c'); - p.keys.escape = KbName('esc'); - p.keys.enter = KbName('return'); - - %% %%%%%%%%%%%%%%%%%%%%%%%%% - %Communication business - %parallel port - p.com.lpt.address = 888;%parallel port of the computer. - %codes for different events that are sent for logging in the - %physiological computer. - p.com.lpt.digitimer = 12;%8 - p.com.lpt.mBlock = 128; - p.com.lpt.StimOnset = 64; - p.com.lpt.oddball = 32; - p.com.lpt.ucs = 16; - - % - %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %timing business - %these are the intervals of importance - %time2fixationcross->cross2onset->onset2shock->shock2offset - %these (duration.BLA) are average duration values: - p.duration.stim = 1.5;%2;%s - p.duration.shock = 0.1;%s;x - p.duration.shockpulse = 0.005;%ms; duration of each individual pulses - p.duration.intershockpulse = 0.01;%ms; and the time between each pulse - p.duration.onset2shock = p.duration.stim - p.duration.shock; - p.duration.crossmoves = p.duration.stim./2; - p.duration.keep_recording = 0.25;%this is the time we will keep recording (eye data) after stim offset. - p.duration.prestim = .85; - %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %stimulus sequence: Explanation of the fields: - s = load([fileparts(which('exp_FearGen_ForAll.m')) filesep 'bin' filesep 'feargen_seq.mat']); - s = s.s; - %Explanation of the fields: - %.cond_id => Condition id, this is the face to be loaded. 1-8: face id, 9 => oddball, 10 => UCS. - %.UCS => 1 if it is UCS trial, otherwise 0 - %.oddball => 1 if it is an oddball trial - %.stim_id => same as cond_id, except for UCS stimuli, where the stim_id is the CS+. This is basically the index of the file that is gonna be read. - %.dist => The angular distance to CS+ face, this is the most important field for analysis - %.cross_position => the position of the cross to be shown, could start from mouth and jump to eyes or vice versa. The exact position is computed in SetPTB. - %.mblcok => irrelevant for this experiment. - %this will deal all the presentation sequence related information - p.presentation = s(Nseq,csp).phase(phase).presentation; - p.presentation.tTrial = length(p.presentation.cond_id);%Total Trials - p.presentation.mblock = ones(1,p.presentation.tTrial);%irrelevant for the FearGen experiment but keeping it. - p.presentation.dist = MinimumAngle((p.presentation.stim_id-1)*45,(csp-1)*45);%infer distances to CS+ - %distances are only defined for the face conditions, for example - %UCS, oddball and null trials do not have that. - p.presentation.dist(p.presentation.cond_id == 9) = 1001; - p.presentation.dist(p.presentation.cond_id == 10) = 1002; - clear s; - %% create the randomized design - p.stim.cs_plus = csp;%index of cs stimulus, this is the one paired to shock - p.stim.cs_neg = csn; - %Record which Phase are we going to run in this run. - p.stim.phase = phase; - p.out.rating = [];%will contain explicite ratings of UCS likelihood - p.out.log = zeros(1000000,4).*NaN;%Experimental LOG. - p.out.response = zeros(p.presentation.tTrial,1);% - p.out.PainThreshold = PainThreshold;%the pain threshold (i.e. pain intensity where p(painful) = .5 for the subject, it is an input argument, must be computed before the experiment. - p.out.ShockFactor = 2;%factor to multiply the PainThreshold with, will use this factor to propose the experimenter the final shock intensity to be used during the FearGen Experiment. - %% - p.var.current_bg = p.stim.bg;%current background to be used. - %Save the stuff - save(p.path.path_param,'p'); - % - function [FM labels] = FileMatrix(path) - %Takes a path with file extension associated to regexp (e.g. - %C:\blabl\bla\*.bmp) returns the file matrix - dummy = dir(path); - FM = [repmat([fileparts(path) filesep],length(dummy),1) vertcat(dummy(:).name)]; - labels = {dummy(:).name}; - end - end - function AskStimRating - - - p.var.ExpPhase = 5; - p.var.current_bg = p.stim.bg_rating; - %% create the order of presentation and balance the position of fixation cross - nseq = 0; - rating_seq = []; - pos1_seq = []; - idx = []; - face_order = 1:p.stim.tFace; - while nseq < p.rating.repetition - nseq = nseq + 1; - [dummy idx] = Shuffle( face_order ); - rating_seq = [rating_seq dummy]; - %this balances both directions - pos1_seq = [pos1_seq ones(1,p.stim.tFace)];%+1 to make [0 1] --> [1 2] - end - rating_seq = rating_seq(:); - pos1_seq = pos1_seq(:); - %% - message = GetText(11); - SliderTextL = GetText(13); - SliderTextR = GetText(12); - % set the background to different color - Screen('FillRect', p.ptb.w , p.var.current_bg ); - Screen('Flip',p.ptb.w); - WaitSecs(2); - % - ShowInstruction(7,1); - rect = [p.ptb.width*0.2 p.ptb.midpoint(2) p.ptb.width*0.6 100];%for the rating slider - tRatend = length(rating_seq); - %save the rating sequence just for security - p.out.rating_seq = rating_seq; - p.out.pos1_seq = pos1_seq; - - %run over all the pictures to be rated. - for nRatend = 1:tRatend; - % - %the variable that are used by Trial function - stim_id = rating_seq(nRatend); - fix_y = pos1_seq(nRatend); - % - next_stim_id = [];%this is a trick, otherwise a fixation cross appears right before the rating :( - next_pos1 = []; - % - %to send know the distance here, little dummy setup: - dummy = -135:45:180; - dist = dummy(stim_id); - % show the picture - %Trial(nTrial ,TimeStimOnset , prestimdur, stim_id , ucs , fix_i, oddball, dist,microblock_jump,mblock_id) - Trial(1000+nRatend,GetSecs+1,p.duration.prestim,stim_id,0,fix_y,0,dist,0,0); - % show the slider - rate(nRatend,1) = RatingSlider(rect, p.rating.division, Shuffle(1:p.rating.division,1), p.keys.increase, p.keys.decrease, p.keys.confirm, {SliderTextL{1} SliderTextR{1}},message,1); - - %%%%%%%%%%%%%%%%%%%%%%%%%%%% - %Verbose the rating of the subject - fprintf('============\nRating Results %d (%d/%d):\n', stim_id, nRatend, tRatend); - dummy = rating_seq(1:nRatend);%trials shown so far - for iii = 1:p.stim.tFace - r = round(mean(rate(dummy == iii))); - if isnan(r) - r = 0; - end - if iii == p.stim.cs_plus - fprintf('Stimulus %02d: * %s \n',iii,repmat('+',1,1+r)); - else - fprintf('Stimulus %02d: %s \n',iii,repmat('+',1,1+r)); - end - end - end - %sort the stim_ids and then sort the same the rates and make a - %matrix out of that to store - [~, i] = sort(rating_seq); - rate = reshape(rate(i),p.rating.repetition,p.stim.tFace)'; - p.out.rating = rate; - save(p.path.path_param,'p'); - Screen('FillRect',p.ptb.w,p.var.current_bg); - % - save(p.path.path_param,'p'); - end - function [rating] = RatingSlider(rect,tSection,position,up,down,confirm,labels,message,numbersOn) - % - %Detect the bounding boxes of the labels. - for nlab = 1:2 - [~ , ~, bb(nlab,:)]=DrawFormattedText(p.ptb.w,labels{nlab}, 'center', 'center', p.stim.white,[],[],[],2); - Screen('FillRect',p.ptb.w,p.var.current_bg); - end - bb = max(bb); - bb_size = bb(3)-bb(1);%vertical size of the bb. - % - DrawSkala; - ok = 1; - while ok == 1 - - [secs, keyCode, ~] = KbStrokeWait(p.ptb.device); - keyCode = find(keyCode); - Log(secs,7,keyCode); - if length(keyCode) == 1%this loop avoids crashes to accidential presses of meta keys - if (keyCode == up) || (keyCode == down) - next = position + increment(keyCode); - if next < (tSection+1) && next > 0 - position = position + increment(keyCode); - end - DrawSkala; - elseif keyCode == confirm - WaitSecs(0.1); - ok = 0; - Screen('FillRect',p.ptb.w,p.var.current_bg); - t=Screen('Flip',p.ptb.w); - end - end - end - - function DrawSkala - %rating = tSection - position + 1; - rating = position ; - increment([up down]) = [1 -1];%delta - tick_x = linspace(rect(1),rect(1)+rect(3),tSection+1);%tick positions - tick_size = rect(3)./tSection; - ss = tick_size/5*0.9;%slider size. - % - for tick = 1:length(tick_x)%draw ticks - Screen('DrawLine', p.ptb.w, [255 0 0], tick_x(tick), rect(2), tick_x(tick), rect(2)+rect(4) , 3); - if tick <= tSection && numbersOn - Screen('TextSize', p.ptb.w,p.text.fontsize); - DrawFormattedText(p.ptb.w, mat2str(tick) , tick_x(tick)+ss/2, rect(2)+rect(4), p.stim.white); - Screen('TextSize', p.ptb.w,p.text.fontsize); - end - if tick == 1 - DrawFormattedText(p.ptb.w, labels{1},tick_x(tick)-bb_size*1.4,rect(2), p.stim.white); - elseif tick == tSection+1 - DrawFormattedText(p.ptb.w, labels{2},tick_x(tick)+bb_size*0.4,rect(2), p.stim.white); - end - end - %slider coordinates - slider = [ tick_x(position)+tick_size*0.1 rect(2) tick_x(position)+tick_size*0.9 rect(2)+rect(4)]; - %draw the slider - Screen('FillRect',p.ptb.w, p.stim.white, round(slider)); - Screen('TextSize', p.ptb.w,p.text.fontsize); - DrawFormattedText(p.ptb.w,message, 'center', p.ptb.midpoint(2)*0.2, p.stim.white,[],[],[],2); - Screen('TextSize', p.ptb.w,p.text.fontsize); - t = Screen('Flip',p.ptb.w); - Log(t,-2,NaN); - end - end - function ShowInstruction(nInstruct,waitforkeypress,varargin) - %ShowInstruction(nInstruct,waitforkeypress) - %if waitforkeypress is 1, ==> subject presses a button to proceed - %if waitforkeypress is 0, ==> text is shown for VARARGIN seconds. - - - [text]= GetText(nInstruct); - ShowText(text); - if waitforkeypress %and blank the screen as soon as the key is pressed - KbStrokeWait(p.ptb.device); - else - WaitSecs(varargin{1}); - end - Screen('FillRect',p.ptb.w,p.var.current_bg); - t = Screen('Flip',p.ptb.w); - - function ShowText(text) - - Screen('FillRect',p.ptb.w,p.var.current_bg); - DrawFormattedText(p.ptb.w, text, 'center', 'center',p.stim.white,[],[],[],2,[]); - t=Screen('Flip',p.ptb.w); - Log(t,-1,nInstruct); - %show the messages at the experimenter screen - fprintf('=========================================================\n'); - fprintf('Text shown to the subject:\n'); - fprintf(text); - fprintf('=========================================================\n'); - - end - end - function [text]=GetText(nInstruct) - if nInstruct == 0%Eyetracking calibration - - text = ['Wir kalibrieren jetzt den Eye-Tracker.\n\n' ... - 'Bitte fixieren Sie die nun folgenden wei�en Kreise und \n' ... - 'bleiben so lange darauf, wie sie zu sehen sind.\n\n' ... - 'Nach der Kalibrierung d�rfen Sie Ihren Kopf nicht mehr bewegen.\n'... - 'Sollten Sie Ihre Position noch ver�ndern m�ssen, tun Sie dies jetzt.\n'... - 'Die beste Position ist meist die bequemste.\n\n'... - 'Bitte dr�cken Sie jetzt den oberen Knopf, \n' ... - 'um mit der Kalibrierung weiterzumachen.\n' ... - ]; - - elseif nInstruct == 1%first Instr. of the training phase. - text = ['Wir werden nun als erstes einen �bungsdurchgang machen,\n' ... - 'damit Sie sich an Ihre Aufgabe gew�hnen k�nnen.\n' ... - 'In diesem Durchgang k�nnen Sie sich vollkommen sicher f�hlen,\n' ... - 'es werden keine elektrischen Reize verabreicht.\n' ... - 'Eine wichtige grunds�tzliche Regel ist, dass Sie das Fixationskreuz (das +)\n' ... - 'wenn es zu sehen ist, mit Ihren Augen fixieren. \n' ... - '\n'... - 'Dr�cken Sie die obere Taste um fortzufahren.\n' ... - ]; - elseif nInstruct == 2%second Instr. of the training phase. - text = ['Ein paar Bemerkungen zu den Zielreizen: \n' ... - 'Zur Erinnerung: Zielreize sind die verschwommenen Gesichter.\n' ... - 'Sobald ein solcher Zielreiz erscheint, \n' ... - 'sollen Sie schnellstm�glich die obere Taste dr�cken, \n' ... - 'und zwar bevor der Zielreiz wieder verschwunden ist \n' ... - '(Sie m�ssen also sehr schnell und aufmerksam sein).\n\n' ... - 'Dr�cken Sie die obere Taste um fortzufahren.\n' ... - ]; - elseif nInstruct == 299%short instruction before localizer - text = ['Die Kalibrierung war erfolgreich.\n'... - 'Es startet nun eine kurze Vormessung (~2 min), w�hrend der Sie nichts tun m�ssen.\n\n'... - ]; - elseif nInstruct == 3%third Instr. of the training phase. - text = ['Wir sind jetzt kurz vor Beginn des Experiments.\n'... - 'Wir m�chten Sie nun noch einmal an die wichtigsten Punkte erinnern.\n\n'... - 'Dr�cken Sie jeweils die obere Taste um fortzufahren.\n' ... - ]; - elseif nInstruct == 301%third Instr. of the training phase. - text = ['1/ Folgen Sie immer streng den Fixationskreuzen.\n'... - ]; - elseif nInstruct == 302%third Instr. of the training phase. - text = ['2/ Dr�cken Sie die Taste, sobald Sie den Zielreiz entdecken.\n'... - ]; - elseif nInstruct == 303%third Instr. of the training phase. - text = ['3/ Bewegen Sie sich nicht.\n'... - ]; - elseif nInstruct == 304%third Instr. of the training phase. - text = ['4/ Lassen Sie sich vom Scannergeschehen nicht st�ren.\n'... - ]; - elseif nInstruct == 305%third Instr. of the training phase. - text = ['5/ Nur eines der Gesichter wird mit elektrischen Reizen gepaart.\n'... - ]; - elseif nInstruct == 306%third Instr. of the training phase. - text = ['Dr�cken Sie jetzt die obere Taste, das Experiment startet dann in wenigen Sekunden.\n' ... - ]; - - - elseif nInstruct == 4%third Instr. of the training phase. - text = ['Vor dem Experiment legen wir nun \n' ... - 'die Schockintensit�t f�r den Rest des Experiments fest. \n' ... - 'Dr�cken Sie die obere Taste um fortzufahren.\n' ... - ]; - - elseif nInstruct == 7;%rating - text = ['In dieser Phase h�tten wir gerne, dass Sie die Gesichter\n'... - 'im Hinblick auf folgende Frage bewerten:\n'... - '"Wie wahrscheinlich ist es, bei dem gerade gesehenen Gesicht \n'... - 'einen elektrischen Schock zu erhalten?"\n'... - 'Bewegen Sie den Zeiger mit der rechten und linken Taste\n'... - 'und best�tigen Sie Ihre Einsch�tzung mit der oberen Taste.\n'... - ]; - elseif nInstruct == 8;%AskDetectionSelectable - text = ['Sie sehen nun noch einmal eine �bersicht der verschiedenen Gesichter.\n'... - 'Bitte geben Sie an, welches der Gesichter Ihrer Meinung nach\n mit dem Schock gepaart wurde.\n\n'... - 'Nutzen Sie die linke und rechte Taste, um die Markierung\n zum richtigen Gesicht zu navigieren,\n'... - 'und dr�cken Sie die obere Taste zum Best�tigen.\n\n'... - 'Bitte zum Starten die obere Taste dr�cken.\n'... - ]; - elseif nInstruct == 801;%AskDetectionSelectable - text = ['Sie sehen nun eine �bersicht der verschiedenen Gesichter.\n'... - 'Bitte schauen Sie sich die Gesichter aufmerksam an.\n'... - 'Bitte dr�cken Sie zum Start die obere Taste und\n' ... - 'fixieren Sie das anschlie�end erscheinende Fixationskreuz.\n'... - ]; - - elseif nInstruct == 9% - %=================================================================================================================% - text = ['Bitte geben Sie an, ob die Reizst�rke des folgenden Schocks\n f�r Sie ertr�glich ist.\n'... - '\n'... - 'Dr�cken Sie bitte die obere Taste um den Reiz zu bekommen.\n'... - ]; - - elseif nInstruct == 10%just before the shock - text = ['Reiz kommt...\n']; - elseif nInstruct == 11%this is the rating question - text = ['Wie wahrscheinlich ist es, bei dem gerade gesehenen Gesicht \n'... - 'einen elektrischen Schock zu erhalten?\n' ... - 'Bewegen Sie den "Zeiger" mit der rechten und linken Taste\n' ... - 'und best�tigen Sie Ihre Einsch�tzung mit der mit der oberen Taste'... - ]; - elseif nInstruct == 12 %These two below are the possible responses to the question in 11 - text = {'Sehr\nwahrscheinlich'}; - elseif nInstruct == 13 - text = {'�berhaupt\nnicht\nwahrscheinlich'}; - elseif nInstruct == 14 - text = ['Danke. Den aktiven Teil des Experiment haben Sie nun geschafft.\n'... - 'Es folgt nun noch eine strukturelle Messung, die ca. 7 Minuten dauert.\n'... - 'Sie k�nnen dabei ruhig die Augen schlie�en und sich entspannen.\n']; - else - text = {''}; - end - end - function SetPTB - %Sets the parameters related to the PTB toolbox. Including - %fontsizes, font names. - %Default parameters - Screen('Preference', 'SkipSyncTests', 1); - Screen('Preference', 'DefaultFontSize', p.text.fontsize); - Screen('Preference', 'DefaultFontName', p.text.fontname); - Screen('Preference', 'TextAntiAliasing',2);%enable textantialiasing high quality - Screen('Preference', 'VisualDebuglevel', 0); - Screen('Preference', 'SkipSyncTests', 1); - Screen('Preference', 'SuppressAllWarnings', 1); - %%Find the number of the screen to be opened - screens = Screen('Screens'); - p.ptb.screenNumber = max(screens);%the maximum is the second monitor - %Make everything transparent for debugging purposes. - if debug - commandwindow; - PsychDebugWindowConfiguration; - end - %set the resolution correctly - res = Screen('resolution',p.ptb.screenNumber); - HideCursor(p.ptb.screenNumber);%make sure that the mouse is not shown at the participant's monitor - %spit out the resolution, - fprintf('Resolution of the screen is %dx%d...\n',res.width,res.height); - - %Open a graphics window using PTB - [p.ptb.w p.ptb.rect] = Screen('OpenWindow', p.ptb.screenNumber, p.var.current_bg); - %Screen('BlendFunction', p.ptb.w, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - Screen('Flip',p.ptb.w);%make the bg - p.ptb.slack = Screen('GetFlipInterval',p.ptb.w)./2; - [p.ptb.width, p.ptb.height] = Screen('WindowSize', p.ptb.screenNumber); - - %find the mid position on the screen. - p.ptb.midpoint = [ p.ptb.width./2 p.ptb.height./2]; - %NOTE about RECT: - %RectLeft=1, RectTop=2, RectRight=3, RectBottom=4. - p.ptb.imrect = [ p.ptb.midpoint(1)-p.stim.width/2 p.ptb.midpoint(2)-p.stim.height/2 p.ptb.midpoint(1)-p.stim.width/2+p.stim.width p.ptb.midpoint(2)-p.stim.height/2+p.stim.height]; - p.ptb.cross_shift = [180 -120]./2.5;%incremental upper and lower cross positions - p.ptb.CrossPosition_x = p.ptb.midpoint(1);%bb(1);%always the same - p.ptb.CrossPosition_y = p.ptb.midpoint(2)+p.ptb.cross_shift;%bb(1);%always the same - %cross position for the eyetracker screen. - p.ptb.CrossPositionET_x = [p.ptb.midpoint(1) p.ptb.midpoint(1)]; - p.ptb.CrossPositionET_y = [p.ptb.midpoint(2)-p.ptb.cross_shift(2) p.ptb.midpoint(2)+p.ptb.cross_shift(2)]; - p.ptb.fc_size = 10; - % - %% - %priorityLevel=MaxPriority(['GetSecs'],['KbCheck'],['KbWait'],['GetClicks']); - Priority(MaxPriority(p.ptb.w)); - %this is necessary for the Eyelink calibration - %InitializePsychSound(0) - %sound('Open') - % Beeper(1000) - if IsWindows - LoadPsychHID; - end - %%%%%%%%%%%%%%%%%%%%%%%%%%%Prepare the keypress queue listening. - p.ptb.device = []; - %get all the required keys in a vector - p.ptb.keysOfInterest = [];for i = fields(p.keys)';p.ptb.keysOfInterest = [p.ptb.keysOfInterest p.keys.(i{1})];end - fprintf('Key listening will be restricted to %d\n',p.ptb.keysOfInterest) - RestrictKeysForKbCheck(p.ptb.keysOfInterest); - p.ptb.keysOfInterest=zeros(1,256); - p.ptb.keysOfInterest(p.keys.confirm) = 1; - %create a queue sensitive to only relevant keys. - % KbQueueCreate(p.ptb.device,p.ptb.keysOfInterest);%default device. - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %prepare parallel port communication. This relies on cogent i - %think. We could do it with PTB as well. - if IsWindows - config_io; - outp(p.com.lpt.address,0); - if( cogent.io.status ~= 0 ) - error('inp/outp installation failed'); - end - end - - - %% %%%%%%%%%%%%%%%%%%%%%%%%% - %Make final reminders to the experimenter to avoid false starts, - %which are annoying. Here I specifically send test pulses to the - %physio computer and check if everything OK. - k = 0; - while ~(k == p.keys.el_calib);%press V to continue - pause(0.1); - outp(p.com.lpt.address,244);%244 means all but the UCS channel (so that we dont shock the subject during initialization). - fprintf('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'); - fprintf('1/ Red cable has to be connected to the Cogent BOX\n'); - fprintf('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'); - fprintf('2/ D2 Connection not to forget on the LPT panel\n'); - fprintf('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'); - fprintf('3/ Switch the SCR cable\n'); - fprintf('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'); - fprintf('4/ Button box has to be on\n'); - fprintf('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'); - fprintf('5/ Did the trigger test work?\n!!!!!!You MUST observe 5 pulses on the PHYSIOCOMPUTER!!!!!\n\n\nPress V(alidate) to continue experiment or C to continue sending test pulses...\n') - [~, k] = KbStrokeWait(p.ptb.device); - k = find(k); - end - fprintf('Continuing...\n'); - %% - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %load the pictures to the video memory. - p.ptb.stim_sprites = CreateStimSprites(p.stim.files);% - %% take care of the circle presentation - %order of faces on the circle that will be shown at the end. - if phase == 4 - circle_order = Shuffle(unique(p.presentation.dist(p.presentation.dist < 500)));% - circle_order(end+1)=circle_order(1); - while any(abs(diff(circle_order)) < 50);%check that neighbors will not be neighbors in the next order. - circle_order = Shuffle(unique(p.presentation.dist(p.presentation.dist < 500))); - circle_order(end+1) = circle_order(1);%to be successful the check has to consider the circularity. - end - p.stim.circle_order = circle_order(1:end-1);%conditions in distances from CSP, 0 = CS+, randomized - p.stim.circle_angles = sort(p.stim.circle_order);%this is just angles with steps of 45 - %transform the angles to rects - for nc = 1:p.stim.tFace - p.stim.circle_rect(nc,:) = angle2rect(p.stim.circle_angles(nc)); - p.stim.circle_file_id(nc) = unique(p.presentation.stim_id(p.presentation.dist == p.stim.circle_order(nc)));%the file that corresponds to different conditions - end - %one to one mappings: - %now we have: circle_order ==> file_id - %circle_angles ==> circle_rect - end - - %% - function [out]=CreateStimSprites(files) - %loads all the stims to video memory - for nStim = 1:size(files,1) - filename = files(nStim,:); - [im , ~, ~] = imread(filename); - out(nStim) = Screen('MakeTexture', p.ptb.w, im ); - end - end - end - function [t]=StopEyelinkRecording - if EyelinkWanted - Eyelink('StopRecording'); - t = GetSecs; - %this is the end of the trial scope. - WaitSecs(0.01); - Eyelink('Message', 'TRIAL_RESULT 0'); - % - WaitSecs(0.01); - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('Command', 'clear_screen %d', 0); - Screen('Textsize', p.ptb.w,p.text.fontsize); - Log(t,8,NaN); - else - t = GetSecs; - end - end - - function [t]=StartEyelinkRecording(nTrial,nStim,phase,dist,oddball,ucs,fix,block_id) - if EyelinkWanted - t = []; - if isnan(dist) - dist=3000; - end - nStim = double(nStim); - Eyelink('Message', 'TRIALID: %04d, PHASE: %04d, FILE: %04d, DELTACSP: %04d, ODDBALL: %04d, UCS: %04d, FIXX: %04d, FIXY %04d, MBLOCK %04d', nTrial, phase, nStim, dist, double(oddball), double(ucs),fix(1),fix(2),block_id); - Eyelink('Message', 'FX Onset at %d %d',fix(1),fix(2)); - % an integration message so that an image can be loaded as - % overlay background when performing Data Viewer analysis. - WaitSecs(0.01); - %return - if nStim~=0 - Eyelink('Message', '!V IMGLOAD CENTER %s %d %d', p.stim.files(nStim,:), p.ptb.midpoint(1), p.ptb.midpoint(2)); - end - % This supplies the title at the bottom of the eyetracker display - Eyelink('Command', 'record_status_message "Stim: %02d, Phase: %d"', nStim, phase); - % - %Put the tracker offline and draw the stimuli. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - % clear tracker display and draw box at center - Eyelink('Command', 'clear_screen %d', 0); - %draw the image on the screen but also the two crosses - if (nStim <= 16 && nStim>0) - Eyelink('ImageTransfer',p.stim.files24(nStim,:),p.ptb.imrect(1),p.ptb.imrect(2),p.stim.width,p.stim.height,p.ptb.imrect(1),p.ptb.imrect(2),0); - end - Eyelink('Command', 'draw_cross %d %d 15',fix(1),fix(2)); - Eyelink('Command', 'draw_cross %d %d 15',fix(1),fix(2)+diff(p.ptb.cross_shift)); - - % - %drift correction - %EyelinkDoDriftCorrection(el,crosspositionx,crosspositiony,0,0); - %start recording following mode transition and a short pause. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('StartRecording'); - t = GetSecs; - Log(t,2,NaN); - else - t = GetSecs; - end - end - function [shuffled idx] = Shuffle(vector,N) - %takes first N from the SHUFFLED before outputting. This function - %could be used as a replacement for randsample - if nargin < 2;N = length(vector);end - [~, idx] = sort(rand([1 length(vector)])); - shuffled = vector(idx(1:N)); - shuffled = shuffled(:); - end - function Buzz - outp(p.com.lpt.address, p.com.lpt.digitimer ); - WaitSecs(p.duration.shockpulse); - outp(p.com.lpt.address, 0); - WaitSecs(p.duration.intershockpulse); - end - function MarkCED(socket,port) - %send pulse to SCR# - outp(socket,port); - WaitSecs(0.01); - outp(socket,0); - end - function InitEyeLink - if EyelinkWanted - % - if EyelinkInit(0)%use 0 to init normaly - fprintf('=================\nEyelink initialized correctly...\n') - else - fprintf('=================\nThere is problem in Eyelink initialization\n') - keyboard; - end - % - WaitSecs(0.5); - [~, vs] = Eyelink('GetTrackerVersion'); - fprintf('=================\nRunning experiment on a ''%s'' tracker.\n', vs ); - - %load 24bits pictures for eyelink... - dummy = dir([p.path.stim24 '*.bmp']); - p.stim.files24 = [repmat([fileparts(p.path.stim24) filesep],length(dummy),1) vertcat(dummy(:).name)]; - % - el = EyelinkInitDefaults(p.ptb.w); - %update the defaults of the eyelink tracker - el.backgroundcolour = p.stim.bg; - el.msgfontcolour = WhiteIndex(el.window); - el.imgtitlecolour = WhiteIndex(el.window); - el.targetbeep = 0; - el.calibrationtargetcolour = WhiteIndex(el.window); - el.calibrationtargetsize = 1.5; - el.calibrationtargetwidth = 0.5; - el.displayCalResults = 1; - el.eyeimgsize = 50; - el.waitformodereadytime = 25;%ms - el.msgfont = 'Times New Roman'; - el.cal_target_beep = [0 0 0];%[1250 0.6 0.05]; - %shut all sounds off - el.drift_correction_target_beep = [0 0 0]; - el.calibration_failed_beep = [0 0 0]; - el.calibration_success_beep = [0 0 0]; - el.drift_correction_failed_beep = [0 0 0]; - el.drift_correction_success_beep= [0 0 0]; - EyelinkUpdateDefaults(el); - PsychEyelinkDispatchCallback(el); - - % open file. - res = Eyelink('Openfile', p.path.edf); - % - Eyelink('command', 'add_file_preamble_text ''Recorded by EyelinkToolbox FearAmy Experiment (Selim Onat)'''); - Eyelink('command', 'screen_pixel_coords = %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - Eyelink('message', 'DISPLAY_COORDS %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - % set calibration type. - Eyelink('command','auto_calibration_messages = YES'); - Eyelink('command', 'calibration_type = HV13'); - Eyelink('command', 'select_parser_configuration = 1'); - %what do we want to record - Eyelink('command', 'file_sample_data = LEFT,RIGHT,GAZE,HREF,AREA,GAZERES,STATUS,INPUT,HTARGET'); - Eyelink('command', 'file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON,INPUT'); - Eyelink('command', 'use_ellipse_fitter = no'); - % set sample rate in camera setup screen - Eyelink('command', 'sample_rate = %d',1000); - end - end - function StopEyelink(filename) - if EyelinkWanted - try - fprintf('Trying to stop the Eyelink system with StopEyelink\n'); - Eyelink('StopRecording'); - Log(t,8,NaN); - WaitSecs(0.5); - Eyelink('Closefile'); - display('receiving the EDF file...'); - Eyelink('ReceiveFile',filename,p.path.path_edf,1); - display('...finished!') - % Shutdown Eyelink: - Eyelink('Shutdown'); - catch - display('StopEyeLink routine didn''t really run well'); - end - end - end - function cleanup - % Close window: - sca; - %set back the old resolution - if strcmp(p.hostname,'triostim1') - % Screen('Resolution',p.ptb.screenNumber, p.ptb.oldres.width, p.ptb.oldres.height ); - %show the cursor - ShowCursor(p.ptb.screenNumber); - end - % - commandwindow; - KbQueueStop(p.ptb.device); - KbQueueRelease(p.ptb.device); - end - function CalibrateEL - if EyelinkWanted - fprintf('=================\n=================\nEntering Eyelink Calibration\n') - p.var.ExpPhase = 0; - ShowInstruction(0,1); - EyelinkDoTrackerSetup(el); - %Returns 'messageString' text associated with result of last calibration - [~, messageString] = Eyelink('CalMessage'); - Eyelink('Message','%s',messageString);% - WaitSecs(0.05); - fprintf('=================\n=================\nNow we are done with the calibration\n') - end - end - function Log(ptb_time, event_type, event_info) - %Phases: - %Instruction : 0 - %Test : 1 - %Rating : 5 - %Calibration : 0 - % - %event types are as follows: - % - %Pulse Detection : 0 info: NaN; - %Tracker Onset : 1 - %Cross Onset : 2 info: position - %Stimulus Onset : 3 info: dist_id - %Cross Movement : 4 info: NaN; - %UCS Delivery : 5 info: NaN; - %Stimulus Offset : 6 info: NaN; - %Key Presses : 7 info: NaN; - %Tracker Offset : 8 info: NaN; - %MicroBlock : 9 info:rank - % - %Text on the screen : -1 info: Which Text? - %RatingScreen Onset : -2 info: NaN; - for iii = 1:length(ptb_time) - p.var.event_count = p.var.event_count + 1; - p.out.log(p.var.event_count,:) = [ptb_time(iii) event_type event_info(iii) p.var.ExpPhase]; - end - % plot(p.out.log(1:p.var.event_count,1) - p.out.log(1,1),p.out.log(1:p.var.event_count,2),'o','markersize',10); - % ylim([-2 8]); - % set(gca,'ytick',[-2:8],'yticklabel',{'Rating On','Text','Pulse','Tracker+','Cross+','Stim+','CrossMov','UCS','Stim-','Key+','Tracker-'}); - % grid on - % drawnow; - - end - function [secs]=WaitPulse(keycode,n) - %[secs]=WaitPulse(keycode,n) - % - % This function waits for the Nth upcoming pulse. If N=1, it will wait for - % the very next pulse to arrive. 1 MEANS NEXT PULSE. So if you wish to wait - % for 6 full dummy scans, you should use N = 7 to be sure that at least 6 - % full acquisitions are finished. - % - % The function avoids KbCheck, KbWait functions, but relies on the OS - % level event queues, which are much less likely to skip short events. A - % nice discussion on the topic can be found here: - % http://ftp.tuebingen.mpg.de/pub/pub_dahl/stmdev10_D/Matlab6/Toolboxes/Psychtoolbox/PsychDocumentation/KbQueue.html - - %KbQueueFlush;KbQueueStop;KbQueueRelease;WaitSecs(1); - fprintf('Will wait for %i dummy pulses...\n',n); - if n ~= 0 - secs = nan(1,n); - pulse = 0; - dummy = []; - while pulse < n - dummy = KbTriggerWait(keycode,p.ptb.device); - pulse = pulse + 1; - secs(pulse+1) = dummy; - Log(dummy,0,NaN); - end - else - secs = GetSecs; - end - end - function [keycode, secs] = KbQueueDump; - %[keycode, secs] = KbQueueDump - % Will dump all the events accumulated in the queue. - - keycode = []; - secs = []; - pressed = []; - %fprintf('there are %03d events\n',KbEventAvail(p.ptb.device)); - while KbEventAvail(p.ptb.device) - [evt, n] = KbEventGet(p.ptb.device); - n = n + 1; - keycode(n) = evt.Keycode; - pressed(n) = evt.Pressed; - secs(n) = evt.Time; - % fprintf('Event is: %d\n',keycode(n)); - end - i = pressed == 1; - keycode(~i) = []; - secs(~i) = []; - %fprintf('there are %03d events found...\n',length(keycode)); - end - function [a]=MinimumAngle(y,x); - %[a]=MinimumAngle(x,y); - % - %finds the minimum angle between two angles given in degrees, the answer is - %also in degrees. The clockwise distances from Y to X are considered as - %positive. Opposite angles are considered as positive 180. - - x = deg2rad(x); - y = deg2rad(y); - - a = atan2(sin(x-y), cos(x-y)); - - a = -round(rad2deg(a)); - - if any(abs(a) == 180); - a(abs(a) == 180) = 180; - end - end -end diff --git a/exp_PMF_ForAll.m b/exp_PMF_ForAll.m deleted file mode 100644 index 421929e..0000000 --- a/exp_PMF_ForAll.m +++ /dev/null @@ -1,1050 +0,0 @@ -function [p]=exp_PMF_ForAll(subject,phase,csp) - -% Same/different discrimination task estimating the perceptual threshold alpha of an -% observer's underlying Psychometric Function (PF), using the method of constant stimuli. -% Input: -% subject = subject number -% phase = phase number, will only name the logfile folder -% csp = CS+ Face as ID (i.e. 1 to 8) -% -% Note: Two "chains" are run intertwinedly, i.e. trials for CS+ are mixed -% with trials for CS-. Chain 1 refers to CS+, Chain 2 to CS-. -% -% adapted by LK in 10/2016 for use on any computer - -EyelinkWanted = 0; %is Eyelink wanted? -fixjump = 1; %fixation cross starts at eyes and jumps to mouth - %(see variable fix_start). - -% make a break every ....th Trial -breakpoint = 50; - -ListenChar(2);%disable unwanted keypresses -commandwindow; -%clear everything -clear mex global functions -cgshut; -global cogent; -%%%%%%%%%%%load the GETSECS mex files so call them at least once -GetSecs; -WaitSecs(0.001); - -el = []; -p = []; -SetParams; -SetPTB; - -if EyelinkWanted - InitEyeLink; - WaitSecs(2); - ShowInstruction(1); - CalibrateEL; -else - WaitSecs(2); - ShowInstruction(11); -end - -SetupLog; -%save the parameter file once now -save(p.path.path_param,'p'); -if EyelinkWanted - ShowInstruction(3); -end -% counter for within chain trials (cc) and global trials (tt) -cc = zeros(1,tchain); -tt = 0; -%trialID is counting every single face (2 per Trial_YN), need that for -%Eyelink -trialID = 0; - -STOP = 0; -while ~STOP - chains = find(cc1 - current_chain = randsample(chains,[1 1]); - end - if tt~=tchain*p.psi.presentation.numtrials_chain - tt=tt+1; - % enter in break loop - if (tt~=1 && mod(tt,breakpoint)==1); - save(p.path.path_param,'p'); - ShowInstruction(4); - %calibrate if Eyelink - if EyelinkWanted - CalibrateEL; - end - end - cc(current_chain)=cc(current_chain)+1; - % Chain 1 is CS+, Chain 2 is CS-. - fprintf('Chain %4.2f, Chain trial %03d/%03d...',current_chain,cc(current_chain),p.psi.presentation.numtrials_chain) - %Present trial here at stimulus intensity x and collect response - fprintf('Intensity x is now %4.2f \n',x(cc(current_chain),current_chain)) - test = x(cc(current_chain),current_chain) + csn_shift(current_chain) + p.stim.cs_plus; - dummy = test; - test = mod(test,360); - % the reference is csp or csn - ref = csn_shift(current_chain) + p.stim.cs_plus; - ref = mod(ref,360); - % start Trial - fprintf('Starting Trial %03d/%03d.\n',tt,tchain*p.psi.presentation.numtrials_chain) - [test_face, ref_face, signal,trialID] = Trial_YN(trialID,ref,test,p.stim.tFace,tt); - % ask subject for answer - fprintf('Rating.\n') - Screen('Textsize', p.ptb.w,p.text.fontsize); - % put Rating there - message1 = 'Waren die Gesichter unterschiedlich oder gleich?\n'; - message2 = 'Bewegen Sie den "Zeiger" mit der rechten und linken Pfeiltaste\n und bestätigen Sie Ihre Einschätzung mit der oberen Pfeiltaste.'; - - rect = [p.ptb.width*0.2 p.ptb.midpoint(2) p.ptb.width*0.6 100]; - [response_subj] = RatingSlider(rect,2,Shuffle(1:2,1),p.keys.increase,p.keys.decrease,p.keys.confirm,{ 'unterschiedlich' 'gleich'},message1,message2,0); - % see if subject found the different pair of faces... - % buttonpress left (Yes) is response_subj=2, right alternative - % (No) outputs a 1, this will be transformed here. - % note that response == 1 only means "yes", but not necessarily - % "correct" - sdt = NaN; - if (response_subj == 2 && signal == 1) - response = 1; - fprintf('...Hit. \n') - sdt=1; - elseif (response_subj==1 && signal == 1) - response = 0; - fprintf('...Miss. \n') - sdt=3; - elseif (response_subj == 2 && signal==0) - response = 1; - fprintf('...False Alarm. \n') - sdt=2; - elseif (response_subj == 1 && signal == 0) - response = 0; - fprintf('...Correct Rejection. \n') - sdt=4; - else - warning('error in the answer algorithm! \n') - end - - % store everything in the Log - row = find(unique(x)==x(cc(current_chain),current_chain)); - p.psi.log.trial_counter(row,current_chain) = p.psi.log.trial_counter(row,current_chain) + 1; - p.psi.log.xrounded(row,p.psi.log.trial_counter(row,current_chain),current_chain) = response; - SetLog; - %iteration control - STOP = sum(cc >= p.psi.presentation.numtrials_chain) == tchain; - end - %final save of parameter-/logfile - save(p.path.path_param,'p'); -end - -%end of Experiment, show text to subject -ShowInstruction(2); -%get the eyelink file back to this computer -if EyelinkWanted - StopEyelink(p.path.edf); -end - -%close everything down -cleanup; -%move the folder to appropriate location -movefile(p.path.subject,p.path.finalsubject); - - function [test_face,ref_face,signal,trialID] = Trial_YN(trialID,ref_stim,test_stim,last_face_of_circle,tt) - Screen('Textsize', p.ptb.w,p.text.fixsize); - % computes the trial FACES, using the test/ref information input - % values (in Deg) - - trial = [ref_stim test_stim]/p.stim.delta; - % correct face number within circle - trial = mod(round(trial),last_face_of_circle)+1; - ref_face = trial(1); - test_face = trial(2); - [trial,idx]= Shuffle(trial); - fprintf('Faces: %d %d \n',trial(1),trial(2)); - %compute if trial had different faces or not - %if trial(1)=trial(2), they were the same and subject has to - %answer with 'no' (right option, is 1), else means correct hit - - if trial(1)==trial(2) - signal = 0; - else - signal = 1; - end - - - trial_deg = [ref_stim test_stim]; - isref = double(trial==ref_face) ; - delta_ref = MinimumAngleQuartile([trial_deg(idx(1)) trial_deg(idx(2))],ref); - delta_csp = MinimumAngleQuartile([trial_deg(idx(1)) trial_deg(idx(2))],p.stim.cs_plus); % ... - abs_FGangle = [trial_deg(idx(1)) trial_deg(idx(2))]; - - trialID=trialID+1; - - %get fixation crosses and onsets from p parameter - - - %GetSecs so that the onsets can be defined - if fixjump ==1 - onsets = 0.25+GetSecs; %fix1 onset - onsets = [onsets onsets(end)+p.duration.fix+rand(1)*.25];%stim1 onset - onsets = [onsets onsets(end)+p.duration.crossmoves]; %fix jump - onsets = [onsets onsets(end)+p.duration.crossmoves]; %stim offset - fixdelta = p.duration.fix+rand(1)*.25; - onsets = [onsets onsets(end)+p.duration.isi-fixdelta]; %fix2 onset - onsets = [onsets onsets(end)+fixdelta]; %stim2 onset - onsets = [onsets onsets(end)+p.duration.crossmoves]; %fix jump - onsets = [onsets onsets(end)+p.duration.crossmoves]; %stim offset - else - onsets = 0.25+GetSecs;%fix1 onset - onsets = [onsets onsets(end)+p.duration.fix+rand(1)*.25];%stim1 onset - onsets = [onsets onsets(end)+p.duration.stim];%stim1 offset - fixdelta = p.duration.fix+rand(1)*.25; - onsets = [onsets onsets(end)+p.duration.isi-fixdelta];%fix2 onset - onsets = [onsets onsets(end)+fixdelta];%stim2 onset - onsets = [onsets onsets(end)+p.duration.stim];%stim2 offset - end - - if fixjump ==1 - fix_i = p.psi.presentation.fix_start(cc(current_chain),current_chain); - fix = round([p.ptb.CrossPosition_x p.ptb.CrossPosition_y(fix_i)]); - FixCross = [fix(1)-1,fix(2)-p.ptb.fc_size,fix(1)+1,fix(2)+p.ptb.fc_size;fix(1)-p.ptb.fc_size,fix(2)-1,fix(1)+p.ptb.fc_size,fix(2)+1]; - %fixation cross 1 - %FixCross = [fix(1,1)-1,fix(1,2)-p.ptb.fc_size,fix(1,1)+1,fix(1,2)+p.ptb.fc_size;fix(1,1)-p.ptb.fc_size,fix(1,2)-1,fix(1,1)+p.ptb.fc_size,fix(1,2)+1]; - Screen('FillRect', p.ptb.w, [255,255,255], FixCross'); - if EyelinkWanted - Eyelink('Message', 'FX Onset at %d %d',fix(1),fix(2)); - end - Screen('Flip',p.ptb.w,onsets(1),0); - if EyelinkWanted - StartEyelinkRecording(trialID,phase,cc(current_chain),tt,current_chain,isref(1),trial(1),delta_ref(1),delta_csp(1),abs_FGangle(1),fix(1,1),fix(1,2)); - end - %face trial(1) - Screen('DrawTexture',p.ptb.w,p.ptb.stim_sprites(trial(1))); - Screen('FillRect', p.ptb.w, [255,255,255], FixCross'); - Screen('Flip',p.ptb.w,onsets(2),0); - if EyelinkWanted - Eyelink('Message', 'Stim Onset'); - Eyelink('Message', 'SYNCTIME'); - end - %fixJUMP trial(1) - fix = [p.ptb.CrossPosition_x p.ptb.CrossPosition_y(setdiff(1:2,fix_i))];%take the other position - FixCross = [fix(1)-1,fix(2)-p.ptb.fc_size,fix(1)+1,fix(2)+p.ptb.fc_size;fix(1)-p.ptb.fc_size,fix(2)-1,fix(1)+p.ptb.fc_size,fix(2)+1]; - %FixCross = [fix(2,1)-1,fix(2,2)-p.ptb.fc_size,fix(2,1)+1,fix(2,2)+p.ptb.fc_size; fix(2,1)-p.ptb.fc_size,fix(2,2)-1,fix(2,1)+p.ptb.fc_size,fix(2,2)+1]; - Screen('DrawTexture',p.ptb.w,p.ptb.stim_sprites(trial(1))); - Screen('FillRect', p.ptb.w, [255,255,255], FixCross'); - Screen('Flip',p.ptb.w,onsets(3),0); - while GetSecscross2onset->onset2shock->shock2offset - %these (duration.BLA) are average duration values: - % 1.5 0.5 0.5 - p.duration.stim = 1.5;%s - p.duration.fix = .7; - p.duration.crossmoves = p.duration.stim./2; - p.duration.isi = 1.0; - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - %create the randomized design - p.stim.csp_id = csp; - csp_degree = mod((p.stim.csp_id-1) * 45,360); - p.stim.cs_plus = csp_degree;%index of cs stimulus, this is the one paired to shock in the main experiment - %p.stim.cs_neg = csn; - - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %Set up Constant Stimuli procedure - csn_shift = [0 180]; - tchain = 2; - interval = 22.5; - maxdegree = 180; - maxtrials = 100; % this will be exceeded, if addzeros > 0 - addzeros = 0; - - tsteps = (2*maxdegree./interval)+1; - if maxdegree == 180 - tsteps = tsteps - 2;%spares out the CSN - end - rep = floor(maxtrials./(tsteps+1));%+1 so that zero can be doubled... - steps = [repmat(0:interval:180-interval,1,rep) repmat(0:interval:180-interval,1,rep)*-1 zeros(1,addzeros)]; - % we chose to have higher resolution around zero and take this from - % the easiest intensity level, i.e. replace 157.5 - steps(steps== 157.5) = 11.25; - steps(steps== -157.5) = -11.25; - - for n = 1:tchain - x(:,n) = Shuffle(steps); - fix_start(:,n) = ones(length(x(:,n)),1)*2; %1 = mouth2eye, 2 = eye2mouth - end - - fprintf('This is the distribution of stimuli we will use:\n') - histi = histc(x,unique(x)); - uniquex = unique(x); - for l = 1:length(unique(x)) - fprintf('Level %+ 7.2f: %02d repetitions. \n',uniquex(l,1),histi(l,1)) - end - fprintf('---------------------------\nTotal trials: %03d per chain.\n',sum(histi(:,1))) - WaitSecs(3); - %store everything in p - p.psi.presentation.x = x; - p.psi.presentation.interval = interval; - p.psi.presentation.numtrials_chain = length(x(:,1)); - p.psi.presentation.tsteps = tsteps; - p.psi.presentation.rep = histi(:,1); - p.psi.presentation.uniquex = unique(x); - p.psi.presentation.fix_start = fix_start; - p.var.current_bg = p.stim.bg;%current background to be used. - %Save the stuff - save(p.path.path_param,'p'); - % - - end - function [rating]=RatingSlider(rect,tSection,position,up,down,confirm,labels,message1,message2,numbersOn) - % - %Detect the bounding boxes of the labels. - for nlab = 1:2 - [nx, ny, bb(nlab,:)]=DrawFormattedText(p.ptb.w,labels{nlab}, 'center', 'center', p.stim.white,[],[],[],2); - Screen('FillRect',p.ptb.w,p.stim.bg); - end - bb = max(bb); - bb_size = bb(3)-bb(1);%vertical size of the bb. - % - DrawSkala; - ok = 1; - while ok == 1 - [secs, keyCode, deltaSecs] = KbStrokeWait; - - keyCode = find(keyCode); - if (keyCode == up) | (keyCode == down) - next = position + increment(keyCode); - if next < (tSection+1) & next > 0 - position = position + increment(keyCode); - rating = tSection - position + 1; - end - DrawSkala; - elseif keyCode == confirm - WaitSecs(0.1); - ok = 0; - Screen('FillRect',p.ptb.w,p.stim.bg); - Screen('Flip',p.ptb.w); - end - end - - function DrawSkala - rating = tSection - position + 1; - increment([up down]) = [1 -1];%delta - tick_x = linspace(rect(1),rect(1)+rect(3),tSection+1);%tick positions - tick_size = rect(3)./tSection; - ss = tick_size/5*0.9;%slider size. - % - for tick = 1:length(tick_x)%draw ticks - Screen('DrawLine', p.ptb.w, [255 0 0], tick_x(tick), rect(2), tick_x(tick), rect(2)+rect(4) , 3); - if tick <= tSection && numbersOn - Screen('TextSize', p.ptb.w,p.text.fontsize./2); - DrawFormattedText(p.ptb.w, mat2str(tick) , tick_x(tick)+ss/2, rect(2)+rect(4), p.stim.white); - Screen('TextSize', p.ptb.w,p.text.fontsize); - end - if tick == 1 - DrawFormattedText(p.ptb.w, labels{1},tick_x(tick)-bb_size*1.6,rect(2), p.stim.white); - elseif tick == tSection+1 - DrawFormattedText(p.ptb.w, labels{2},tick_x(tick)+bb_size*0.2,rect(2), p.stim.white); - end - end - %slider coordinates - slider = [ tick_x(position)+tick_size*0.1 rect(2) tick_x(position)+tick_size*0.9 rect(2)+rect(4)]; - %draw the slider - Screen('FillRect',p.ptb.w, p.stim.white, round(slider)); - Screen('TextSize', p.ptb.w,p.text.fontsize); - DrawFormattedText(p.ptb.w,message1, 'center', p.ptb.midpoint(2)*0.2, p.stim.white,[],[],[],2); - Screen('TextSize', p.ptb.w,p.text.fontsize./2); - DrawFormattedText(p.ptb.w,message2, 'center', p.ptb.midpoint(2)*0.4, p.stim.white,[],[],[],2); - Screen('TextSize', p.ptb.w,p.text.fontsize); - Screen('Flip',p.ptb.w); - end - end - - function [shuffled,idx] = Shuffle(vector,N) - %takes first N from the SHUFFLED before outputting. This function - %could be used as a replacement for randsample - if nargin < 2;N = length(vector);end - [dummy, idx] = sort(rand([1 length(vector)])); - shuffled = vector(idx(1:N)); - shuffled = shuffled(:); - end - - function [a]=MinimumAngleQuartile(y,x) - %[a]=MinimumAngle(x,y); - % - %finds the minimum angle between two angles given in degrees, the answer is - %also in degrees. The clockwise distances from Y to X are considered as - %positive. Opposite angles are considered as positive 180. - - x = deg2rad(x); - y = deg2rad(y); - - a = atan2(sin(x-y), cos(x-y)); - - a = -round(((180/pi)*a)*4)/4; - - if any(abs(a) == 180); - a(abs(a) == 180) = 180; - end - end - - function ShowInstruction(nInstruct) - - [text]=GetText(nInstruct); - ShowText(text); - %let subject read it and ask confirmation to proceed. - if nInstruct ~= 2 - KbStrokeWait; - else - WaitSecs(2) - end - Screen('FillRect',p.ptb.w,p.stim.bg); - Screen('Flip',p.ptb.w); - - end - function ShowText(text) - - - Screen('FillRect',p.ptb.w,p.stim.bg); - %DrawFormattedText(p.ptb.w, text, p.text.start_x, 'center',p.stim.white,[],[],[],2,[]); - DrawFormattedText(p.ptb.w, text, 'center', 'center',p.stim.white,[],[],[],2,[]); - Screen('Flip',p.ptb.w); - - %show the messages at the experimenter screen - fprintf([repmat('=',1,50) '\n']); - fprintf('Subject''s monitor:\n'); - fprintf(text); - fprintf([repmat('=',1,50) '\n']); - - end - - - function [text]=GetText(nInstruct) - - if nInstruct == 0%Eyetracking calibration - - text = ['Um Ihre Augenbewegungen zu messen, \n' ... - 'müssen wir jetzt den Eye-Tracker kalibrieren.\n' ... - 'Dazu zeigen wir Ihnen einige Punkte auf dem Bildschirm, \n' ... - 'bei denen Sie sich wie folgt verhalten:\n' ... - 'Bitte fixieren Sie den Fixationspunkt und \n' ... - 'bleiben Sie so lange darauf, wie er zu sehen ist.\n' ... - 'Bitte drücken Sie jetzt den oberen Knopf, \n' ... - 'um mit der Kalibrierung weiterzumachen.\n' ... - ]; - - elseif nInstruct == 1 - text = ['In diesem Experiment sehen Sie nacheinander jeweils zwei Gesichter.\n'... - 'Danach werden Sie gefragt, ob die Gesichter unterschiedlich oder gleich waren.\n'... - '\n'... - 'Benutzen Sie zum Antworten die Pfeiltasten (links, rechts) und die obere Taste zum Bestätigen.\n'... - '\n'... - 'Sie erhalten in diesem Teil keine Schocks.\n'... - 'Folgen Sie aber bitte auch hier streng den Fixationskreuzen!\n'... - '\n'... - 'Sie werden alle ' num2str(breakpoint) ' Durchgänge eine Pause machen können,\nnach der der Eyetracker neu kalibriert wird.\n'... - 'Das heißt, Sie können in der Pause den Kopf ruhig aus der Kopfstütze nehmen und sich entspannen. \n'... - '\n'... - 'Wenn Sie noch Fragen haben, können Sie jetzt die Versuchsleiter/in fragen.\n'... - 'Wir können Sie jederzeit hören.\n'... - '\n'... - 'Drücken Sie ansonsten die obere Taste,\n'... - ' um das Experiment zu starten.\n' ... - ]; - elseif nInstruct == 11 - text = ['In diesem Experiment sehen Sie nacheinander jeweils zwei Gesichter.\n'... - 'Danach werden Sie gefragt, ob die Gesichter unterschiedlich oder gleich waren.\n'... - '\n'... - 'Benutzen Sie zum Antworten die Pfeiltasten (links, rechts) und die obere Taste zum Bestätigen.\n'... - '\n'... - 'Sie erhalten in diesem Teil keine Schocks.\n'... - 'Folgen Sie aber bitte streng den Fixationskreuzen!\n'... - '\n'... - 'Sie werden alle ' num2str(breakpoint) ' Durchgänge eine Pause machen können \n'... - 'nach der Sie durch Tastendruck fortfahren können. \n'... - '\n'... - 'Wenn Sie noch Fragen haben, können Sie jetzt die Versuchsleiter/in fragen.\n'... - 'Wir können Sie jederzeit hören.\n'... - '\n'... - 'Drücken Sie ansonsten die obere Taste,\n'... - ' um das Experiment zu starten.\n' ... - ]; - elseif nInstruct == 3 - text = ['Der Eyetracker ist nun kalibiert.\n'... - '\n'... - 'Bitte verändern Sie Ihre Kopfposition nun nicht mehr.\n'... - '\n'... - 'Zur Erinnerung: Im Experiment sehen Sie jeweils zwei Gesichter und geben anschließend an,\n'... - '\n'... - 'ob die Gesichter gleich oder unterschiedlich waren.\n'... - '\n'... - 'Benutzen Sie dazu die Pfeiltasten (links, rechts) und die obere Taste zum Bestätigen.\n'... - '\n'... - 'Zusätzlich folgen Sie auch hier immer den Fixationskreuzen.\n'... - '\n'... - 'Drücken Sie nun die obere Taste,\n'... - ' um das Experiment zu starten!\n' ... - ]; - elseif nInstruct == 2%end - text = 'Experiment beendet!\n'; - elseif nInstruct==4%break - text = [sprintf('Sie haben bereits %g von %g Durchgängen geschafft!\n',tt-1,p.psi.presentation.numtrials_chain*tchain)... - 'Machen Sie eine kurze Pause, lehnen Sie sich gern einen Moment zurück\n'... - 'und schließen Sie die Augen, um diese zu entspannen.\n'... - 'Drücken Sie anschließend die mittlere Taste, um weiterzumachen.\n']; - end - end - - function SetupLog - - p.psi.log.globaltrial= NaN(tchain,length(x)); - p.psi.log.signal = NaN(tchain,length(x)); - p.psi.log.x = NaN(tchain,length(x)); - p.psi.log.refface = NaN(tchain,length(x)); - p.psi.log.testface = NaN(tchain,length(x)); - p.psi.log.response = NaN(tchain,length(x)); - % p.psi.log.xrounded = NaN(p.stim.tFace/tchain+1,p.psi.presentation.numtrials_chain,tchain); - p.psi.log.xrounded = NaN(length(unique(x)),max(p.psi.presentation.rep),tchain); - p.psi.log.sdt = NaN(tchain,length(x)); - p.psi.log.trial_counter = zeros(length(unique(x)),tchain); - end - - function SetLog - - p.psi.log.globaltrial(current_chain,cc(current_chain))= tt; - p.psi.log.signal(current_chain,cc(current_chain)) = signal; - p.psi.log.x(current_chain,cc(current_chain)) = x(cc(current_chain),current_chain); - p.psi.log.refface(current_chain,cc(current_chain)) = ref_face; - p.psi.log.testface(current_chain,cc(current_chain)) = test_face; - p.psi.log.response(current_chain,cc(current_chain)) = response; - p.psi.log.sdt(current_chain,cc(current_chain)) = sdt;%1=hit 2=FA 3=miss 4=CR - - - end -% function PlotProcedure -% plotproc=figure(1); -% % title(sprintf('Threshold Estimation for subject %02d',tchain),'FontSize',14) -% for sub=1:tchain; -% subplot(2,2,sub) -% t = 1:length(p.log.x(sub)); -% hold on; -% plot(t,abs(p.log.x(sub)),'bo-'); -% errorbar(t,p.log.alpha(sub),p.log.seAlpha(sub),'r--') -% plot(t(p.log.response(sub) == 1),p.log.x(sub)(p.log.response(sub) == 1),'ko', ... -% 'MarkerFaceColor','k'); -% plot(t(p.log.response(sub) == 0),p.log.x(sub)(p.log.response(sub) == 0),'ko', ... -% 'MarkerFaceColor','w'); -% -% set(gca,'FontSize',12); -% axis([0 max(t)+1 0 max(p.log{sub}.alpha)+max(p.log{sub}.seAlpha)+20]) -% xlabel('Trial'); -% ylabel('xCurrent (Deg)'); -% -% end -% annotation('textbox', [0 0.9 1 0.1], 'String',... -% (sprintf('Threshold Estimation for subject %02d',tchain)), ... -% 'EdgeColor', 'none', ... -% 'HorizontalAlignment', 'center','FontSize',14) -% legend('xCurrent','estimated Threshold','Response = 1','Response = 0','Location','northeast'); -% -% % end -% function Plot_Fit -% plotfit=figure(2); -% for sub=1:tchain; -% subplot(2,2,sub) -% t = 1:length(p.log{sub}.x); -% hold on; -% plot(t,abs(p.log{sub}.x),'bo-'); -% errorbar(t,p.log{1}.alpha,p.log{1}.seAlpha,'r--') -% plot(t(p.log{sub}.response == 1),p.log{sub}.x(p.log{sub}.response == 1),'ko', ... -% 'MarkerFaceColor','k'); -% plot(t(p.log{sub}.response == 0),p.log{sub}.x(p.log{sub}.response == 0),'ko', ... -% 'MarkerFaceColor','w'); -% -% set(gca,'FontSize',12); -% axis([0 max(t)+1 0 max(p.log{sub}.alpha)+max(p.log{sub}.seAlpha)+20]) -% xlabel('Trial'); -% ylabel('xCurrent (Deg)'); -% -% end - - function [t]=StartEyelinkRecording(trialID,phase,cc,tt,current_chain,isref,file,delta_ref,delta_csp,abs_FGangle,fixx,fixy) - - t = []; - - - Eyelink('Message', 'TRIALID:%04d, PHASE:%04d, CHAIN:%04d, CHAINTRIAL:%04d, TTRIAL:%04d, ISREF:%04d, FILE:%04d, DELTAREF:%04d, DELTACSP:%04d, FGDEG:%04d, FXX:%04d, FXY:%04d',trialID, phase,... - current_chain, cc, tt, isref, file, delta_ref*100, delta_csp*100, abs_FGangle*100,fixx,fixy); - % an integration message so that an image can be loaded as - % overlay background when performing Data Viewer analysis. - WaitSecs(0.01); - Eyelink('Message', '!V IMGLOAD CENTER %s %d %d', p.stim.files(file,:), p.ptb.midpoint(1), p.ptb.midpoint(2)); - % This supplies the title at the bottom of the eyetracker display - Eyelink('Command', 'record_status_message "Stim: %d, Phase: %d"',file, phase); - % - %Put the tracker offline and draw the stimuli. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - % clear tracker display and draw box at center - Eyelink('Command', 'clear_screen %d', 0); - %draw the image on the screen - Eyelink('ImageTransfer',p.stim.files24(file,:),p.ptb.imrect(1),p.ptb.imrect(2),p.ptb.imrect(3),p.ptb.imrect(4),p.ptb.imrect(1),p.ptb.imrect(2)); - Eyelink('Command', 'draw_cross %d %d %d',p.ptb.midpoint(1),p.ptb.CrossPositionET_y(1),p.ptb.fc_size); - Eyelink('Command', 'draw_cross %d %d %d',p.ptb.midpoint(1),p.ptb.CrossPositionET_y(2),p.ptb.fc_size); - % - %drift correction - %EyelinkDoDriftCorrection(el,crosspositionx,crosspositiony,0,0); - %start recording following mode transition and a short pause. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('StartRecording'); - - t = GetSecs; - Log(t,8,NaN); - end - - function [t] = StopEyelinkRecording - - Eyelink('Message', 'Stim Offset'); - Eyelink('Message', 'BLANK_SCREEN'); - Eyelink('StopRecording'); - t = GetSecs; - %this is the end of the trial scope. - WaitSecs(0.01); - Eyelink('Message', 'TRIAL_RESULT 0'); - % - WaitSecs(0.01); - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('Command', 'clear_screen %d', 0); - - Log(t,-8,NaN); - end - - function InitEyeLink - % - if EyelinkInit(0)%use 0 to init normaly - fprintf('=================\nEyelink initialized correctly...\n') - else - fprintf('=================\nThere is problem in Eyelink initialization\n') - keyboard; - end - % - WaitSecs(0.5); - [~, vs] = Eyelink('GetTrackerVersion'); - fprintf('=================\nRunning experiment on a ''%s'' tracker.\n', vs ); - - %load 24bits pictures for eyelink... - dummy = dir([p.path.stim24 '*.bmp']); - p.stim.files24 = [repmat([fileparts(p.path.stim24) filesep],length(dummy),1) vertcat(dummy(:).name)]; - % for i=1:32 - % filename = p.stim.files24(nStim,:); - % [im , ~, ~] = imread(filename); - % end - % - % - el = EyelinkInitDefaults(p.ptb.w); - %update the defaults of the eyelink tracker - el.backgroundcolour = p.stim.bg; - el.msgfontcolour = WhiteIndex(el.window); - el.imgtitlecolour = WhiteIndex(el.window); - el.targetbeep = 0; - el.calibrationtargetcolour = WhiteIndex(el.window); - el.calibrationtargetsize = 1.5; - el.calibrationtargetwidth = 0.5; - el.displayCalResults = 1; - el.eyeimgsize = 50; - el.waitformodereadytime = 25;%ms - el.msgfont = 'Times New Roman'; - el.cal_target_beep = [0 0 0];%[1250 0.6 0.05]; - %shut all sounds off - el.drift_correction_target_beep = [0 0 0]; - el.calibration_failed_beep = [0 0 0]; - el.calibration_success_beep = [0 0 0]; - el.drift_correction_failed_beep = [0 0 0]; - el.drift_correction_success_beep= [0 0 0]; - EyelinkUpdateDefaults(el); - %PsychEyelinkDispatchCallback(el) - - % open file. - res = Eyelink('Openfile', p.path.edf); - if res == -3 - fprintf('File cannot be created!!!!\n'); - return; - end - % - Eyelink('command', 'add_file_preamble_text ''Recorded by EyelinkToolbox FearCloud Experiment'''); - Eyelink('command', 'screen_pixel_coords = %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - Eyelink('message', 'DISPLAY_COORDS %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - % set calibration type. - Eyelink('command', 'calibration_type = HV5'); - Eyelink('command','auto_calibration_messages = YES'); - Eyelink('command', 'select_parser_configuration = 1'); - %what do we want to record - Eyelink('command', 'file_sample_data = LEFT,RIGHT,GAZE,HREF,AREA,GAZERES,STATUS,INPUT,HTARGET'); - Eyelink('command', 'file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON,INPUT'); - Eyelink('command', 'use_ellipse_fitter = no'); - % set sample rate in camera setup screen - Eyelink('command', 'sample_rate = %d',1000); - end - function StopEyelink(filename) - try - fprintf('Trying to stop the Eyelink system with StopEyelink\n'); - Eyelink('StopRecording'); - WaitSecs(0.5); - Eyelink('Closefile'); - display('receiving the EDF file...'); - Eyelink('ReceiveFile',filename,[p.path.subject '\eye\'],1); - display('...finished!') - % Shutdown Eyelink: - Eyelink('Shutdown'); - catch - display('StopEyeLink routine didn''t really run well'); - end - end - function CalibrateEL - fprintf('=================\n=================\nEntering Eyelink Calibration\n') - p.var.ExpPhase = 0; - ShowInstruction(0); - EyelinkDoTrackerSetup(el); - %Returns 'messageString' text associated with result of last calibration - [~, messageString] = Eyelink('CalMessage'); - Eyelink('Message','%s',messageString);% - WaitSecs(0.05); - fprintf('=================\n=================\nNow we are done with the calibration\n') - end - - function Log(ptb_time, event_type, event_info) - %Phases: - %Pre-Experiment : 1 - %Post-Experiment : 2 - % %Instruction : 1 - % %Baseline : 2 - % %Conditioning : 3 - % %Test : 4 - % %Rating : 5 - % %Calibration : 0 - % - %event types are as follows: - % - %Scan Detection : 0 info: NaN; - %Cross Onset : 1 info: position - %Stimulus Onset/Offset: 2/-2 info: stim_id - %Cross Movement : 3 info: NaN; - %Stimulus Offset : -2 info: NaN; - %UCS Delivery : 4 info: NaN; - %Key Presses : 7 info: NaN; - %Tracker Onset/Offset : 8 info: NaN; - % - %Text on the screen : 5 info: Which Text? - %RatingScreen Onset : 6 info: NaN; - - p.var.event_count = p.var.event_count + 1; - p.out.log(p.var.event_count,:) = [ptb_time event_type event_info phase]; - % % p_out_log(p.out.event_counter,:) - %logstring([ 'Logged: ' mat2str(p_out_log(p.out.event_counter,:)) ' - Type: ' p.verbose.eventtype{abs(event_type)} ' - Phase: ' p.verbose.eventphase{CurrentExperimentalPhase}]) - %for i = 1:3;subplot(3,1,i);plot(p_out_log(1:p.out.event_counter ,i),'o-');drawnow;end - % - - end - function cleanup - - % Close window: - sca; - %set back the old resolution - if strcmp(p.hostname,'triostim1') - Screen('Resolution',p.ptb.screenNumber, p.ptb.oldres.width, p.ptb.oldres.height ); - %show the cursor - ShowCursor(p.ptb.screenNumber); - end - % - % %IOPort('ConfigureSerialPort', p.com.serial,' StopBackgroundRead'); - % %IOPort('Close',p.com.serial); - % commandwindow; - % ListenChar(0); - % KbQueueRelease(p_ptb_device); - end - -end diff --git a/exp_PMparam.m b/exp_PMparam.m deleted file mode 100644 index 9cef65e..0000000 --- a/exp_PMparam.m +++ /dev/null @@ -1,677 +0,0 @@ -function [p] = remi3_fmri(subject,run,group) - - if nargin == 0 - subject = 99; run = 1; group = 1; - end - - if group == 1 - name = 'NaCl'; - elseif group == 2 - name = 'Remi50'; - elseif goup == 3 - name = 'Remi100'; - end - fprintf(['Sub' num2str(subject) '\nRun' num2str(run) '\nGroup: ' name '\n']); - - - - %%%%%%%%%%%%%%%%%%%%%%%%%%% Put in your experiment choices here - debug = 1; % Use this function to have a transparent screen - p_mri_on = 0; % If on, waits for pulses and useses BrainVision Recorder marking BEFORE it marks CED. Otherwise, it only uses CED marking and sets BVR to 0 - p_slave_on = 0; % If on, waits for pulse from master and starts presentation at the same time. - - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % Initialize Experiment Environment - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - %ListenChar(2); % Disable pressed keys to printed out; Ctrl+C reenables keyboard - commandwindow; - %clear everything without using 'clear all' - clear mex global functions - - %%%%%%%%%%%%%%%%%%%%%%%%%%% Load the GETSECS mex files so call them at - %%%%%%%%%%%%%%%%%%%%%%%%%%% least oncec - GetSecs; - WaitSecs(0.001); %?? Why? - - SetParameters; - - if strcmp(p.hostname,'triostim1') % Automatically disable debug mode if run from fMRI server - debug = 0; - end - - SetPTB; - - - %%%%%%%%%%%%%%%%%%%%%%%%%%% Initialize all variables - nTrial = 0; %?? why are some grey? Bc they are used later on? No... - stimName = []; - itiDuration = []; - CueDuration = []; - TimeCrossOn = []; - TimeCueOn = []; - TimeHeatOn = []; - TimeStarOn = []; - TimeBlankOn = []; - TimeBreathOn = []; - p_stim_white = p.stim.white; - p_stim_red = p.stim.red; - p_stim_backgr = p.stim.backgr; - p_stim_sizeCross = p.stim.sizeCross; - p_stim_widthCross = p.stim.widthCross; - p_monitor_nx = p.monitor.Xaxis; % pixel x-axis - p_monitor_ny = p.monitor.Yaxis; % pixel y-axis - p_com_lpt_CEDaddress = p.com.lpt.CEDaddress; - p_com_lpt_CEDduration = p.com.lpt.CEDduration; - p_com_lpt_scannerPulseOnset = p.com.lpt.scannerPulseOnset; - p_com_lpt_ITIOnset = p.com.lpt.ITIOnset; - % p_com_lpt_CueOnset = p.com.lpt.CueOnset; - p_com_lpt_HeatOnset = p.com.lpt.HeatOnset; - p_com_lpt_VASOnset = p.com.lpt.VASOnset; - p_presentation_itiDuration = p.presentation.itiDuration; - p_presentation_CueDuration = p.presentation.CueDuration; - p_presentation_stimDuration = p.presentation.stimDuration; - p_presentation_blankDuration = p.presentation.blankDuration; - p_presentation_stimSequence = p.presentation.stimSequence; - p_presentation_TrialList = p.trialList; - p_presentation_scaleDuration = p.presentation.scaleDuration; - p_keys_trigger = p.keys.trigger; - p_keys_nextStep = p.keys.nextStep; - p_mri_tr = p.mri.tr; - p_ptb_w = p.ptb.w; - p_ptb_midpoint = p.ptb.midpoint; - p_ptb_midpoint_y = p.ptb.midpoint(2); - p_ptb_rect = p.ptb.rect; - p_ptb_startY = p.ptb.startY; - p_text_linespace = p.text.linespace; - p_ptb_lineheight = p.ptb.lineheight; - - % save again the parameter file - save(p.path.save ,'p'); - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % - % Run Experiment - % - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - putLog(GetSecs, 'Experiment Start'); - fprintf(['=================\n=================\nStart thermode protocol ' num2str(p.presentation.stimSequence) '!!!!\n']); - - % Show Instructions; - ShowInstruction; - - % Wait for Dummy Scans - %firstScannerPulseTime = WaitPulse(p.keys.trigger,p.mri.dummyScan); %?? - %TEMP REMOVAL - commandwindow; - p.log.mriExpStartTime = firstScannerPulseTime(end); - putLog(p.log.mriExpStartTime, 'FirstMRPulse_ExpStart'); - - % Actual stimulus presentation - runExperiment; - - % Show SessionEnd - ShowEndSessionText; - - cleanup; -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% End of Experiment -% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - -%% Set all parameters relevant for the whole experiment and the specific subject - function SetParameters - p.mri.on = p_mri_on; - p.mri.dummyScan = 5; - p.mri.tr = 2.65; - p.slave = p_slave_on; - p.subinfo.subID = subject; - p.subinfo.group = group; % nacl 1 remi50 2 remi100 3 - p.subinfo.run = run; - % p.subinfo.trialList = trialList; - - %%%%%%%%%%%%%%%%%%%%%%%%%%% create log structure - p.log.mriExpStartTime = 0; % Initialize as zero - p.log.events = {{},{},{},{}}; % event count, real time, experiment duration, event string - p.log.ratings1 = []; % event count, real time, experiment duration, event string - p.log.ratings2 = []; - p.log.eventCount = 0; - p.log.rating1EventCount = 0; - p.log.rating2EventCount = 0; - p.log.onratingEventCount = 0; - p.log.moodEventCount = 0; - p.log.scaleDefaultVAS1 = []; - p.log.scaleDefaultVAS2 = []; - - %%%%%%%%%%%%%%%%%%%%%%%%%%% relative paths to stim and experiments - [~, hostname] = system('hostname'); - p.hostname = deblank(hostname); - p.hostaddress = java.net.InetAddress.getLocalHost ; - p.hostIPaddress = char( p.hostaddress.getHostAddress); - if strcmp(p.hostname,'triostim1') - p.path.experiment = 'C:\USER\horing\PMParametric\'; - p.monitor.Xaxis = 1024; % stim PC resolution - p.monitor.Yaxis = 768; % stim PC resolution - else - p.path.experiment = 'C:\Users\Bjoern\Google Drive\_STUDIEN (2014+)\2016_parametric pain matrix\m files\'; - p.monitor.Xaxis = 1920; % stim PC resolution - p.monitor.Yaxis = 1200; % stim PC resolution - end - % - p.subID = sprintf('sub%02d',subject); - p.timestamp = datestr(now,30); - - %define and create subject folder path - p.path.subject = [p.path.experiment 'logs/' p.subID '/']; - mkdir(p.path.subject); - - %??Why doesn't this folder need to be created, too? - %define subfolder of subject folder for current trial number/run - p.path.save = [p.path.subject p.subID '_run' num2str(p.subinfo.run) '_' p.timestamp ]; - - %%%%%%%%%%%%%%%%%%%%%%%%%%% font size, background gray level, monitor settings - p.text.fontname = 'Arial'; - p.text.fontsize = 20; %30; %18; - p.text.linespace = 10; - p.stim.white = [255 255 255]; - p.stim.red = [255 0 0]; - p.stim.backgr = [70 70 70]; - p.stim.widthCross = 3; - p.stim.sizeCross = 20; - p.MoodRating = []; %?? How is this a monitor setting? - p.Rating1 = []; %?? How is this a monitor setting? - p.Rating2 = []; %?? How is this a monitor setting? - - if strcmp(p.hostname,'triostim1') % curdes button box single diamond (HID NAR 12345) - p.keys.confirm = KbName('3#'); % green button - p.keys.right = KbName('4$'); % red button - p.keys.left = KbName('2@'); % yellow button - p.keys.esc = KbName('esc'); - p.keys.nextStep = KbName('space'); - p.keys.trigger = KbName('5%'); - else - %All settings for laptop computer. - KbName('UnifyKeyNames'); - p.keys.confirm = KbName('Return'); - p.keys.right = KbName('RightArrow'); - p.keys.left = KbName('LeftArrow'); - p.keys.esc = KbName('Escape'); - p.keys.nextStep = KbName('space'); - p.keys.trigger = KbName('5'); - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%% Parallel port settings - % Codes for different events - % device Thermode: 4 - % Spike-channel 4 : 32 - % Spike-channel 5 : 64 - % Spike-channel 6 : 128 - - if strcmp(p.hostname,'triostim1') - p.com.lpt.scannerPulseOnset = 224; % start of each run -> 32+64+128 (all 3 channels) - p.com.lpt.HeatOnset = 36; % Cue (spike channel 4) - p.com.lpt.VASOnset = 64; % Heat trigger for thermode plus spike channel 5 - p.com.lpt.ITIOnset = 128; % VAS/Mood scale on (Spike-channel 6) -% p.com.lpt.ITIOnset = 192; % white fixation cross on channel 5 and 6 - else - p.com.lpt.scannerPulseOnset = 0; % start of each run -> 32+64+128 (all 3 channels) - p.com.lpt.CueOnset = 0; % Cue (spike channel 4) - p.com.lpt.HeatOnset = 255; % Heat trigger for thermode - p.com.lpt.VASOnset = 0; % VAS/Mood scale on (Spike-channel 6) - p.com.lpt.ITIOnset = 0; % white fixation cross - end - p.com.lpt.CEDaddress = 888; - p.com.lpt.CEDduration = 0.005; - - %%%%%%%%%%%%%%%%%%%%%%%%%%% Stimulus sequence and startle timings - p.presentation.stimDuration = 17; - p.presentation.blankDuration = 0.5; - iti = [24 24.5 25 25.5 26 26 26.5 27 27.5 28]; -% trialLists = load([p.path.experiment 'trial_seq.mat']); %?? TEMP REMOVAL -% trialLists = trialLists.trial_seq; %?? TEMP REMOVAL -trialLists=[1 2 3 4;1 2 4 3;2 1 3 4;2 1 4 3]; %HILFSKONSTRUKT -% sequence = load([p.path.experiment 'rand_seq.mat']); %?? TEMP REMOVAL -% sequence = sequence.rand_seq; %?? TEMP REMOVAL -sequence=round((4-1).*rand(4,99)+1); %HILFSKONSTRUKT - p.presentation.stimSequence = sequence(run,subject); - p.trialList = trialLists(:,p.presentation.stimSequence); - p.presentation.tTrial = length(p.trialList); %number of trials - p.presentation.itiDuration = iti(randperm(length(iti))); - p.presentation.CueDuration = 4; - p.presentation.scaleDuration = 21; - p.presentation.scaleBackColor = p.stim.backgr; - p.BreathRem = 3; - p.starTime = 0.6; - p.lastITI = 5; - - clearvars trialLists - - %%%%%%%%%%%%%%%%%%%%%%%%%%% Save the parameters for this subject - save(p.path.save ,'p'); - end - -%% Set Up the PTB with parameters and initialize drivers - function SetPTB - screens = Screen('Screens'); % Find the number of the screen to be opened - p.ptb.screenNumber = max(screens); % The maximum is the second monitor - if debug - commandwindow; - PsychDebugWindowConfiguration; % Make everything transparent for debugging purposes. - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%% Default parameters - Screen('Preference', 'SkipSyncTests', 1); - Screen('Preference', 'DefaultFontSize', p.text.fontsize); - Screen('Preference', 'DefaultFontName', p.text.fontname); - %Screen('Preference', 'TextAntiAliasing',2); % Enable textantialiasing high quality - Screen('Preference', 'VisualDebuglevel', 0); % 0 disable all visual alerts - %Screen('Preference', 'SkipSyncTests', 0); - %Screen('Preference', 'SuppressAllWarnings', 0); - if debug == 0; - HideCursor(p.ptb.screenNumber); % Hide the cursor - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%% Open a graphics window using PTB - p.ptb.w = Screen('OpenWindow', p.ptb.screenNumber, p.stim.backgr); - % Screen('TextStyle', p.ptb.w, 1); % Make Text Bold - Screen('Flip',p.ptb.w); % Make the bg - p.ptb.slack = Screen('GetFlipInterval',p.ptb.w)./2; - % [p.ptb.width, p.ptb.height] = Screen('WindowSize', p.ptb.screenNumber); - p.ptb.rect = [0 0 p.monitor.Xaxis p.monitor.Yaxis]; - p.ptb.width = p.monitor.Xaxis; - p.ptb.height = p.monitor.Yaxis; - p.ptb.midpoint = [p.ptb.width./2 p.ptb.height./2]; % Find the mid position on the screen. - - p.ptb.startY = p.monitor.Yaxis/4; - p.ptb.lineheight = p.text.fontsize + p.text.linespace; - - p.ptb.whiteFix1 = [p.ptb.midpoint(1)-p.stim.sizeCross p.ptb.startY-p.stim.widthCross p.ptb.midpoint(1)+p.stim.sizeCross p.ptb.startY+p.stim.widthCross]; - p.ptb.whiteFix2 = [p.ptb.midpoint(1)-p.stim.widthCross p.ptb.startY-p.stim.sizeCross p.ptb.midpoint(1)+p.stim.widthCross p.ptb.startY+p.stim.sizeCross]; - % p.ptb.imrect = [ p.ptb.midpoint(1)-p.stim.width/2 p.ptb.midpoint(2)-p.stim.height/2 p.stim.width p.stim.height]; - - p.ptb.priorityLevel=MaxPriority('GetSecs','KbCheck','KbWait'); - Priority(MaxPriority(p.ptb.w)); - p.ptb.device = []; - - %%%%%%%%%%%%%%%%%%%%%%%%%%% Parallel port communication. - %config_io;%?? TEMP REMOVAL - %outp(p.com.lpt.CEDaddress,0);%?? TEMP REMOVAL - - end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Functions collection -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - function [secs]=WaitPulse(keyCode,n) - %[secs]=WaitPulse(keycode,n) - % - % This function waits for the Nth upcoming pulse. If N=1, it will wait for - % the very next pulse to arrive. 1 MEANS NEXT PULSE. So if you wish to wait - % for 6 full dummy scans, you should use N = 7 to be sure that at least 6 - % full acquisitions are finished. - % - % The function avoids KbCheck, KbWait functions, but relies on the OS - % level event queues, which are much less likely to skip short events. A - % nice discussion on the topic can be found here: - % http://ftp.tuebingen.mpg.de/pub/pub_dahl/stmdev10_D/Matlab6/Toolboxes/Psychtoolbox/PsychDocumentation/KbQueue.html - - %KbQueueFlush;KbQueueStop;KbQueueRelease;WaitSecs(1); - fprintf('Will wait for %i dummy pulses...\n',n); - if n ~= 0 - secs = nan(1,n); - pulse = 0; - dummy = []; - while pulse < n %Listening loop - keyboard - dummy = KbTriggerWait(keyCode,p.ptb.device); - pulse = pulse + 1; - secs(pulse+1) = dummy; - fprintf('Waiting for dummy scan %d\n',pulse); - putLog(dummy,num2str(pulse)); - end - else - secs = GetSecs; - end - end - -%% Start the actual experiment - function runExperiment - for nTrial = 1:p.presentation.tTrial; % Enter the presentation loop - stimName = p_presentation_TrialList(nTrial); - itiDuration = p_presentation_itiDuration(nTrial); - CueDuration = p_presentation_CueDuration; - - if nTrial == 1 % Turn on the fixation cross for the first trial. These have to be done before the main for loop. - Screen('FillRect', p_ptb_w, p_stim_white, p.ptb.whiteFix1); - Screen('FillRect', p_ptb_w, p_stim_white, p.ptb.whiteFix2); - TimeCrossOn = Screen('Flip',p_ptb_w); % gets timing of event for putLog - putMark(p_com_lpt_ITIOnset); % Mark Fixation Cross Onset - putLog(TimeCrossOn, 'FirstITIOnset'); % Log the cross onset... - fprintf('=================\n=================\nFirst ITI, waiting for 5 seconds\n=================\n=================\n'); - while GetSecs < TimeCrossOn + 5 end - end - - fprintf('%d of %d, Stim: %d, CueDuration: %d, itiDuration: %d \n',nTrial,p.presentation.tTrial, stimName(1), CueDuration, itiDuration); - - p.log.scaleDefaultVAS1(nTrial,1) = randi([20,81]); - p.log.scaleDefaultVAS2(nTrial,1) = randi([20,81]); - p.log.scaleDefaultMood(nTrial,1) = randi([3,6]); - - Trial(itiDuration); - - end - - fprintf('=================\n=================\nWait for last scanner pulse of experiment!...\n'); - - mriEnd = KbTriggerWait(p_keys_trigger,p.ptb.device); - putLog(mriEnd, 'mriTrigger'); - putLog(GetSecs, 'ExpEnd'); - end - -%% Present affective Picture - function Trial(itiDuration) %Trial(stimID,stimName,stimStrlOnset,itiDuration,itiStrlOnset,jitter) - - %cue - if p.presentation.stimSequence == 2 && nTrial == 2 || p.presentation.stimSequence == 2 && nTrial == 7 ||... - p.presentation.stimSequence == 4 && nTrial == 1 || p.presentation.stimSequence == 4 && nTrial == 6 - DrawFormattedText(p_ptb_w, 'Im nächsten Durchgang bewerten Sie bitte', 'center',p_ptb_startY-100, p_stim_white); - DrawFormattedText(p_ptb_w, 'die Schmerzhaftigkeit WÄHREND des Hitzereizes!', 'center',p_ptb_startY-70, p_stim_white); - end - - Screen('FillRect', p_ptb_w, p_stim_red, p.ptb.whiteFix1); - Screen('FillRect', p_ptb_w, p_stim_red, p.ptb.whiteFix2); - TimeCueOn = Screen('Flip',p_ptb_w); - putLog(TimeCueOn, 'CueOnset'); - p.reactionTime(nTrial) = getRT(p_presentation_CueDuration,TimeCueOn); % check reaction time during cue - if nTrial > 1 - if isnan(p.reactionTime(end)) && isnan(p.reactionTime(end-1)) - warning(sprintf('\n***********\n***********\nNo RT for 2 Trials!\nPlease check participant!!!\n***********\n***********\n')); - end - end - - %Pain - %online rating scale -% if p.presentation.stimSequence == 2 && nTrial == 2 || p.presentation.stimSequence == 2 && nTrial == 7 ||... -% p.presentation.stimSequence == 4 && nTrial == 1 || p.presentation.stimSequence == 4 && nTrial == 6 - TimeHeatOn = GetSecs; - putMark(p_com_lpt_HeatOnset); - putLog(TimeHeatOn, 'HeatOnset'); - [p.onrating.conRating,p.onrating.conTime,p.onrating.response] = onlineScale(p_ptb_w,p.ptb.rect,... - p_presentation_stimDuration,p_stim_backgr,p_ptb_startY,p.keys,p.starTime); % - putOnRatingLog(nTrial); - -% else % only showing cross during pain -% Screen('FillRect', p_ptb_w, p_stim_red, p.ptb.whiteFix1); % no treatment condition -% Screen('FillRect', p_ptb_w, p_stim_red, p.ptb.whiteFix2); -% TimeHeatOn = Screen('Flip',p_ptb_w); -% putMark(p_com_lpt_HeatOnset); -% putLog(TimeHeatOn, 'HeatOnset'); -% fprintf('Heat on\n'); -% while GetSecs < TimeHeatOn + (p_presentation_stimDuration/2.5) end % = WaitSecs(p_presentation_stimDuration); -% %Show star for rating -% Screen('TextSize',p_ptb_w,p.text.fontsize+40); -% Screen('FillRect', p_ptb_w, p_stim_red, p.ptb.whiteFix1); % no treatment condition -% Screen('FillRect', p_ptb_w, p_stim_red, p.ptb.whiteFix2); -% Screen('DrawText', p_ptb_w,'*',p.ptb.midpoint(1)-14,p.ptb.startY-60,p_stim_white); -% TimeStarOn = Screen('Flip',p_ptb_w); -% putLog(TimeStarOn, 'StarOnset'); -% fprintf('Star on\n'); -% while GetSecs < TimeStarOn + p.starTime end -% Screen('FillRect', p_ptb_w, p_stim_red, p.ptb.whiteFix1); % no treatment condition -% Screen('FillRect', p_ptb_w, p_stim_red, p.ptb.whiteFix2); -% TimeHeatOn2 = Screen('Flip',p_ptb_w); -% -% while GetSecs < TimeStarOn + (p_presentation_stimDuration - (p_presentation_stimDuration/2.5)) end % = WaitSecs(p_presentation_stimDuration); -% end - - %blank screen - TimeBlankOn = Screen('Flip',p_ptb_w); - while GetSecs < TimeBlankOn + p_presentation_blankDuration end % = WaitSecs(p_presentation_blankDuration); - putLog(TimeBlankOn, 'BlankOnset'); - - %VAS T3 - putLog(GetSecs, 'VAS1Onset'); - putMark(p_com_lpt_VASOnset); - fprintf('VAS_T3 on\n'); - - [p.rating1.finalRating,p.rating1.reactionTime,p.rating1.response] = vasScaleT3(p_ptb_w,p.ptb.rect,... - p_presentation_scaleDuration,p.log.scaleDefaultVAS1(nTrial,1),p_stim_backgr,p_ptb_startY,p.keys); % - putRating1Log(nTrial); - p.Rating1(nTrial) = p.rating1.finalRating; - - %blank screen - TimeBlankOn = Screen('Flip',p_ptb_w); - while GetSecs < TimeBlankOn + p_presentation_blankDuration end % = WaitSecs(p_presentation_blankDuration); - putLog(TimeBlankOn, 'BlankOnset'); - - %VAS peak - putLog(GetSecs, 'VAS2Onset'); - putMark(p_com_lpt_VASOnset); - fprintf('VAS_peak on\n'); - - [p.rating2.finalRating,p.rating2.reactionTime,p.rating2.response] = vasScaleT2(p_ptb_w,p.ptb.rect,... - p_presentation_scaleDuration,p.log.scaleDefaultVAS2(nTrial,1),p_stim_backgr,p_ptb_startY,p.keys,p.rating1.finalRating); % - putRating2Log(nTrial); - p.Rating2(nTrial) = p.rating2.finalRating; - - %blank screen - TimeBlankOn = Screen('Flip',p_ptb_w); - while GetSecs < TimeBlankOn + p_presentation_blankDuration end % = WaitSecs(p_presentation_blankDuration); - putLog(TimeBlankOn, 'BlankOnset'); - - %Mood - putLog(GetSecs, 'MoodOnset'); - fprintf('Mood on\n'); - - [p.mood.finalRating,p.mood.reactionTime,p.mood.response] = moodScale(p_ptb_w,p.ptb.rect,... - p_presentation_scaleDuration,p.log.scaleDefaultMood(nTrial,1),p_stim_backgr,p_ptb_startY,p.keys); %p.log.scaleDefaultVAS(nTrial,1) - putMoodLog(nTrial); - p.MoodRating(nTrial) = p.mood.finalRating; - if nTrial > 1 - if p.MoodRating(end)+3 <= p.MoodRating(end-1) - warning(sprintf('\n***********\n***********\nParticipant rated 3 points less!\nPlease check participant!!!\n***********\n***********\n')); - end - end - -% %Breath -% Screen('TextSize',p_ptb_w,p.text.fontsize); -% p_monitor_ny = p.monitor.Yaxis/4; -% [p_monitor_nx, p_monitor_ny, textbounds]=DrawFormattedText(p_ptb_w, 'Bitte achten Sie darauf,', 'center', p_monitor_ny, p_stim_white); -% [p_monitor_nx, p_monitor_ny, textbounds]=DrawFormattedText(p_ptb_w, 'ruhig und gleichmäßig durch die Nase zu atmen.', 'center', p_monitor_ny+p_ptb_lineheight, p_stim_white); -% -% fprintf('Breath Reminder\n'); -% TimeBreathOn = Screen('Flip',p_ptb_w); -% putLog(TimeBreathOn, 'BreathOnset'); -% while GetSecs < TimeBreathOn + p.BreathRem end - - %ITI - p.presentation.itiDurationReal(nTrial) = (itiDuration + p.lastITI) - (p.mood.reactionTime+p.rating1.reactionTime+p.rating2.reactionTime); - -% if p.presentation.itiDurationReal(nTrial) > 0 - Screen('FillRect', p_ptb_w, p_stim_white, p.ptb.whiteFix1); - Screen('FillRect', p_ptb_w, p_stim_white, p.ptb.whiteFix2); - TimeCrossOn = Screen('Flip',p_ptb_w); - putMark(p_com_lpt_ITIOnset); - putLog(TimeCrossOn, 'ITIOnset'); - fprintf(['Remaining ITI duration: ' num2str(p.presentation.itiDurationReal(nTrial)) '\n']); - while GetSecs < (TimeCrossOn + p.presentation.itiDurationReal(nTrial)) end -% else -% Screen('FillRect', p_ptb_w, p_stim_white, p.ptb.whiteFix1); -% Screen('FillRect', p_ptb_w, p_stim_white, p.ptb.whiteFix2); -% TimeCrossOn = Screen('Flip',p_ptb_w); -% putLog(TimeCrossOn, 'ITIOnset'); -% putMark(p_com_lpt_ITIOnset); -% while GetSecs < TimeCrossOn + 5 end -% % fprintf('adding seconds to ITI to show breathing reminder\n'); -% % p.presentation.itiDurationReal(nTrial) = p.presentation.itiDurationReal(nTrial) + abs(p.presentation.itiDurationReal(nTrial) - p.BreathRem); -% end -% - save(p.path.save ,'p'); - end - -%% Instruction Text - function ShowInstruction - if run == 1 - p_monitor_ny = p.monitor.Yaxis/8; - [p_monitor_nx, p_monitor_ny, textbounds]=DrawFormattedText(p_ptb_w, 'Gleich beginnt das Experiment.', 'center', p_monitor_ny, p_stim_white); - [p_monitor_nx, p_monitor_ny, textbounds]=DrawFormattedText(p_ptb_w, 'Bleiben Sie die ganze Zeit so ruhig wie möglich liegen!', 'center', p_monitor_ny+p_ptb_lineheight, p_stim_white); - [p_monitor_nx, p_monitor_ny, textbounds]=DrawFormattedText(p_ptb_w, 'Haben Sie noch Fragen?', 'center', p_monitor_ny+p_ptb_lineheight, p_stim_white); - [p_monitor_nx, p_monitor_ny, textbounds]=DrawFormattedText(p_ptb_w, 'Sonst geht es jetz los!', 'center', p_monitor_ny+p_ptb_lineheight, p_stim_white); - else - [p_monitor_nx, p_monitor_ny, textbounds]=DrawFormattedText(p_ptb_w, 'Es geht gleich los...', 'center', p.ptb.startY, p_stim_white); - end - - introTextTime = Screen('Flip',p_ptb_w); - putLog(introTextTime,'IntroTextOn'); - WaitSecs(1); - - fprintf('=================\n=================\nInput "%s" required to continue...\n',p_keys_nextStep); - - while 1 %?? Listening loop - [keyIsDown, ~, keyCode] = KbCheck(); % Start waiting 1/2 TR before JitterOnset for next pulse (this avoids collecting Pulses before). %?? what's with the tilde ~? - if keyIsDown - if find(keyCode) == p_keys_nextStep; - break; - end - end - end - - %FlushEvents('keyDown'); %?? can't hurt, can it? - - StartWaitTime = Screen('Flip',p_ptb_w); - putLog(StartWaitTime, 'WaitForExpStartOnset'); - - fprintf('=================\n=================\nAsk if subject is alright\nThen tell MTA to start scanner!!!!!!!!...\n'); - fprintf('=================\n=================\nWill wait %d volumes for dummy...\n',p.mri.dummyScan); - end - -%% End session Text - function ShowEndSessionText - Screen('TextSize',p_ptb_w,p.text.fontsize); - if run == 8 - [p_monitor_nx, p_monitor_ny, textbounds]=DrawFormattedText(p_ptb_w, 'Das Experiment ist beendet.', 'center', p.ptb.start, p_stim_white); - [p_monitor_nx, p_monitor_ny, textbounds]=DrawFormattedText(p_ptb_w, 'Vielen Dank!', 'center', p_monitor_ny+p_ptb_lineheight, p_stim_white); - else - [p_monitor_nx, p_monitor_ny, textbounds]=DrawFormattedText(p_ptb_w, 'Ende des Durchgangs.', 'center', p.ptb.startY, p_stim_white); - [p_monitor_nx, p_monitor_ny, textbounds]=DrawFormattedText(p_ptb_w, 'Es geht gleich weiter!', 'center', p_monitor_ny+p_ptb_lineheight, p_stim_white); - end - - endTextTime = Screen('Flip',p_ptb_w); - putLog(endTextTime,'EndTextOn'); - - WaitSecs(1); - - while 1 - [keyIsDown, ~, keyCode] = KbCheck(); % Start waiting 1/2 TR before JitterOnset for next pulse (this avoids collecting Pulses before). - if keyIsDown - if find(keyCode) == p_keys_nextStep; - break; - end - end - end - end - -%% get reaction time - function reactionTime = getRT(durCue,startTime) - response = 0; - numberOfSecondsRemaining = durCue; - while numberOfSecondsRemaining > 0 - - if response == 0 - - [ keyIsDown, secs, keyCode ] = KbCheck; % this checks the keyboard very, very briefly. - if keyIsDown % only if a key was pressed we check which key it was - response = 0; % predefine variable for confirmation button 'space' - if keyCode(p.keys.confirm) - response = 1; - reactionTime = secs - startTime; - disp(['Reaction Time: ' num2str(reactionTime)]); - flip_confKey = GetSecs; - SecondsRemaining = durCue-(flip_confKey-startTime); - WaitSecs(SecondsRemaining); - break; - end - end - end - numberOfSecondsElapsed = (GetSecs - startTime); - numberOfSecondsRemaining = durCue - numberOfSecondsElapsed; - end - - if response == 0 - warning(sprintf('\n***********\n***********\nNo Response!\nPlease check participant!!!\n***********\n***********\n')); - reactionTime = NaN; - end - - end -%% Set Marker for CED and BrainVision Recorder - function putMark(port) - % Send pulse to CED for SCR, thermode, digitimer - % [handle, errmsg] = IOPort('OpenSerialport',num2str(port)); - outp(p_com_lpt_CEDaddress,port); - WaitSecs(p_com_lpt_CEDduration); - outp(p_com_lpt_CEDaddress,0); - % IOPort('CloseAll'); - end - -%% Log all events - function putLog(ptb_time, event_info) - p.log.eventCount = p.log.eventCount + 1; - p.log.events(p.log.eventCount,1) = {p.log.eventCount}; - p.log.events(p.log.eventCount,2) = {ptb_time}; - p.log.events(p.log.eventCount,3) = {ptb_time-p.log.mriExpStartTime}; - p.log.events(p.log.eventCount,4) = {event_info}; - end - function putOnRatingLog(currentTrial) - p.log.onratingEventCount = p.log.onratingEventCount + 1; - p.log.onratings.conTrial(p.log.onratingEventCount,1) = {currentTrial}; - p.log.onratings.conRating(:,p.log.onratingEventCount) = {p.onrating.conRating}; - p.log.onratings.conTime(:,p.log.onratingEventCount) = {p.onrating.conTime}; - p.log.onratings.conRes(p.log.onratingEventCount,1) = {p.onrating.response}; - end - function putRating1Log(currentTrial) - p.log.rating1EventCount = p.log.rating1EventCount + 1; - p.log.ratings1(p.log.rating1EventCount,1) = currentTrial; - p.log.ratings1(p.log.rating1EventCount,2) = p.rating1.finalRating; - p.log.ratings1(p.log.rating1EventCount,3) = p.rating1.response; - p.log.ratings1(p.log.rating1EventCount,4) = p.rating1.reactionTime; - end - - function putRating2Log(currentTrial) - p.log.rating2EventCount = p.log.rating2EventCount + 1; - p.log.ratings2(p.log.rating2EventCount,1) = currentTrial; - p.log.ratings2(p.log.rating2EventCount,2) = p.rating2.finalRating; - p.log.ratings2(p.log.rating2EventCount,3) = p.rating2.response; - p.log.ratings2(p.log.rating2EventCount,4) = p.rating2.reactionTime; - end - - function putMoodLog(currentTrial) - p.log.moodEventCount = p.log.moodEventCount + 1; - p.log.mood(p.log.moodEventCount,1) = currentTrial; - p.log.mood(p.log.moodEventCount,2) = p.mood.finalRating; - p.log.mood(p.log.moodEventCount,3) = p.mood.response; - p.log.mood(p.log.moodEventCount,4) = p.mood.reactionTime; - end - -%% After experiment is over clean everything and close drivers - function cleanup - sca; % Close window: - commandwindow; - ListenChar(0); % Use keys again - %KbQueueRelease(p_ptb_device); - save(p.path.save ,'p'); - if run == 4 - diary off; - end - end - -end - - - - - diff --git a/exp_PainThreshold.m b/exp_PainThreshold.m deleted file mode 100755 index 9e15045..0000000 --- a/exp_PainThreshold.m +++ /dev/null @@ -1,407 +0,0 @@ -function [p]=exp_PainThreshold(subject,varargin) - -clear mex global functions -cgshut; -if ~isempty(varargin) - debug = varargin{1}; -else - debug = 0; -end -global cogent; -% -p = []; -log_threshold =[]; -% -SetParams; -SetPTB; -SCRCheck; -MarkCED(p.lpt.address,p.lpt.InitExperiment); -GetThreshold; -save(p.path.filename,'p'); -%%now give the subject a final shock with the "tobeused level" and ask -%%whether it is bearable. -%factor = input('Enter the desired factor (for example 1.4). Start with the highest :).\n'); -%ConfirmIntensity(factor); -save(p.path.filename,'p'); -% -ShowInstruction(6); - -%move the file to its final location. -movefile(p.path.subject,p.path.finalsubject); -cleanup; - - - function GetThreshold - - %message to show on the rating screen. - message = 'War der Reiz schmerzhaft oder nicht?\nBewege den "Zeiger" mit der rechten und linken Pfeiltaste\n und bestätige deine Einschätzung mit der mit der oberen Pfeiltaste.'; - % - p.threshold.init.alphas = log(0.1):0.177/100:log(50); - p.threshold.init.prior = PAL_pdfNormal(p.threshold.init.alphas, log(3), log(2.5)); - p.threshold.init.stopcriterion = 'trials'; - p.threshold.init.stoprule = 12; - p.threshold.init.PFfit = @PAL_Gumbel; - p.threshold.init.beta = 3.5; - p.threshold.init.lambda = 0; - p.threshold.init.gamma = 0; - p.threshold.init.meanmode = 'mode'; - p.threshold.final.factor = [1.5 2 2.5]; - % - p.threshold.RF = PAL_AMRF_setupRF('priorAlphaRange', p.threshold.init.alphas, 'prior', p.threshold.init.prior,... - 'stopCriterion',p.threshold.init.stopcriterion,'stoprule',p.threshold.init.stoprule,'beta',p.threshold.init.beta,'gamma',p.threshold.init.gamma,... - 'lambda',p.threshold.init.lambda,'PF',p.threshold.init.PFfit,'meanmode',p.threshold.init.meanmode); - % - p.threshold.RF.xCurrent = log(1);%start shock; - % - response_mapping = [1 0]; - ShowInstruction(4); - % - counter = 0; - close all; - while ~p.threshold.RF.stop - % - counter = counter + 1; - fprintf([repmat('=',1,50) '\n']); - fprintf('SHOCK No: %d of %d.\n',counter,p.threshold.init.stoprule); - fprintf('!!! ADJUST THE SHOCK INTENSITY ON THE DIGITIMER !!!\n'); - fprintf(' The intensity is now: %g\n',exp(p.threshold.RF.xCurrent)); - fprintf(' Experimenter: Press any key to deliver a shock.\n'); - fprintf(' Or escape to quit prematurely.\n'); - fprintf([repmat('=',1,50) '\n']); - % - [secs, keyCode, deltaSecs] = KbStrokeWait; - if find(keyCode ) == p.keys.esc - p.threshold.RF.stop = 1; - else - ShowInstruction(5);%shock is coming message, stays ~2 sec... - %prepare for the shock - MarkCED(p.lpt.address,p.lpt.ShockOnset) - t = GetSecs + p.duration.shock; - while GetSecs < t; - Buzz; - end - %Ask for rating - [response] = RatingSlider(p.ptb.rect,2,Shuffle(1:2,1),p.keys.increase,p.keys.decrease,p.keys.confirm,{ 'nicht\nschmerzhaft' 'schmerzhaft'},message,0); - response = response_mapping(response); - % - response = logical(response); - amplitude = p.threshold.RF.xCurrent; - p.threshold.RF = PAL_AMRF_updateRF(p.threshold.RF, amplitude, response); - % - plot(p.threshold.RF.priorAlphaRange,p.threshold.RF.pdf,'r') - drawnow; -% % % RF = p.threshold.RF; -% % % figure(1);set(gcf,'position',[940 770 360 206]) -% % % x = 1:length(RF.x); -% % % plot(x,exp(RF.x),'o-'); -% % % hold on; -% % % plot(x(RF.response == 1),exp(RF.x(RF.response == 1)),'.-') -% % % drawnow -% % % figure(2);set(gcf,'position',[941 485 361 212]) -% % % plot(x,log(exp(RF.x)),'o-'); -% % % hold on; -% % % plot(x(RF.response == 1),log(exp(RF.x(RF.response == 1))),'.-') -% % % drawnow -% % % figure(3) -% % % set(gcf,'position',[940 294 362 115]) -% % % %plot(exp(alphas),RF.pdf,'r'); - end - end - log_threshold = p.threshold.RF.(p.threshold.init.meanmode); - p.threshold.final.estimated = exp(log_threshold); - - fprintf('\n\n\nRESULT:\n'); - fprintf('The estimated pain threshold : %g mA\n',p.threshold.final.estimated); - fprintf('Choose an intensity:\n'); - fprintf('Intensity to be used for factor x 1.2): %g mA\n',exp(log_threshold.*p.threshold.final.factor(1))); - fprintf('Intensity to be used for factor x 1.3): %g mA\n',exp(log_threshold.*p.threshold.final.factor(2))); - fprintf('Intensity to be used for factor x 1.4): %g mA\n',exp(log_threshold.*p.threshold.final.factor(3))); - fprintf('We will now ask whether this is bearable...\n'); - end - function ConfirmIntensity(factor) - % - if log_threshold > 0 - I = exp(log_threshold*factor); - else - I = exp(log_threshold*(1-factor)); - end - % - ShowInstruction(1); - % - fprintf([repmat('=',1,50) '\n']); - fprintf('TEST SHOCK:\n'); - fprintf('!!! ADJUST THE SHOCK INTENSITY ON THE DIGITIMER !!!\n'); - fprintf(' The intensity is now: %g mA\n',I); - fprintf(' Experimenter: Press any key to deliver a shock.\n'); - fprintf([repmat('=',1,50) '\n']); - % - [secs, keyCode, deltaSecs] = KbStrokeWait; - ShowInstruction(5);%shock is coming message... - MarkCED(p.lpt.address,p.lpt.ShockOnset) - t = GetSecs + p.duration.shock; - while GetSecs < t; - Buzz; - end - % - message = 'Bewege den "Zeiger" mit der rechten und linken Pfeiltaste\n und bestätige deine Einschätzung mit der mit der oberen Pfeiltaste.'; - [p.threshold.confirmation.response] = RatingSlider(p.ptb.rect,2,1,p.keys.increase,p.keys.decrease,p.keys.confirm,{ 'nicht\nerträglich' 'erträglich'},message,0); - if p.threshold.confirmation.response == 1 - fprintf('All is fine :)\n'); - fprintf('Subject confirmed the shock intensity...\n') - fprintf('INTENSITY TO BE USED FOR THE MAIN EXPERIMENT: %g mA\n',I); - p.threshold.final.tobeused = I; - return; - elseif p.threshold.confirmation.response == 2 - fprintf('Shit... :(, %g is too much for the subject\n',I); - fprintf('We will try a little milder intensity.\n'); - factor = factor - 0.05; - ConfirmIntensity(factor); - end - - - end - function SetParams - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %relative path to stim and experiments - %Path Business. - p.path.baselocation = 'C:\Users\onat\Documents\Experiments\'; - p.path.experiment = [p.path.baselocation 'PainThreshold\']; - % - p.name = subject; - timestamp = datestr(now,30); - p.path.subject = [p.path.experiment 'data\tmp\' p.name '_' timestamp '\']; - p.path.finalsubject = [p.path.experiment 'data\' p.name '_' timestamp ]; - mkdir(p.path.subject); - p.path.filename = [regexprep(p.path.subject,'\\','\\\') 'param.mat' ]; - %font size and background gray level - p.text.fontname = 'Times New Roman'; - p.text.fontsize = 30; - %where to place text on the screen; - p.text.start_x = 60; - p.textstart_y = 275; - % - p.stim.bg = [0.47 0.47 0.47]*255;%background color - p.stim.bg_rating = [0 0.47 0].*255; - p.stim.white = [255 255 255]; - p.stim.crossy = 30;%crosshair position - % - p.size_RatingScale = 200;%size of the rating scale in pixels. The actual size is 2x. - %All settings for laptop computer. - p.keys.confirm = KbName('up'); - p.keys.increase = KbName('right'); - p.keys.decrease = KbName('left'); - p.keys.space = KbName('space'); - p.keys.esc = KbName('esc'); - %parallel port - p.lpt.address = 888; - p.lpt.digitimer = 128; - p.lpt.ShockOnset = 16; - p.lpt.InitExperiment = 64; - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %timing business - p.duration.shock = 0.1;%s;x - p.duration.shockpulse = 0.005;%ms; duration of each individual pulses - p.duration.intershockpulse = 0.01;%ms; and the time between each pulse - - % - %Save the stuff - save(p.path.filename,'p'); - end - function [rating]=RatingSlider(rect,tSection,position,up,down,confirm,labels,message,numbersOn) - % - %Detect the bounding boxes of the labels. - for nlab = 1:2 - [nx ny bb(nlab,:)]=DrawFormattedText(p.ptb.w,labels{nlab}, 'center', 'center', p.stim.white,[],[],[],2); - Screen('FillRect',p.ptb.w,p.stim.bg); - end - bb = max(bb); - bb_size = bb(3)-bb(1);%vertical size of the bb. - % - DrawSkala; - ok = 1; - while ok == 1 - [secs, keyCode, deltaSecs] = KbStrokeWait; - - keyCode = find(keyCode); - if (keyCode == up) | (keyCode == down) - next = position + increment(keyCode); - if next < (tSection+1) & next > 0 - position = position + increment(keyCode); - rating = tSection - position + 1; - end - DrawSkala; - elseif keyCode == confirm - WaitSecs(0.1); - ok = 0; - Screen('FillRect',p.ptb.w,p.stim.bg); - Screen('Flip',p.ptb.w); - end - end - - function DrawSkala - rating = tSection - position + 1; - increment([up down]) = [1 -1];%delta - tick_x = linspace(rect(1),rect(1)+rect(3),tSection+1);%tick positions - tick_size = rect(3)./tSection; - ss = tick_size/5*0.9;%slider size. - % - for tick = 1:length(tick_x)%draw ticks - Screen('DrawLine', p.ptb.w, [255 0 0], tick_x(tick), rect(2), tick_x(tick), rect(2)+rect(4) , 3); - if tick <= tSection && numbersOn - Screen('TextSize', p.ptb.w,p.text.fontsize./2); - DrawFormattedText(p.ptb.w, mat2str(tick) , tick_x(tick)+ss/2, rect(2)+rect(4), p.stim.white); - Screen('TextSize', p.ptb.w,p.text.fontsize); - end - if tick == 1 - DrawFormattedText(p.ptb.w, labels{1},tick_x(tick)-bb_size*1.2,rect(2), p.stim.white); - elseif tick == tSection+1 - DrawFormattedText(p.ptb.w, labels{2},tick_x(tick)+bb_size*0.2,rect(2), p.stim.white); - end - end - %slider coordinates - slider = [ tick_x(position)+tick_size*0.1 rect(2) tick_x(position)+tick_size*0.9 rect(2)+rect(4)]; - %draw the slider - Screen('FillRect',p.ptb.w, p.stim.white, round(slider)); - Screen('TextSize', p.ptb.w,p.text.fontsize./2); - DrawFormattedText(p.ptb.w,message, 'center', p.ptb.midpoint(2)*0.2, p.stim.white,[],[],[],2); - Screen('TextSize', p.ptb.w,p.text.fontsize); - Screen('Flip',p.ptb.w); - end - end - function ShowInstruction(nInstruct) - - [text]=GetText(nInstruct); - ShowText(text); - %let subject read it and ask confirmation to proceed. But we don't - %need that in the case of INSTRUCT = 5; - if nInstruct == 5 %this is for the Reiz kommnt - WaitSecs(0.5+rand(1)); - elseif nInstruct == 6 - WaitSecs(3); - else - KbStrokeWait; - end - Screen('FillRect',p.ptb.w,p.stim.bg); - Screen('Flip',p.ptb.w); - function ShowText(text) - - - Screen('FillRect',p.ptb.w,p.stim.bg); - %DrawFormattedText(p.ptb.w, text, p.text.start_x, 'center',p.stim.white,[],[],[],2,[]); - DrawFormattedText(p.ptb.w, text, 'center', 'center',p.stim.white,[],[],[],2,[]); - Screen('Flip',p.ptb.w); - - %show the messages at the experimenter screen - fprintf([repmat('=',1,50) '\n']); - fprintf('Subject''s monitor:\n'); - fprintf(text); - fprintf([repmat('=',1,50) '\n']); - - end - function [text]=GetText(nInstruct); - if nInstruct == 1%Baseline Phase - %=================================================================================================================% - text = ['Gib bitte an ob die Reizstärke des folgenden Schocks\nfür dich erträglich ist.\n'... - '\n'... - 'Drücke bitte die mittlere Taste um den Reiz zu bekommen.\n'... - ]; - - - elseif nInstruct == 4%shock calibration - text = ['Wir werden nun deine Schmerzschwelle bestimmen.\n'... - '\n'... - 'Dafür wirst du mehrere (~10) elektrische Reize bekommen.\n' ... - '\n'... - 'Bitte gib jeweils nach jedem Reiz an, ob er schmerzhaft war oder nicht.\n'... - '\n'... - 'Wenn du noch fragen hast, kannst du jetzt den Versuchsleiter fragen.\n'... - '\n'... - 'Drücke ansonsten die mittlere Taste,\n'... - ' um das Experiment fortzusetzen.\n' ... - ]; - elseif nInstruct == 5%just before the shock - text = ['Reiz kommt...\n']; - elseif nInstruct == 6%transition. - - text = ['Damit ist dieser Teil zu Ende.\n' ... - '\n'... - 'Wir machen nun mit der nächsten Phase weiter.\n'... - ]; - - else - text = {''}; - end - end - end - function SetPTB - %Open a graphics window using PTB - screens = Screen('Screens'); - screenNumber = 1; - %make everything transparent for debuggin purposes. - if debug - commandwindow; - PsychDebugWindowConfiguration; - end - Screen('Preference', 'SkipSyncTests', 1); - Screen('Preference', 'DefaultFontSize', p.text.fontsize); - Screen('Preference', 'DefaultFontName', p.text.fontname); - % - [p.ptb.w ] = Screen('OpenWindow', screenNumber, p.stim.bg); - [p.ptb.width, p.ptb.height] = Screen('WindowSize', screenNumber); - %find the mid position. - p.ptb.midpoint = [ p.ptb.width./2 p.ptb.height./2]; - %area of the slider - p.ptb.rect = [p.ptb.midpoint(1)*0.5 p.ptb.midpoint(2)*0.8 p.ptb.midpoint(1) p.ptb.midpoint(2)*0.2]; - %compute the cross position. - [nx ny bb] = DrawFormattedText(p.ptb.w,'+','center','center'); - Screen('FillRect',p.ptb.w,p.stim.bg); - p.ptb.cross_shift = [45 50];%upper and lower cross positions - p.ptb.CrossPosition_y = [ny-p.ptb.cross_shift(1) ny+p.ptb.cross_shift(2) ]; - p.ptb.CrossPosition_x = [bb(1) bb(1)]; - p.ptb.CrossPositionET_x = [p.ptb.midpoint(1) p.ptb.midpoint(1)]; - p.ptb.CrossPositionET_y = [p.ptb.midpoint(2)-p.ptb.cross_shift(2) p.ptb.midpoint(2)+p.ptb.cross_shift(2)]; - % - Priority(MaxPriority(p.ptb.w)); - %prepare parallel port communication. This relies on cogent i - %think. - config_io; - outp(p.lpt.address,0); - if( cogent.io.status ~= 0 ) - error('inp/outp installation failed'); - end - end - function shuffled = Shuffle(vector,N) - %takes first N from the SHUFFLED before outputting. This function - %could be used as a replacement for randsample - if nargin < 2;N = length(vector);end - [dummy, idx] = sort(rand([1 length(vector)])); - shuffled = vector(idx(1:N)); - shuffled = shuffled(:); - end - function MarkCED(socket,port) - %send pulse to SCR# - outp(socket,port); - WaitSecs(0.01); - outp(socket,0); - end - function Buzz - outp(p.lpt.address, p.lpt.digitimer ); - WaitSecs(p.duration.shockpulse); - outp(p.lpt.address, 0); - WaitSecs(p.duration.intershockpulse); - end - function cleanup - % Close window: - sca; - commandwindow; - end - function SCRCheck - fprintf([repmat('!',1,50) '\n']); - fprintf([repmat('!',1,50) '\n']); - fprintf([repmat('!',1,50) '\n']); - fprintf('Did you TURN ON the SCR ????\n Press a key to continue...\n'); - KbStrokeWait; - end -end diff --git a/exp_Prime.m b/exp_Prime.m deleted file mode 100644 index 4e1a5f3..0000000 --- a/exp_Prime.m +++ /dev/null @@ -1,694 +0,0 @@ -function [p]=exp_Prime(subject,stim_id,prime_id) - - -debug = 1;%debug mode - -%clear everything -clear mex global functions -%%%%%%%%%%%load the GETSECS mex files so call them at least once -GetSecs; -WaitSecs(0.001); -% -el = []; -p = []; -SetParams; -SetPTB; -%% init some variables so that they are global. -t = []; -nTrial = 0; -TimeEndStim = []; -TimeStartShock = []; -TimeTrackerOff = []; -TimeCrossOn = []; -p_var_ExpPhase = []; -p_var_event_count = 0; -%% -InitEyeLink; -WaitSecs(2); -%calibrate if we are at the scanner computer. -if strcmp(p.hostname,'triostim1') || strcmp(p.hostname,'etpc'); - CalibrateEL; -end -%save again the parameter file -save(p.path.path_param,'p'); -% ShowInstruction(1,1); -% -PresentStimuli; - -%get the eyelink file back to this computer -StopEyelink(p.path.edf); -%% trim the log file and save -p.out.log = p.out.log(sum(isnan(p.out.log),2) ~= size(p.out.log,2),:); -%shift the time so that the first timestamp is equal to zero -p.out.log(:,1) = p.out.log(:,1) - p.out.log(1); -p.out.log = p.out.log;%copy it to the output variable. -save(p.path.path_param,'p'); -% -%move the file to its final location. -movefile(p.path.subject,p.path.finalsubject); -%close everything down -cleanup; -%% - function PresentStimuli - %Enter the presentation loop and wait for the first pulse to - %arrive. - TimeEndStim = GetSecs;%this is now - for nTrial = 1:p.presentation.tTrial; - % - %Get the variables that Trial function needs. - stim_id = p.presentation.stim_id(nTrial); - prime_id = p.presentation.prime_id(nTrial); - P_OnsetTime = TimeEndStim + p.duration.ISI - (p.duration.stim + p.duration.prime);%this is when the prime has to be ON. - KbQueueStart(p.ptb.device);%monitor keypresses... - - %Start with the trial, here is time-wise sensitive must be optimal - fprintf('Trial %d of %d; stim_id: %d, prime_id: %d\n',nTrial,p.presentation.tTrial,stim_id,prime_id); - Trial( nTrial , P_OnsetTime, stim_id , prime_id ); - AskStimRating; - TimeEndStim = GetSecs; - % - [keypressed, firstPress]=KbQueueCheck(p.ptb.device); - - %if the press was after stimulus onset and before stimulus offset - if keypressed && (firstPress(p.keys.confirm) > P_OnsetTime) && (firstPress(p.keys.confirm) < TimeEndStim) - p.out.response(nTrial) = 1; - Log(firstPress(p.keys.confirm),7,NaN);%log the key press for hit detection. - fprintf('Subject Pressed the %d Key!!\n',find(keypressed)); - end - end - end - function [TimeEndStim]=Trial(nTrial, TimePrimeOnset , stim_id, prime_id) - %% get all the times - TimeStimOnset = TimePrimeOnset + p.duration.prime; - TimeCrossOnset = TimePrimeOnset - p.duration.fixcross;%first a cross will be set. - TimeEndStim = TimePrimeOnset + p.duration.stim + p.duration.prime;% - TimeTrackerOff = TimeEndStim + p.duration.keep_recording;%you want to record a bit more than necessary - %% START RECORDING NOW - StartEyelinkRecording(nTrial,stim_id,prime_id); - %% Fixation Onset - FixCross = [fix(1)-1,fix(2)-20,fix(1)+1,fix(2)+20;fix(1)-20,fix(2)-1,fix(1)+20,fix(2)+1]; - Screen('FillRect', p.ptb.w, [255,255,255], FixCross'); - TimeCrossOn = Screen('Flip',p.ptb.w,TimeCrossOnset,0); - Eyelink('Message', 'FX Onset at %d %d',fix(1),fix(2)); - Log(TimeCrossOn,1,stim_id);%cross onset. - %% PRIME ONSET - Screen('DrawTexture', p.ptb.w, p.ptb.stim_sprites(prime_id));%Draw the prime to the buffer - Screen('DrawingFinished',p.ptb.w,0); - TimePrimeOnset = Screen('Flip',p.ptb.w,TimePrimeOnset,0);% turn it ON when time is correct - % send eyelink a marker asap - Eyelink('Message', 'Stim Onset'); - Eyelink('Message', 'SYNCTIME'); - %% STIM ONSET - Screen('DrawTexture', p.ptb.w, p.ptb.stim_sprites(stim_id)); - Screen('DrawingFinished',p.ptb.w,0); - TimeStimOnset = Screen('Flip',p.ptb.w,TimeStimOnset,0); - %% STIM OFF immediately - TimeEndStim = Screen('Flip',p.ptb.w,TimeEndStim,0); - %send eyelink and ced a marker - Eyelink('Message', 'Stim Offset'); - Eyelink('Message', 'BLANK_SCREEN'); - % - Log(TimePrimeOnset,2,prime_id);%log the stimulus onset - Log(TimeStimOnset,2,stim_id);%log the stimulus onset - Log(TimeEndStim,-2,stim_id);%log the stimulus offset - %% record some more eye data after stimulus offset. - WaitSecs('UntilTime',TimeTrackerOff); - TimeTrackerOff = StopEyelinkRecording; - end - function SetParams - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %relative path to stim and experiments - %Path Business. - [~, hostname] = system('hostname'); - p.hostname = deblank(hostname); - p.path.experiment = '/Users/onat/Documents/PrimeAfford/'; - if exist(p.path.experiment) == 0 - fprintf('Baselocation:\n %s doesn''t exist\n will create it\n',p.path.baselocation); - keyboard - end - p.path.stim = [p.path.experiment 'stim' filesep]; - % - p.subID = sprintf('sub%03d',subject); - p.path.edf = sprintf('sub%03d.edf',subject); - timestamp = datestr(now,30); - p.path.subject = [p.path.experiment 'data' filesep 'tmp' filesep p.subID '_' timestamp filesep]; - p.path.finalsubject = [p.path.experiment 'data' filesep p.subID '_' timestamp filesep ]; - %create folder hierarchy - mkdir(p.path.subject); - mkdir([p.path.subject 'scr']); - mkdir([p.path.subject 'eye']); - mkdir([p.path.subject 'stimulation']); - mkdir([p.path.subject 'midlevel']); - p.path.path_param = [p.path.subject 'stimulation' filesep 'data.mat']; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %get stim files names - [p.stim.files p.stim.label] = FileMatrix([p.path.stim '*.bmp']); - p.stim.tFile = size(p.stim.files,1);%number of different files (including the UCS symbol) - p.stim.tFace = p.stim.tFile - 1;%number of faces. - display([mat2str(p.stim.tFile) ' found in the destination.']); - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - p.stim.bg = [100 100 100];%background color - p.stim.bg_rating = [100 100 100];%bg of the rating screen. - p.stim.white = [255 255 255]; - %get the actual stim size (assumes all the same) - info = imfinfo(p.stim.files(1,:)); - p.stim.width = info.Width; - p.stim.height = info.Height; - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %font size and background gray level - p.text.fontname = 'Times New Roman'; - p.text.fontsize = 30; - p.text.fixsize = 60; - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %rating business - p.rating.division = 2;%number of divisions for the rating slider - p.rating.repetition = 2;%how many times a given face has to be repeated... - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %All settings for laptop computer. - try - p.keys.confirm = KbName('UpArrow'); - p.keys.increase = KbName('RightArrow'); - p.keys.decrease = KbName('LeftArrow'); - p.keys.space = KbName('space'); - p.keys.esc = KbName('ESCAPE'); - catch - fprintf('you need to change the key names coz your system doesn''t operate the same as mine\n You can do that by calling the KbName function and \n pressing the key you want, it will output the correct keyname.\n And then replace on the code above.\n Kapisch?\n'); - end - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %duration of different events. - p.duration.stim = 2;%2;%second - p.duration.keep_recording = 0.25;%this is the time we will keep recording (eye data) after stim offset. - p.duration.prime = .5; - p.duration.fixcross = .5; - p.duration.ISI = p.duration.stim + p.duration.prime + 5;%3 seconds is the ISI. - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %stimulus presentation - p.presentation.stim_id = stim_id;%SEQ is one of the inputs. - p.presentation.prime_id = prime_id; - p.presentation.tTrial = length(stim_id); - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - p.out.response = zeros(p.presentation.tTrial,1); - %Save the stuff for safety - save(p.path.path_param,'p'); - % - function [FM labels] = FileMatrix(path) - %Takes a path with file extension associated to regexp (e.g. - %C:\blabl\bla\*.bmp) returns the file matrix - dummy = dir(path); - FM = [repmat([fileparts(path) filesep],length(dummy),1) vertcat(dummy(:).name)]; - labels = {dummy(:).name}; - end - end - function AskStimRating - - %% texts on the rating screen and sliders - message = GetText(11); - SliderTextL = GetText(13); - SliderTextR = GetText(12); - %change the background if you want - Screen('FillRect', p.ptb.w , p.stim.bg_rating); - Screen('Flip',p.ptb.w); - WaitSecs(1); - % -% ShowInstruction(7,1); - % - p.out.rating(nTrial,1) = RatingSlider(p.rating.rect, p.rating.division, Shuffle(1:p.rating.division,1), p.keys.increase, p.keys.decrease, p.keys.confirm, {SliderTextL{1} SliderTextR{1}},message,1); - save(p.path.path_param,'p');%save it so that we don't lose data in case of natural catastrophies - Screen('FillRect',p.ptb.w,p.stim.bg); - % - save(p.path.path_param,'p'); - end - function [rating] = RatingSlider(rect,tSection,position,up,down,confirm,labels,message,numbersOn) - % - %Detect the bounding boxes of the labels. - for nlab = 1:2 - [~ , ~, bb(nlab,:)]=DrawFormattedText(p.ptb.w,labels{nlab}, 'center', 'center', p.stim.white,[],[],[],2); - Screen('FillRect',p.ptb.w,p.stim.bg); - end - bb = max(bb); - bb_size = bb(3)-bb(1);%vertical size of the bb. - % - DrawSkala; - ok = 1; - while ok == 1 - [secs, keyCode, ~] = KbStrokeWait; - keyCode = find(keyCode); - Log(secs,7,keyCode); - if length(keyCode) == 1%this loop avoids crashes to accidential presses of meta keys - if (keyCode == up) || (keyCode == down) - next = position + increment(keyCode); - if next < (tSection+1) && next > 0 - position = position + increment(keyCode); - %rating = tSection - position + 1; - end - DrawSkala; - elseif keyCode == confirm - WaitSecs(0.1); - ok = 0; - Screen('FillRect',p.ptb.w,p.stim.bg); - t=Screen('Flip',p.ptb.w); - end - end - end - - function DrawSkala - %rating = tSection - position + 1; - rating = position ; - increment([up down]) = [1 -1];%delta - tick_x = linspace(rect(1),rect(1)+rect(3),tSection+1);%tick positions - tick_size = rect(3)./tSection; - ss = tick_size/5*0.9;%slider size. - % - for tick = 1:length(tick_x)%draw ticks - Screen('DrawLine', p.ptb.w, [255 0 0], tick_x(tick), rect(2), tick_x(tick), rect(2)+rect(4) , 3); - if tick <= tSection && numbersOn - Screen('TextSize', p.ptb.w,p.text.fontsize./2); - DrawFormattedText(p.ptb.w, mat2str(tick) , tick_x(tick)+ss/2, rect(2)+rect(4), p.stim.white); - Screen('TextSize', p.ptb.w,p.text.fontsize); - end - if tick == 1 - DrawFormattedText(p.ptb.w, labels{1},tick_x(tick)-bb_size*1.4,rect(2), p.stim.white); - elseif tick == tSection+1 - DrawFormattedText(p.ptb.w, labels{2},tick_x(tick)+bb_size*0.4,rect(2), p.stim.white); - end - end - %slider coordinates - slider = [ tick_x(position)+tick_size*0.1 rect(2) tick_x(position)+tick_size*0.9 rect(2)+rect(4)]; - %draw the slider - Screen('FillRect',p.ptb.w, p.stim.white, round(slider)); - Screen('TextSize', p.ptb.w,p.text.fontsize./2); - DrawFormattedText(p.ptb.w,message, 'center', p.ptb.midpoint(2)*0.2, p.stim.white,[],[],[],2); - Screen('TextSize', p.ptb.w,p.text.fontsize); - t = Screen('Flip',p.ptb.w); - Log(t,6,NaN); - end - end - function ShowInstruction(nInstruct,waitforkeypress) - %ShowInstruction(nInstruct,waitforkeypress) - %if waitforkeypress is 1, then subject has to press a button to - %make the instruction text dissappear. Otherwise you have to take - %care of it later - - [text]= GetText(nInstruct); - ShowText(text); - %let subject read it and ask confirmation to proceed. But we don't - %need that in the case of INSTRUCT = 5; - if waitforkeypress - if nInstruct ~= 10%this is for the Reiz kommnt - KbStrokeWait; - else - WaitSecs(2.5+rand(1)); - end - Screen('FillRect',p.ptb.w,p.stim.bg); - t = Screen('Flip',p.ptb.w); - Log(t,-5,nInstruct); - else - if nInstruct ~= 10%this is for the Reiz kommnt - KbStrokeWait; - else - WaitSecs(1+rand(1)); - end - end - - - function ShowText(text) - - Screen('FillRect',p.ptb.w,p.stim.bg); - %DrawFormattedText(p.ptb.w, text, p.text.start_x, 'center',p.stim.white,[],[],[],2,[]); - DrawFormattedText(p.ptb.w, text, 'center', 'center',p.stim.white,[],[],[],2,[]); - t=Screen('Flip',p.ptb.w); - Log(t,5,nInstruct); - %show the messages at the experimenter screen - fprintf('=========================================================\n'); - fprintf('Text shown to the subject:\n'); - fprintf('=========================================================\n'); - fprintf(text); - fprintf('=========================================================\n'); - - end - end - function [text]=GetText(nInstruct) - if nInstruct == 0%Eyetracking calibration - - text = ['Um Ihre Augenbewegungen zu messen, \n' ... - 'müssen wir jetzt den Eye-Tracker kalibrieren.\n' ... - 'Dazu zeigen wir Ihnen einige Punkte auf dem Bildschirm, \n' ... - 'bei denen Sie sich wie folgt verhalten:\n' ... - 'Bitte fixieren Sie den kleinen weißen Kreis und \n' ... - 'bleiben so lange darauf, wie es zu sehen ist.\n' ... - 'Bitte drücken Sie jetzt den oberen Knopf, \n' ... - 'um mit der Kalibrierung weiterzumachen.\n' ... - ]; - - elseif nInstruct == 1%first Instr. of the training phase. - text = ['Wir werden nun als erstes einen Übungsdurchgang machen,\n' ... - 'damit Sie sich an Ihre Aufgabe gewöhnen können.\n' ... - 'In diesem Durchgang können Sie sich vollkommen sicher fühlen,\n' ... - 'es werden keine elektrischen Reize verabreicht.\n' ... - 'Eine wichtige grundsätzliche Regel ist, dass Sie das Fixationskreuz (das „+“)\n' ... - 'wenn es zu sehen ist, mit Ihren Augen fixieren. \n' ... - 'Drücken Sie die obere Taste um fortzufahren.\n' ... - ]; - elseif nInstruct == 101%first Instr. of the training phase. - text = ['Willkommen zum zweiten Teil des Experiments.\n'... - 'Eine wichtige grundsätzliche Regel ist auch hier,\n'... - 'dass Sie das Fixationskreuz (das „+“)\n' ... - 'wenn es zu sehen ist, mit Ihren Augen fixieren. \n' ... - 'Drücken Sie die obere Taste um fortzufahren.\n' ... - ]; - elseif nInstruct == 2%second Instr. of the training phase. - text = ['Ein paar Bemerkungen zu den Zielreizen: \n' ... - 'Zur Erinnerung: Zielreize sind die verschwommenen Gesichter.\n' ... - 'Sobald ein solcher Zielreiz erscheint, \n' ... - 'sollen Sie schnellstmöglich die obere Taste drücken, \n' ... - 'und zwar bevor der Reiz wieder verschwunden ist \n' ... - '(Sie müssen also sehr schnell und aufmerksam sein).' ... - ]; - elseif nInstruct == 3%third Instr. of the training phase. - text = ['Es ist sehr wichtig, dass Sie Ihren Kopf während \n' ... - 'des Experiments nicht bewegen. \n' ... - 'Das ist besonders wichtig für die Qualität der Messung.\n' ... - ]; - elseif nInstruct == 4%third Instr. of the training phase. - text = ['Vor dem Experiment legen wir nun \n' ... - 'die Schockintensität für den Rest des Experiments fest. \n' ... - 'Drücken Sie die obere Taste um fortzufahren.' ... - ]; - - elseif nInstruct == 5%Baseline Phase - % - % - %=================================================================================================================% - text = ['Jetzt geht es mit dem Experiment los.\n' ... - 'Ihre Aufgabe ist es jetzt, die Gesichter, \n' ... - 'die Ihnen gezeigt werden aufmerksam zu betrachten und \n' ... - 'den oberen Knopf zu drücken, sobald Sie einen Zielreiz sehen.\n' ... - '\n'... - 'Hin und wieder erscheint ein Symbol (ein Blitzpfeil, der vor Strom warnt), \n' ... - 'das einen elektrischen Reiz ankündigt. \n' ... - 'Die Reize erfolgen aber nur bei diesem Symbol, nicht bei den Gesichtern! \n' ... - 'Bei Gesichtern können Sie sich also sicher fühlen.\n' ... - 'Bitte denken Sie daran: 1. Fixationskreuz fixieren und 2. nicht bewegen!\n\n' ... - 'Sie können das Experiment nun durch Drücken der oberen Taste starten. \n' ... - ]; - - elseif nInstruct == 6%Test and Conditioning Phase - %=================================================================================================================% - text = ['Auch im nun folgenden Teil des Experiments \n' ... - 'sollen Sie die Gesichter aufmerksam betrachten und \n' ... - 'den oberen Knopf drücken, sobald Sie einen Zielreiz sehen. \n' ... - 'Wie im ersten Teil des Experiments sollen Sie \n' ... - 'das Fixationskreuz immer fixieren. \n' ... - 'In dieser Phase des Experiments werden Sie\n' ... - 'gelegentlich elektrische Reize bekommen.\n\n' ... - 'Die elektrischen Reize folgen jetzt auf bestimmte Gesichter. \n' ... - - ]; - - - elseif nInstruct == 7;%rating - text = ['In dieser Phase hätten wir gerne, dass Sie die Gesichter\n'... - 'im Hinblick auf folgende Frage bewerten:\n'... - '„Wie wahrscheinlich ist es, bei dem gerade gesehenen Gesicht \n'... - 'einen elektrischen Schock zu erhalten?“\n'... - 'Bewegen Sie den Zeiger mit der rechten und linken Pfeiltaste \n'... - 'und bestätigen Sie Ihre Einschätzung mit der oberen Pfeiltaste.\n'... - ]; - - elseif nInstruct == 8 %CS+ detection - text = ['Du bekommen nun eine Reihe von Gesichtern gezeigt.\n' ... - 'Bitte wählen Sie das Gesicht aus bei dem der Schock verabreicht wurde.\n'... - 'Drücken Sie die obere Taste um fortzufahren.\n'... - ]; - elseif nInstruct == 9% - %=================================================================================================================% - text = ['Bitte geben Sie an, ob die Reizstärke des folgenden Schocks\n für Sie erträglich ist.\n'... - '\n'... - 'Drücken Sie bitte die obere Taste um den Reiz zu bekommen.\n'... - ]; - - elseif nInstruct == 10%just before the shock - text = ['Reiz kommt...\n']; - elseif nInstruct == 11%this is the rating question - text = ['Bu alet elle mi ayakla mi kullaniliii\n'... - ]; - elseif nInstruct == 12 %These two below are the possible responses to the question in 11 - text = {'Elle'}; - elseif nInstruct == 13 - text = {'Ayakla'}; - elseif nInstruct == 14 - text = ['Bitte machen Sie eine kurze Pause.\n' ... - 'Sie können hierbei gern die Augen einen Moment schließen.\n'... - 'Drücken Sie anschließend die obere Taste um fortzufahren.\n'... - 'Wir werden dann den Eyetracker noch einmal kalibrieren.\n'... - ]; - else - text = {''}; - end - end - function SetPTB - %Sets the parameters related to the PTB toolbox. Including - %fontsizes, font names. - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %Find the number of the screen to be opened - screens = Screen('Screens'); - p.ptb.screenNumber = max(screens);%the maximum is the second monitor - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %Use the debug feature of PTB - if debug - PsychDebugWindowConfiguration;%transparent Screen - else - commandwindow; - ListenChar(2);%disable pressed keys to be spitted around - end - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %Default parameters - Screen('Preference', 'SkipSyncTests', 1); - Screen('Preference', 'DefaultFontSize', p.text.fontsize); - Screen('Preference', 'DefaultFontName', p.text.fontname); - Screen('Preference', 'TextAntiAliasing',2);%enable textantialiasing high quality - Screen('Preference', 'VisualDebuglevel', 0); - Screen('Preference', 'SuppressAllWarnings', 1); - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %Open a graphics window using PTB - p.ptb.w = Screen('OpenWindow', p.ptb.screenNumber, p.stim.bg); - Screen('BlendFunction', p.ptb.w, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - Screen('Flip',p.ptb.w);%make the bg - p.ptb.slack = Screen('GetFlipInterval',p.ptb.w)./2; - [p.ptb.width, p.ptb.height] = Screen('WindowSize', p.ptb.screenNumber); - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %find the mid position on the screen. - p.ptb.midpoint = [ p.ptb.width./2 p.ptb.height./2]; - p.ptb.imrect = [ p.ptb.midpoint(1)-p.stim.width/2 p.ptb.midpoint(2)-p.stim.height/2 p.stim.width p.stim.height]; - [nx, ny bb] = DrawFormattedText(p.ptb.w,'+','center','center'); - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %this is necessary for the Eyelink calibration for some obscure - %reasons. - InitializePsychSound(0); - Beeper(5000) - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %Prepare the keypress queue listening. - p.ptb.device = -1; - p.ptb.keysOfInterest=zeros(1,256); - p.ptb.keysOfInterest(p.keys.confirm) = 1; - KbQueueCreate(p.ptb.device,p.ptb.keysOfInterest);%default device. - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %load the pictures to the memory. - p.ptb.stim_sprites = CreateStimSprites(p.stim.files); - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - p.rating.rect = [p.ptb.width*0.2 p.ptb.midpoint(2) p.ptb.width*0.6 100];%necessary for rating screen. - % - Priority(MaxPriority(p.ptb.w)); - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - function [out]=CreateStimSprites(files) - %loads all the stims to video memory - for nStim = 1:p.stim.tFile - filename = files(nStim,:); - [im , ~, ~] = imread(filename); - out(nStim) = Screen('MakeTexture', p.ptb.w, im ); - end - end - end - function [t]=StopEyelinkRecording - Eyelink('StopRecording'); - t = GetSecs; - %this is the end of the trial scope. - WaitSecs(0.01); - Eyelink('Message', 'TRIAL_RESULT 0'); - % - WaitSecs(0.01); - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('Command', 'clear_screen %d', 0); - Screen('Textsize', p.ptb.w,p.text.fontsize); - Log(t,-8,NaN); - end - function [t]=StartEyelinkRecording(nTrial,stim_id,prime_id) - %(nTrial,stim_id,prime_id); - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - stim_id = double(stim_id);%otherwise messages to eyelink are not sent. - Eyelink('Message', 'TRIALID: %04d, STIMID: %04d, PRIMEID: %04d', nTrial, stim_id, prime_id); - % an integration message so that an image can be loaded as - % overlay background when performing Data Viewer analysis (peh peh peh). - WaitSecs(0.01); - Eyelink('Message', '!V IMGLOAD CENTER %s %d %d', p.stim.files(stim_id,:), p.ptb.midpoint(1), p.ptb.midpoint(2)); - - % This supplies the title at the bottom of the eyetracker display - Eyelink('Command', 'record_status_message "stim_id: %02d, prime_id: %d"', stim_id, prime_id); - % - %Put the tracker offline and draw the stimuli. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - % clear tracker display and draw box at center - Eyelink('Command', 'clear_screen %d', 0); - %draw the image on the screen but also the two crosses - Eyelink('ImageTransfer',p.stim.files(stim_id,:),p.ptb.imrect(1),p.ptb.imrect(2),p.ptb.imrect(3),p.ptb.imrect(4),p.ptb.imrect(1),p.ptb.imrect(2)); - % - %drift correction (not yet implemented, we might need it) - %EyelinkDoDriftCorrection(el,crosspositionx,crosspositiony,0,0); - %start recording following mode transition and a short pause. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('StartRecording'); - t = GetSecs; - Log(t,8,NaN); - end - function shuffled = Shuffle(vector,N) - %takes first N from the SHUFFLED before outputting. This function - %could be used as a replacement for randsample - if nargin < 2;N = length(vector);end - [~, idx] = sort(rand([1 length(vector)])); - shuffled = vector(idx(1:N)); - shuffled = shuffled(:); - end - function InitEyeLink - %will init the eyelink connection - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - if EyelinkInit(0)%use 0 to init normaly - fprintf('=================\nEyelink initialized correctly...\n') - else - fprintf('=================\nThere is problem in Eyelink initialization\n') - keyboard; - end - WaitSecs(0.5); - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - [~, vs] = Eyelink('GetTrackerVersion'); - fprintf('=================\nRunning experiment on a ''%s'' tracker.\n', vs ); - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - el = EyelinkInitDefaults(p.ptb.w); - %update the defaults of the eyelink tracker - el.backgroundcolour = p.stim.bg; - el.msgfontcolour = WhiteIndex(el.window); - el.imgtitlecolour = WhiteIndex(el.window); - el.targetbeep = 0; - el.calibrationtargetcolour = WhiteIndex(el.window); - el.calibrationtargetsize = 1.5; - el.calibrationtargetwidth = 0.5; - el.displayCalResults = 1; - el.eyeimgsize = 50; - el.waitformodereadytime = 25;%ms - el.msgfont = 'Times New Roman'; - el.cal_target_beep = [0 0 0];%[1250 0.6 0.05];%shut all sounds off - el.drift_correction_target_beep = [0 0 0]; - el.calibration_failed_beep = [0 0 0]; - el.calibration_success_beep = [0 0 0]; - el.drift_correction_failed_beep = [0 0 0]; - el.drift_correction_success_beep= [0 0 0]; - EyelinkUpdateDefaults(el); - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % open EDF file and write information on it. - res = Eyelink('Openfile', p.path.edf); - % - Eyelink('command', 'add_file_preamble_text ''Recorded by EyelinkToolbox FearCloud Experiment'''); - Eyelink('command', 'screen_pixel_coords = %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - Eyelink('message', 'DISPLAY_COORDS %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - % set calibration type. - Eyelink('command','auto_calibration_messages = YES'); - Eyelink('command', 'calibration_type = HV13'); - Eyelink('command', 'select_parser_configuration = 1'); - %what do we want to record - Eyelink('command', 'file_sample_data = LEFT,RIGHT,GAZE,HREF,AREA,GAZERES,STATUS,INPUT,HTARGET'); - Eyelink('command', 'file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON,INPUT'); - Eyelink('command', 'use_ellipse_fitter = no'); - % set sample rate in camera setup screen - Eyelink('command', 'sample_rate = %d',1000); - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - end - function StopEyelink(filename) - try - fprintf('Trying to stop the Eyelink system with StopEyelink\n'); - Eyelink('StopRecording'); - WaitSecs(0.5); - Eyelink('Closefile'); - display('receiving the EDF file...'); - Eyelink('ReceiveFile',filename,[p.path.subject '\eye\'],1); - display('...finished!') - % Shutdown Eyelink: - Eyelink('Shutdown'); - catch - display('StopEyeLink routine didn''t really run well'); - end - end - function cleanup - - % Close window: - sca; - % - commandwindow; - ListenChar(0); - KbQueueRelease(p.ptb.device); - end - function CalibrateEL - fprintf('=================\n=================\nEntering Eyelink Calibration\n') - p_var_ExpPhase = 0; - ShowInstruction(0,1); - EyelinkDoTrackerSetup(el); - %Returns 'messageString' text associated with result of last calibration - [~, messageString] = Eyelink('CalMessage'); - Eyelink('Message','%s',messageString);% - WaitSecs(0.05); - fprintf('=================\n=================\nNow we are done with the calibration\n') - end - function Log(ptb_time, event_type, event_info) - %Phases: - %Instruction : 1 - %Baseline : 2 - %Conditioning : 3 - %Test : 4 - %Rating : 5 - %Calibration : 0 - % - %event types are as follows: - % - %Scan Detection : 0 info: NaN; - %Cross Onset : 1 info: position - %Stimulus Onset/Offset: 2/-2 info: stim_id - %Cross Movement : 3 info: NaN; - %Stimulus Offset : -2 info: NaN; - %UCS Delivery : 4 info: NaN; - %Key Presses : 7 info: NaN; - %Tracker Onset/Offset : 8 info: NaN; - % - %Text on the screen : 5 info: Which Text? - %RatingScreen Onset : 6 info: NaN; - - p_var_event_count = p_var_event_count + 1; - %% - % - % for x = 1:10 - % disp(x) - % end - % - p.out.log(p_var_event_count,:) = [ptb_time event_type event_info]; - % % p.out.log(p.out.event_counter,:) - %logstring([ 'Logged: ' mat2str(p.out.log(p.out.event_counter,:)) ' - Type: ' p.verbose.eventtype{abs(event_type)} ' - Phase: ' p.verbose.eventphase{CurrentExperimentalPhase}]) - %for i = 1:3;subplot(3,1,i);plot(p.out.log(1:p.out.event_counter ,i),'o-');drawnow;end - % - - end - - -end diff --git a/exp_Sepf.m b/exp_Sepf.m deleted file mode 100644 index d59ac7f..0000000 --- a/exp_Sepf.m +++ /dev/null @@ -1,1222 +0,0 @@ -function [p]=exp_predCodfMRI(subject,phase,itration) - -%check the response box!!!! - - -debug = 0;%debug mode - -%replace parallel port function with a dummy function -[~, hostname] = system('hostname'); -hostname = deblank(hostname); -% if strcmp(hostname,'Sepideh-PC') -% outp = @(x,y) fprintf('[%i %i]\n',x,y); -% end - -if nargin ~= 3 - fprintf('Wrong number of inputs\n'); - keyboard; -end - -commandwindow; -%clear everything -clear mex global functions -if ~strcmp(hostname,'Sepideh-PC') - cgshut; - global cogent; -end -%%%%%%%%%%%load the GETSECS mex files so call them at least once -GetSecs; -WaitSecs(0.001); -% -el = []; -p = []; -SetParams; -SetPTB; -% -%init all the variables -t = []; -nTrial = 0; -%% -%Time Storage -TimeCueOnset = []; -TimeCrossOnset = []; -TimeEndStim = []; -TimeEndTrial = []; -TimeTrackerOff = []; -p.var.event_count = 0; -%% -if strcmp(p.hostname,'triostim1') - InitEyeLink; -end -WaitSecs(2); -if strcmp(p.hostname,'triostim1') - CalibrateEL; -end - -% sep KbQueueStop(p.ptb.device); -% sep KbQueueRelease(p.ptb.device); -%save again the parameter file -save(p.path.path_param,'p'); -if phase>0 - p.var.ExpPhase = phase; - %sep CalibrateEL; - for ninst = [3 30:1:37 301:306] - ShowInstruction(ninst,1); - end - p.out.expStart = GetSecs; - PresentStimuli; -end - -%get the eyelink file back to this computer -if strcmp(p.hostname,'triostim1') - StopEyelink(p.path.edf); -end -%trim the log file and save -p.out.log = p.out.log(sum(isnan(p.out.log),2) ~= size(p.out.log,2),:); -%shift the time so that the first timestamp is equal to zero -p.out.log(:,1) = p.out.log(:,1) - p.out.log(1); -p.out.log = p.out.log;%copy it to the output variable. -save(p.path.path_param,'p'); -% -%move the file to its final location. -movefile(p.path.subject,p.path.finalsubject); -%close everything down -p.out.expEnd = GetSecs; -WaitSecs((p.out.expEnd-p.out.expStart)-(821*1.24)) -cleanup; - - - function PresentStimuli - %Enter the presentation loop and wait for the first pulse to - %arrive. - %wait for the dummy scans - - [secs] = WaitPulse(p.keys.pulse,p.mrt.dummy_scan);%will log it - p.out.firstPulse=secs(end); - KbQueueStop(p.ptb.device); - WaitSecs(.05); - KbQueueCreate(p.ptb.device); - KbQueueStart(p.ptb.device); - %log the pulse timings. - TimeEndTrial = secs(end)- p.ptb.slack;%take the first valid pulse as the end of the last stimulus. - fix_y = p.presentation.CrossPosition; - fix = [p.ptb.CrossPosition_x p.ptb.CrossPosition_y(fix_y)]; - FixCross = [fix(1)-1,fix(2)-p.ptb.fc_size,fix(1)+1,fix(2)+p.ptb.fc_size;fix(1)-p.ptb.fc_size,fix(2)-1,fix(1)+p.ptb.fc_size,fix(2)+1]; - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.imrect ); %always create a gray background - Screen('FillRect', p.ptb.w, p.stim.white, FixCross'); - Screen('Flip',p.ptb.w); - for nTrial = 1:p.presentation.tTrial; -% Screen('BlendFunction', p.ptb.w, 'GL_SRC_ALPHA', 'GL_ONE_MINUS_SRC_ALPHA'); - if (p.presentation.catch(nTrial)) - fix_y = p.presentation.CrossPosition; - cue_id = randi(6); - p.out.catch_id(nTrial) = cue_id; - prestimdur = p.presentation.prestimdurCatch(nTrial); %when cue apears - ISI = p.presentation.catchisi(nTrial); - TimeStimOnset = TimeEndTrial + prestimdur + ISI - p.ptb.slack; - p.out.catchCueOnset(nTrial)=TimeStimOnset - prestimdur; - [TimeEndTrial] = catchTrial(nTrial, TimeStimOnset, prestimdur, cue_id, fix_y); - fprintf('CatchOffsetTime: %05.8gs, Difference of %05.8gs\n',TimeEndTrial,TimeEndTrial-TimeStimOnset-4); - [keycode, secs] = KbQueueDump;%this contains both the pulses and keypresses. - %log everything but "pulse keys" as pulses, not as keypresses. - pulses = (keycode == p.keys.pulse); - if any(~pulses);%log keys presses if only there is one - Log(secs(~pulses),7,keycode(~pulses)); - end - if any(pulses);%log pulses if only there is one - Log(secs(pulses),0,keycode(pulses)); - end - end - - %Get the variables that Trial function needs. - stim_id = p.presentation.stim_id(nTrial); - stim_add = p.presentation.stim_add(nTrial); - con_id = p.presentation.con_id(nTrial); - fix_y = p.presentation.CrossPosition; - ISI = p.presentation.isi(nTrial); - pain = p.presentation.pain(nTrial); - cue_id = p.presentation.cue_id(nTrial); - prestimdur = p.presentation.prestimdur(nTrial); %when cue apears - TimeStimOnset = TimeEndTrial + prestimdur + ISI - p.ptb.slack; - p.out.stimOnset(nTrial)=TimeStimOnset; - p.out.cueOnset(nTrial)=TimeStimOnset - prestimdur; - fprintf('%d of %d, S: %d, ISI: %d, pain: %d, OnsetTime: %05.8gs, ',nTrial,p.presentation.tTrial,stim_id,ISI,pain, TimeStimOnset); - - %Start with the trial, here is time-wise sensitive must be - %optimal - [TimeEndTrial] = Trial(nTrial, TimeStimOnset, prestimdur, stim_add, stim_id, cue_id, con_id, pain, fix_y); - %(nTrial,TimeStimOnset , prestimdur, stim_id , pain , fix_i, oddball, dist ) - fprintf('OffsetTime: %05.8gs, Difference of %05.8gs\n',TimeEndTrial,TimeEndTrial-TimeStimOnset-4); - % - %dump it - [keycode, secs] = KbQueueDump;%this contains both the pulses and keypresses. - %log everything but "pulse keys" as pulses, not as keypresses. - pulses = (keycode == p.keys.pulse); - if any(~pulses);%log keys presses if only there is one - Log(secs(~pulses),7,keycode(~pulses)); - end - if any(pulses);%log pulses if only there is one - Log(secs(pulses),0,keycode(pulses)); - end - %now we have to detect if the subject has pressed the CONFIRM - %key while the ODDBALL stimulus was on the screen. - end - KbQueueRelease(p.ptb.device); - %wait 6 seconds for the BOLD signal to come back to the baseline... - WaitSecs(6); -% WaitPulse(p.keys.pulse,p.mrt.LastScans) -% WaitPulse(p.keys.pulse,ceil(6./p.mrt.tr));% - %stop the queue - KbQueueStop(p.ptb.device); - KbQueueRelease(p.ptb.device); - end - function [TimeEndTrial]=Trial(nTrial, TimeStimOnset, prestimdur, stim_add, stim_id, cue_id, con_id, pain, fix_i) - - %get all the times - TimeCueOnset = TimeStimOnset - prestimdur; - TimeCrossOnset = TimeStimOnset - prestimdur + p.duration.cueDur; - TimeEndStim = TimeStimOnset + p.duration.stim- p.ptb.slack; - TimeEndTrial = TimeStimOnset + p.duration.stim- p.ptb.slack + p.duration.ratingDur; - TimeTrackerOff = TimeStimOnset + 2 + p.duration.keep_recording; - - %% Cue Onset - imageArray = imread(char(strcat(p.path.cue,num2str(cue_id),'.png'))); - Screen('FillRect', p.ptb.w , p.stim.bg ); %always create a gray background - Screen('PutImage', p.ptb.w, imageArray); - Screen('DrawingFinished',p.ptb.w,0); - TimeCueOnset = Screen('Flip',p.ptb.w,TimeCueOnset,0); - MarkCED( p.com.lpt.address, p.com.lpt.StimOnset ); - Log(TimeCueOnset,1,cue_id);%cross onset. - %% Fixation Onset - fix = [p.ptb.CrossPosition_x p.ptb.CrossPosition_y(fix_i)]; - FixCross = [fix(1)-1,fix(2)-p.ptb.fc_size,fix(1)+1,fix(2)+p.ptb.fc_size;fix(1)-p.ptb.fc_size,fix(2)-1,fix(1)+p.ptb.fc_size,fix(2)+1]; - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.imrect ); %always create a gray background - Screen('FillRect', p.ptb.w, p.stim.red, FixCross');%draw the prestimus cross atop - Screen('DrawingFinished',p.ptb.w,0); - TimeCrossOnset = Screen('Flip',p.ptb.w,TimeCrossOnset,0); - Log(TimeCrossOnset,2,fix_i);%cross onset. - %turn the eye tracker on - if strcmp(p.hostname,'triostim1') - StartEyelinkRecording(nTrial,stim_id,p.var.ExpPhase,pain,fix); - Eyelink('Message', 'Stim Onset'); - Eyelink('Message', 'SYNCTIME'); - end - %% Draw the stimulus to the buffer - if ~stim_id==0 - if stim_id <4 - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.imrect ); %always create a gray background - Screen('FillRect', p.ptb.w, p.stim.red, FixCross'); - Screen('DrawingFinished',p.ptb.w,0); - %% STIMULUS ONSET - TimeStimOnset = Screen('Flip',p.ptb.w,TimeStimOnset,0);%asap and dont clear - MarkCED(p.com.lpt.address, p.com.lpt.pain); - if strcmp(p.hostname,'triostim1') - Eyelink('Message', 'pain Onset'); - end - Buzz; - Log(TimeStimOnset,3,stim_id); - else - imageTexture=p.ptb.stim_sprites(find(strcmp(p.stim.label,stim_add))); - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.imrect ); %always create a gray background - Screen('FillRect', p.ptb.w, p.stim.red, FixCross'); - Screen('DrawingFinished',p.ptb.w,0); - %% STIMULUS ONSET - TimeStimOnset = Screen('Flip',p.ptb.w,TimeStimOnset,0);%asap and dont clear - MarkCED(p.com.lpt.address, p.com.lpt.pic); - if strcmp(p.hostname,'triostim1') - Eyelink('Message', 'pic Onset'); - end - Log(TimeStimOnset,3,stim_id); - mytime=0; - slope=10; - while mytime<.5 - thisContrast = 1/(1+exp(-slope*(mytime-0.25))); - % Draw the image to the screen - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.imrect ); %always create a gray background - Screen('DrawTexture', p.ptb.w, imageTexture, [], [], 0, [], thisContrast); - Screen('FillRect', p.ptb.w, p.stim.red, FixCross'); - Screen('DrawingFinished',p.ptb.w,0); - % Increment the time - mytime = mytime + p.ptb.ifi; - % Flip to the screen - Screen('Flip', p.ptb.w); - end - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.imrect ); %always create a gray background - Screen('DrawTexture', p.ptb.w, imageTexture); - Screen('FillRect', p.ptb.w, p.stim.red, FixCross'); - Screen('DrawingFinished',p.ptb.w,0); - Screen('Flip', p.ptb.w); - end - end - %log the stimulus onset - - %% - - %% STIM OFF immediately - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.imrect ); %always create a gray background - Screen('FillRect', p.ptb.w, p.stim.white, FixCross'); - TimeEndStim = Screen('Flip',p.ptb.w,TimeEndStim,0); - %send eyelink and ced a marker - Log(TimeEndStim,4,con_id);%log the stimulus offset - % - %% record some more eye data after stimulus offset. - WaitSecs('UntilTime',TimeTrackerOff); - if strcmp(p.hostname,'triostim1') - Eyelink('Message', 'Stim Offset'); - Eyelink('Message', 'SLIDER_SCREEN'); - TimeTrackerOff = StopEyelinkRecording; - end - if pain == 1 - fprintf('This was a pain trial!\n'); - else - fprintf('This was a picture trial!\n'); - end - %% rating - %the super ratings: - [p.out.rating(nTrial,:), p.out.rt(nTrial,:), p.out.mans{nTrial}] = RatingCircle(p.rating.crect, p.rating.division, GetSecs, NaN, p.keys.one, p.keys.two, p.keys.three,p.keys.four, {p.rating.SliderTextL{1} p.rating.SliderTextR{1}},p.rating.message,1,p.duration.ratingDur); -% [p.out.rating(nTrial,:), p.out.rt(nTrial,:)] = RatingSlider(p.rating.rect, p.rating.division, GetSecs, NaN, p.keys.one, p.keys.two, p.keys.three,p.keys.four, {p.rating.SliderTextL{1} p.rating.SliderTextR{1}},p.rating.message,1,p.duration.ratingDur); - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.imrect ); %always create a gray background - Screen('FillRect', p.ptb.w, p.stim.white, FixCross'); - TimeEndTrial = Screen('Flip',p.ptb.w,TimeEndTrial,0); - Log(TimeEndTrial,5,p.out.rating(nTrial,1));%log the stimulus offset - Log(TimeEndTrial,6,p.out.rt(nTrial,1)); - end - - function [TimeEndTrial]=catchTrial(nTrial, TimeStimOnset, prestimdur, cue_id, fix_i) - - %get all the times - TimeCueOnset = TimeStimOnset - prestimdur; - TimeCrossOnset = TimeStimOnset - prestimdur + p.duration.cueDur; - TimeEndTrial = TimeStimOnset - p.ptb.slack + p.duration.ratingDur+2; - TimeTrackerOff = TimeStimOnset + p.duration.keep_recording; - - %% Cue Onset - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.imrect ); %always create a gray background - imageArray = imread(char(strcat(p.path.cue,num2str(cue_id),'.png'))); - Screen('PutImage', p.ptb.w, imageArray); - Screen('DrawingFinished',p.ptb.w,0); - TimeCueOnset = Screen('Flip',p.ptb.w,TimeCueOnset,0); - Log(TimeCueOnset,11,cue_id);%cross onset. - %% Fixation Onset - fix = [p.ptb.CrossPosition_x p.ptb.CrossPosition_y(fix_i)]; - FixCross = [fix(1)-1,fix(2)-p.ptb.fc_size,fix(1)+1,fix(2)+p.ptb.fc_size;fix(1)-p.ptb.fc_size,fix(2)-1,fix(1)+p.ptb.fc_size,fix(2)+1]; - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.imrect ); %always create a gray background - Screen('FillRect', p.ptb.w, p.stim.white, FixCross');%draw the prestimus cross atop - Screen('DrawingFinished',p.ptb.w,0); - TimeCrossOnset = Screen('Flip',p.ptb.w,TimeCrossOnset,0); - Log(TimeCrossOnset,12,fix_i);%cross onset. - %turn the eye tracker on - %% - %% STIM OFF immediately - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.imrect ); %always create a gray background - TimeEndStim = Screen('Flip',p.ptb.w,TimeStimOnset,0); - %send eyelink and ced a marker - Log(TimeEndStim,13,cue_id);%log the stimulus offset - % - %% record some more eye data after stimulus offset. - %% rating - %the super ratings: - [p.out.catchCueMod(nTrial,1)] = RatingSlider(p.rating.rect, 2, GetSecs, NaN, p.keys.one, p.keys.two, p.keys.three, p.keys.four, {'Schmerz' 'Bild'},GetText(9),1,p.duration.ratingDur+2); - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.imrect ); %always create a gray background - Screen('FillRect', p.ptb.w, p.stim.white, FixCross'); - TimeEndTrial = Screen('Flip',p.ptb.w,TimeEndTrial,0); - Log(TimeEndTrial,14,p.out.catchCueMod(nTrial,1));%log the stimulus offset - [p.out.catchCueInt(nTrial,1)] = RatingSlider(p.rating.rect, 3, GetSecs, NaN, p.keys.one, p.keys.two, p.keys.three, p.keys.four, {'niedrig' 'hoch'},GetText(10),1,p.duration.ratingDur+2); - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.imrect ); %always create a gray background - Screen('FillRect', p.ptb.w, p.stim.white, FixCross'); - TimeEndTrial = Screen('Flip',p.ptb.w,TimeEndTrial+ p.duration.ratingDur+2,0); - Log(TimeEndTrial,14,p.out.catchCueInt(nTrial,1));%log the stimulus offset - end - - function SetParams - p.parm.phase = phase; - p.parm.interation = itration; - %mrt business - p.mrt.dummy_scan = 7;%7 this will wait until the 6th image is acquired. - p.mrt.LastScans = 5;%7 number of scans after the offset of the last stimulus - p.mrt.tr = 1.24;%in seconds. - %will count the number of events to be logged - p.var.event_count = 0; - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %% relative path to stim and experiments - %Path Business. - [~, hostname] = system('hostname'); - p.hostname = deblank(hostname); - if strcmp(p.hostname,'triostim1') - p.path.baselocation = 'C:\USER\fazeli\scannerFiles'; - p.path.cue = ['C:\USER\fazeli\scannerFiles\codes\NormCues\']; - elseif strcmp(p.hostname,'etpc') - p.path.baselocation = 'C:\USER\fazeli\scannerFiles'; - p.path.cue = ['C:\USER\fazeli\scannerFiles\codes\NormCues\']; - elseif strcmp(p.hostname,'Sepideh-PC') - p.path.baselocation = 'C:\Users\Sepideh\work\cueingPE'; - p.path.cue = ['C:\Users\Sepideh\work\ncueingPE\matlabFiles\pilot\V-2\NormCues\']; - else - - end - - p.path.experiment = [p.path.baselocation filesep]; - p.path.stim = [p.path.baselocation filesep 'stimuli' filesep 'Normalized' filesep]; - p.path.stim24 = [p.path.stim '24bit' filesep]; - % - p.subID = sprintf('s%02d',subject); - timestamp = datestr(now,30); - p.path.subject = [p.path.experiment 'tmp' filesep p.subID '_' timestamp filesep ]; - p.path.finalsubject = [p.path.experiment p.subID '_' timestamp filesep ]; - p.path.path_edf = [p.path.subject 'eye' filesep]; - p.path.edf = sprintf([p.subID 'p%02d.edf' ],phase); - p.path.path_param = [p.path.subject 'stimulation' filesep 'data.mat']; - %create folder hierarchy - mkdir(p.path.subject); - mkdir([p.path.subject 'scr']); - mkdir([p.path.subject 'eye']); - mkdir([p.path.subject 'stimulation']); - mkdir([p.path.subject 'midlevel']); - %% %%%%%%%%%%%%%%%%%%%%%%%%% - %get stim files - [p.stim.files p.stim.label] = FileMatrix([p.path.stim '*.jpg']); - p.stim.tFile = size(p.stim.files,1);%number of different files (including the pain symbol) - % - display([mat2str(p.stim.tFile) ' found in the destination.']); - - %is all the captured bg values the same? - - %if so take it as the bg color - p.stim.bg = [100 100 100]; - - %bg of the rating screen. - p.stim.bg_rating = p.stim.bg; - p.stim.white = [0 0 0]; - p.stim.red = [120 0 0]; - %% font size and background gray level -% p.text.fontname = 'Times New Roman'; - p.text.fontname = 'Arial'; - p.text.fontsize = 20;%18;%30; - p.text.intfontsize = 16;%18;%30; - p.text.fixsize = 60; - %rating business - p.rating.division = 4;%number of divisions for the rating slider - %% get the actual stim size (assumes all the same) - info = imfinfo(p.stim.files(1,:)); - p.stim.width = info.Width; - p.stim.height = info.Height; - info = imfinfo(char(strcat(p.path.cue,'1.png'))); - p.cue.width = info.Width; - p.cue.height = info.Height; - %% keys to be used during the experiment - %1, 6 ==> Right - %2, 7 ==> Left - %3, 8 ==> Down - %4, 9 ==> Up (confirm) - %5 ==> Pulse from the scanner - p.keys.confirm = KbName('4$'); - p.keys.two = KbName('1!'); - p.keys.three = KbName('2@'); - p.keys.four = KbName('3#'); - p.keys.one = KbName('4$'); -% p.keys.confirm = KbName('4'); -% p.keys.one = KbName('1!'); -% p.keys.two = KbName('2'); -% p.keys.three = KbName('3'); -% p.keys.four = KbName('4$'); - p.keys.pulse = KbName('5%'); - p.keys.el_calib = KbName('v'); - p.keys.el_valid = KbName('c'); - if ismac - p.keys.escape = KbName('escape'); - else - p.keys.escape = KbName('esc'); - end - p.keys.enter = KbName('return'); - - %% %%%%%%%%%%%%%%%%%%%%%%%%% - %Communication business - %parallel port -% p.com.lpt.address = hex2dec('378'); %training -% p.com.lpt.thermode = hex2dec('E800'); %training - p.com.lpt.address = 888; %scanner - p.com.lpt.thermode = 888; %scanner - %codes for different events - p.com.lpt.StimOnset = 64; - p.com.lpt.pic = 32; - p.com.lpt.pain = 16; - - %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %timing business - %these are the intervals of importance - %time2fixationcross->cross2onset->onset2shock->shock2offset - %these (duration.BLA) are average duration values: - p.duration.stim = 2;%1.5;%2;%s - p.duration.keep_recording = 0.05;%this is the time we will keep recording (eye data) after stim offset. - p.duration.cueDur = 0.5; - p.duration.ratingDur = 2; - p.duration.pain = 2; - %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %this will deal all the presentation sequence related information - %stimulus sequence - if phase > 0 - load([p.path.baselocation '\ExpParams\myexpPars.mat']); - seq = sequence{itration,phase}; - seq.tTrial = length(seq.stim_id); - catchOrd = randperm(seq.tTrial); %1:1:130;% - temp = Shuffle(seq.tisi); - seq.isi = temp(1:seq.tTrial); - seq.catchisi(catchOrd(1:4)) = temp(seq.tTrial+1:end); - seq.catchisi(end+1:seq.tTrial) = 0; - seq = rmfield(seq,'tisi'); - temp = Shuffle(seq.tpsdur); - seq.prestimdur = temp(1:seq.tTrial); - seq.prestimdurCatch(catchOrd(1:4)) = temp(seq.tTrial+1:end); - seq.prestimdurCatch(end+1:seq.tTrial) = 0; - seq = rmfield(seq,'tpsdur'); - seq.catch(catchOrd(1:4)) = [1 1 1 1]; - seq.catch(end+1:seq.tTrial) = 0; - seq.stim_add (seq.stim_id==4) = Shuffle(seq.stim_add (seq.stim_id==4)); - seq.stim_add (seq.stim_id==5) = Shuffle(seq.stim_add (seq.stim_id==5)); - seq.stim_add (seq.stim_id==6) = Shuffle(seq.stim_add (seq.stim_id==6)); - end - % - p.presentation = seq; - clear seq - %% create the randomized design - %Record which Phase are we going to run in this run. - p.stim.phase = phase; - - - p.out.rating = zeros(p.presentation.tTrial,1); - p.out.rt = zeros(p.presentation.tTrial,1); - p.out.log = zeros(1000000,4).*NaN; - p.out.firstPulse = NaN; - p.out.stimOnset = zeros(p.presentation.tTrial,1); - p.out.cueOnset = zeros(p.presentation.tTrial,1); - p.out.catchCueOnset = zeros(p.presentation.tTrial,1); - p.out.catchCueInt = zeros(p.presentation.tTrial,1); - p.out.catchCueMod = zeros(p.presentation.tTrial,1); - %% - p.var.current_bg = p.stim.bg;%current background to be used. - % - p.rating.message = {}; - p.rating.SliderTextL = GetText(13); - p.rating.SliderTextR = GetText(12); - - %Save the stuff - save(p.path.path_param,'p'); - % - function [FM labels] = FileMatrix(path) - - %Takes a path with file extension associated to regexp (e.g. - %C:\blabl\bla\*.bmp) returns the file matrix - dummy = dir(path); - FM = [repmat([fileparts(path) filesep],length(dummy),1) vertcat(dummy(:).name)]; - labels = {dummy(:).name}; - end - end - - function [rating, rt] = RatingSlider(rect,tSection,secs,position,up,down,left,right,labels,message,numbersOn,ratingDur) - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.imrect ); %always create a gray background - timewaitend= GetSecs + ratingDur; - while GetSecs<=timewaitend - % - %Detect the bounding boxes of the labels. - for nlab = 1:2 - [~ , ~, bb(nlab,:)]=DrawFormattedText(p.ptb.w,labels{nlab}, 'center', 'center', p.stim.white,[],[],[],2); - Screen('FillRect',p.ptb.w,p.var.current_bg); - end - bb = max(bb); - bb_size = bb(3)-bb(1);%vertical size of the bb. - % - DrawSkala; -% rating = NaN; - ok = 1; - while ok == 1 && GetSecs<=timewaitend - [secs, keyCode, ~] = KbStrokeWait(p.ptb.device,timewaitend); - keyCode = find(keyCode); - if length(keyCode) == 1%this loop avoids crashes to accidential presses of meta keys - switch keyCode - case up - position = 1; - case down - position = 2; - case left - position = 3; - case right - position = 4; - end - Log(secs,7,keyCode); -% ok =0; - if positiontimewaitend - break - end - end - if GetSecs>timewaitend - break - end - end -% entTime=GetSecs; - function DrawSkala - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.imrect ); %always create a gray background - %rating = tSection - position + 1; - rating = position ; - rt = secs; - tick_x = linspace(rect(1),rect(1)+rect(3),tSection+1);%tick positions - tick_size = rect(3)./tSection; - ss = tick_size/5*0.9;%slider size. - % - for tick = 1:length(tick_x)%draw ticks - Screen('DrawLine', p.ptb.w, p.stim.red, tick_x(tick), rect(2), tick_x(tick), rect(2)+rect(4) , 3); - if tick <= tSection && numbersOn - Screen('TextSize', p.ptb.w,p.text.fontsize); - DrawFormattedText(p.ptb.w, mat2str(tick) , tick_x(tick)+ss/2, rect(2)+rect(4), p.stim.white); - Screen('TextSize', p.ptb.w,p.text.fontsize); - end - if tick == 1 - DrawFormattedText(p.ptb.w, labels{1},tick_x(tick)-bb_size*1.4,rect(2), p.stim.white); - elseif tick == tSection+1 - DrawFormattedText(p.ptb.w, labels{2},tick_x(tick)+bb_size*0.4,rect(2), p.stim.white); - end - end - %slider coordinates - if ~isnan(position) - slider = [ tick_x(position)+tick_size*0.1 rect(2) tick_x(position)+tick_size*0.9 rect(2)+rect(4)]; - %draw the slider - Screen('FillRect',p.ptb.w, p.stim.white, round(slider)); - end - Screen('TextSize', p.ptb.w,p.text.fontsize); - DrawFormattedText(p.ptb.w,message, 'center', p.ptb.midpoint(2)*0.2, p.stim.white,[],[],[],2); - Screen('TextSize', p.ptb.w,p.text.fontsize); - t = Screen('Flip',p.ptb.w); - Log(t,-2,NaN); - end - end - function [rating, rt ,mans] = RatingCircle(rect,tSection,secs,position,up,down,left,right,labels,message,numbersOn,ratingDur) - timewaitend= GetSecs + ratingDur; - while GetSecs<=timewaitend - % - %Detect the bounding boxes of the labels. - for nlab = 1:2 - [~ , ~, bb(nlab,:)]=DrawFormattedText(p.ptb.w,labels{nlab}, 'center', 'center', p.stim.white,[],[],[],2); - Screen('FillRect',p.ptb.w,p.var.current_bg); - end - bb = max(bb); - bb_size = bb(3)-bb(1);%vertical size of the bb. - % - cc = 0; - DrawSkala; -% rating = NaN; - ok = 1; - while ok == 1 && GetSecs<=timewaitend - [secs, keyCode, ~] = KbStrokeWait(p.ptb.device,timewaitend); - cc = cc+1; - keyCode = find(keyCode); - if length(keyCode) == 1%this loop avoids crashes to accidential presses of meta keys - switch keyCode - case up - position = 1; - case down - position = 2; - case left - position = 3; - case right - position = 4; - end - Log(secs,7,keyCode); -% ok =0; - if positiontimewaitend - break - end - end - if GetSecs>timewaitend - break - end - end -% entTime=GetSecs; - function DrawSkala - %rating = tSection - position + 1; - rating = position ; - rt = secs; - if cc>0 - mans.rating(cc) = position; - mans.rt(cc) = secs; - else - mans.rating(cc+1) = NaN; - mans.rt(cc+1) = NaN; - end - - tick_size = rect(3)./tSection; - ss = tick_size*0.25;%slider size. - tick_x = linspace(rect(1),rect(1)+rect(3),(tSection/2)+1);%tick positions - tick_y = linspace(rect(2),rect(2)+rect(4),(tSection/2)+1);%tick positions - pointList(:,:,1)=[tick_x(2)-ss tick_y(1); tick_x(2) tick_y(1)-ss; tick_x(2)+ss tick_y(1); tick_x(2) tick_y(1)+ss]; - pointList(:,:,2)=[tick_x(3)-ss tick_y(2); tick_x(3) tick_y(2)-ss; tick_x(3)+ss tick_y(2); tick_x(3) tick_y(2)+ss]; - pointList(:,:,3)=[tick_x(2)-ss tick_y(3); tick_x(2) tick_y(3)-ss; tick_x(2)+ss tick_y(3); tick_x(2) tick_y(3)+ss]; - pointList(:,:,4)=[tick_x(1)-ss tick_y(2); tick_x(1) tick_y(2)-ss; tick_x(1)+ss tick_y(2); tick_x(1) tick_y(2)+ss]; - - % - for tick = 1:tSection%draw ticks - slider = [pointList(2,1,tick) pointList(1,2,tick) pointList(3,1,tick) pointList(4,2,tick)]; - Screen('FillOval', p.ptb.w, p.stim.white, round(slider)); -% Screen('DrawLine', p.ptb.w, [255 0 0], tick_x(tick), rect(2), tick_x(tick), rect(2)+rect(4) , 3); - if tick <= tSection && numbersOn - Screen('TextSize', p.ptb.w,p.text.fontsize); - DrawFormattedText(p.ptb.w, mat2str(tick) , round(pointList(2,1,tick))+1.5*ss, round(pointList(1,2,tick))+1.5*ss, p.stim.white); - Screen('TextSize', p.ptb.w,p.text.fontsize); - end - if tick == 1 - DrawFormattedText(p.ptb.w, labels{1},round(pointList(2,1,tick))+bb_size*1.4,round(pointList(1,2,tick)), p.stim.white); - elseif tick == tSection - DrawFormattedText(p.ptb.w, labels{2},round(pointList(2,1,tick))-bb_size*1.4,round(pointList(1,2,tick)), p.stim.white); - end - end - %slider coordinates - if ~isnan(position) - %draw the slider - slider = [pointList(2,1,position) pointList(1,2,position) pointList(3,1,position) pointList(4,2,position)]; - Screen('FillOval', p.ptb.w, p.stim.red, round(slider)); - end - Screen('TextSize', p.ptb.w,p.text.fontsize); - DrawFormattedText(p.ptb.w,message, 'center', p.ptb.midpoint(2)*0.2, p.stim.white,[],[],[],2); - Screen('TextSize', p.ptb.w,p.text.fontsize); - t = Screen('Flip',p.ptb.w); - Log(t,-2,NaN); - end - end - function ShowInstruction(nInstruct,waitforkeypress) - %ShowInstruction(nInstruct,waitforkeypress) - %if waitforkeypress is 1, then subject has to press a button to - %make the instruction text dissappear. Otherwise you have to take - %care of it later - - [text]= GetText(nInstruct); - if ismember(nInstruct,[31:1:36]) - imageArray = imread(char(strcat(p.path.cue,num2str(nInstruct-30),'.png'))); - Screen('FillRect', p.ptb.w , p.stim.bg ); %always create a gray background - Screen('PutImage', p.ptb.w, imageArray); - DrawFormattedText(p.ptb.w,text, 'center', p.ptb.midpoint(2)*0.2, p.stim.white,[],[],[],2); -% DrawFormattedText(p.ptb.w, text, 'center', 'center',p.stim.white,[],[],[],2,[]); - Screen('DrawingFinished',p.ptb.w,0); - t=Screen('Flip',p.ptb.w); - - else - ShowText(text); - end - - %let subject read it and ask confirmation to proceed. But we don't - %need that in the case of INSTRUCT = 5; - if waitforkeypress - if nInstruct ~= 14%this is for the Reiz kommnt - KbStrokeWait(p.ptb.device); - else - WaitSecs(2.5+rand(1)); - end - Screen('FillRect',p.ptb.w,p.var.current_bg); - t = Screen('Flip',p.ptb.w); - else - if ~ismember(nInstruct,[14]);%this is for the Reiz kommnt and danke message at the end - KbStrokeWait(p.ptb.device); - else - WaitSecs(1+rand(1)); - end - end - - - function ShowText(text) - - Screen('FillRect',p.ptb.w,p.var.current_bg); - DrawFormattedText(p.ptb.w, text, 'center', 'center',p.stim.white,[],[],[],2,[]); - t=Screen('Flip',p.ptb.w); - Log(t,-1,nInstruct); - %show the messages at the experimenter screen - fprintf('=========================================================\n'); - fprintf('Text shown to the subject:\n'); - fprintf(text); - fprintf('=========================================================\n'); - - end - end - function [text]=GetText(nInstruct) - if nInstruct == 0%Eyetracking calibration - - text = ['Wir kalibrieren jetzt den Eye-Tracker.\n\n' ... - 'Bitte fixieren Sie die nun folgenden weißen Kreise und \n' ... - 'bleiben so lange darauf, wie sie zu sehen sind.\n\n' ... - 'Nach der Kalibrierung dürfen Sie Ihren Kopf nicht mehr bewegen.\n'... - 'Sollten Sie Ihre Position noch verändern müssen, tun Sie dies jetzt.\n'... - 'Die beste Position ist meist die bequemste.\n\n'... - 'Bitte drücken Sie jetzt den oberen Knopf, \n' ... - 'um mit der Kalibrierung weiterzumachen.\n' ... - ]; - - elseif nInstruct == 3%third Instr. of the training phase. - text = ['Wir sind jetzt kurz vor Beginn des Experiments.\n'... - 'Wir möchten Sie nun noch einmal an die wichtigsten Punkte erinnern.\n\n'... - 'Drücken Sie eine beliebige Taste um fortzufahren.\n' ... - ]; - elseif nInstruct == 30%third Instr. of the training phase. - text = [' Es gibt 6 verschiedene Hinweisreize.\n' ... - ]; - elseif nInstruct == 31%third Instr. of the training phase. - text = ['Dies ist ein Hinweisreiz für \n'... - 'NIEDRIGEN SCHMERZ!\n' ... - ]; - elseif nInstruct == 32%third Instr. of the training phase. - text = ['Dies ist ein Hinweisreiz für \n'... - 'MITTELEREN SCHMERZ!\n' ... - ]; - elseif nInstruct == 33%third Instr. of the training phase. - text = ['Dies ist ein Hinweisreiz für \n'... - 'STARKEN SCHMERZ!\n' ... - ]; - elseif nInstruct == 34%third Instr. of the training phase. - text = ['Dies ist ein Hinweisreiz für ein \n'... - 'NEUTRALES BILD!\n' ... - ]; - elseif nInstruct == 35%third Instr. of the training phase. - text = ['Dies ist ein Hinweisreiz für ein \n'... - 'MITTELSCHLIMMES BILD!\n' ... - ]; - elseif nInstruct == 36%third Instr. of the training phase. - text = ['Dies ist ein Hinweisreiz für ein \n'... - 'SEHR SCHLIMMES BILD!\n' ... - ]; - elseif nInstruct == 37%third Instr. of the training phase. - text = ['und, einige andere wichtige Punkte:\n'... - ]; - elseif nInstruct == 301%third Instr. of the training phase. - text = ['1/ Konzentrieren Sie sich immer auf das Fixationskreuz.\n'... - ]; - elseif nInstruct == 302%third Instr. of the training phase. - text = ['2/ Merken Sie sich immer den Informationsgehalt des Hinweisreizes (Dreiecke).\n'... - ]; - elseif nInstruct == 303%third Instr. of the training phase. - text = ['3/ Bitte bewerten Sie die Wertigkeit \n'... - 'des Hinweisreizes in den Überprüfungsdurchgängen \n'... - ]; - elseif nInstruct == 304%third Instr. of the training phase. - text = ['4/ Lassen Sie sich vom Scannergeschehen nicht stören.\n'... - ]; - elseif nInstruct == 305%third Instr. of the training phase. - text = ['5/ Bewegen Sie sich nicht.\n'... - ]; - elseif nInstruct == 306%third Instr. of the training phase. - text = ['Drücken Sie jetzt die obere Taste, \n'... - 'das Experiment startet dann in wenigen Sekunden.\n' ... - ]; - elseif nInstruct == 9% - %=================================================================================================================% - text = ['Schmerz (1) oder Bild (2) ?']; - elseif nInstruct == 10 - text = ['Wie war die Intensität?']; - elseif nInstruct == 12 %These two below are the possible responses to the question in 11 -% text = {'Sehr\nwahrscheinlich'}; - text = {'stark'}; - elseif nInstruct == 13 -% text = {'Überhaupt\nnicht\nwahrscheinlich'}; - text = {'neutral'}; - else - text = {''}; - end - end - function SetPTB - %KbName('UnifyKeyNames'); - %Sets the parameters related to the PTB toolbox. Including - %fontsizes, font names. - %Default parameters - Screen('Preference', 'SkipSyncTests', 1); - Screen('Preference', 'DefaultFontSize', p.text.intfontsize); - Screen('Preference', 'DefaultFontName', p.text.fontname); - Screen('Preference', 'TextAntiAliasing',2);%enable textantialiasing high quality - Screen('Preference', 'VisualDebuglevel', 0); -% Screen('Preference', 'SkipSyncTests', 1); - Screen('Preference', 'SuppressAllWarnings', 1); - %%Find the number of the screen to be opened - screens = Screen('Screens'); - p.ptb.screenNumber = max(screens);%the maximum is the second monitor -% p.ptb.screenNumber = 1;%max(screens);%the maximum is the second monitor - - %Make everything transparent for debugging purposes. - if debug - commandwindow; - PsychDebugWindowConfiguration; - end - %set the resolution correctly - res = Screen('resolution',p.ptb.screenNumber); -% HideCursor(p.ptb.screenNumber); - %spit out the resolution - fprintf('Resolution of the screen is %dx%d...\n',res.width,res.height); - - %Open a graphics window using PTB - [p.ptb.w p.ptb.rect] = Screen('OpenWindow', p.ptb.screenNumber, p.var.current_bg); - Screen('BlendFunction', p.ptb.w, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - Screen('Flip',p.ptb.w);%make the bg - p.ptb.slack = Screen('GetFlipInterval',p.ptb.w)./2; - [p.ptb.width, p.ptb.height] = Screen('WindowSize', p.ptb.screenNumber); - p.ptb.ifi = Screen('GetFlipInterval', p.ptb.w); - - %find the mid position on the screen. - p.ptb.midpoint = [ p.ptb.width./2 p.ptb.height./2]; -% p.ptb.cue_win = [0.5*res.width-0.125*p.cue.width 0.5*res.height+0.125*p.cue.height 0.5*res.width+0.125*p.cue.width 0.5*res.height+0.375*p.cue.height; -% 0.5*res.width-0.25*p.cue.width 0.5*res.height-0.05*p.cue.height 0.5*res.width+0.25*p.cue.width 0.5*res.height+0.45*p.cue.height; -% 0.5*res.width-0.5*p.cue.width 0.5*res.height-0.35*p.cue.height 0.5*res.width+0.5*p.cue.width 0.5*res.height+0.65*p.cue.height; -% ]; - p.ptb.cue_win = [0.5*res.width-0.125*p.cue.width 0.5*res.height-0.165*p.cue.height 0.5*res.width+0.125*p.cue.width 0.5*res.height+0.085*p.cue.height; - 0.5*res.width-0.25*p.cue.width 0.5*res.height-0.33*p.cue.height 0.5*res.width+0.25*p.cue.width 0.5*res.height+0.17*p.cue.height; - 0.5*res.width-0.5*p.cue.width 0.5*res.height-0.66*p.cue.height 0.5*res.width+0.5*p.cue.width 0.5*res.height+0.34*p.cue.height; - ]; - - %NOTE about RECT: - %RectLeft=1, RectTop=2, RectRight=3, RectBottom=4. - p.ptb.cuerect = [ p.ptb.midpoint(1)-p.cue.width/2 p.ptb.midpoint(2)-p.cue.height/2 p.ptb.midpoint(1)-p.cue.width/2+p.cue.width p.ptb.midpoint(2)-p.cue.height/2+p.cue.height]; - p.ptb.imrect = [ p.ptb.midpoint(1)-p.stim.width/2 p.ptb.midpoint(2)-p.stim.height/2 p.ptb.midpoint(1)-p.stim.width/2+p.stim.width p.ptb.midpoint(2)-p.stim.height/2+p.stim.height]; - p.ptb.cross_shift = [0 0];%[180 -120]./2.5;%incremental upper and lower cross positions - p.ptb.CrossPosition_x = p.ptb.midpoint(1);%bb(1);%always the same - p.ptb.CrossPosition_y = p.ptb.midpoint(2)+p.ptb.cross_shift;%bb(1);%always the same - %cross position for the eyetracker screen. - p.ptb.CrossPositionET_x = [p.ptb.midpoint(1) p.ptb.midpoint(1)]; - p.ptb.CrossPositionET_y = [p.ptb.midpoint(2)-p.ptb.cross_shift(2) p.ptb.midpoint(2)+p.ptb.cross_shift(2)]; - p.ptb.fc_size = 10; - % - %% - %priorityLevel=MaxPriority(['GetSecs'],['KbCheck'],['KbWait'],['GetClicks']); - Priority(MaxPriority(p.ptb.w)); - %this is necessary for the Eyelink calibration - %InitializePsychSound(0) - %sound('Open') - % Beeper(1000) - LoadPsychHID - %%%%%%%%%%%%%%%%%%%%%%%%%%%Prepare the keypress queue listening. - p.ptb.device = []; - %get all the required keys in a vector - p.ptb.keysOfInterest = [];for i = fields(p.keys)';p.ptb.keysOfInterest = [p.ptb.keysOfInterest p.keys.(i{1})];end - fprintf('Key listening will be restricted to %d\n',p.ptb.keysOfInterest) - RestrictKeysForKbCheck(p.ptb.keysOfInterest); - - p.ptb.keysOfInterest=zeros(1,256); - p.ptb.keysOfInterest(p.keys.confirm) = 1; - %create a queue sensitive to only relevant keys. - % KbQueueCreate(p.ptb.device,p.ptb.keysOfInterest);%default device. - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %prepare parallel port communication. This relies on cogent i - %think. We could do it with PTB as well. -% if ismac -% config_io64; -% outp(p.com.lpt.address,0); -% if( cogent.io.status ~= 0 ) -% error('inp/outp installation failed'); -% end -% end - if ~strcmp(p.hostname,'Sepideh-PC') - config_io; - outp(p.com.lpt.address,0); - outp(p.com.lpt.thermode,0); % closes all channels - thermode LPT - if( cogent.io.status ~= 0 ) - error('inp/outp installation failed'); - end - end - %CORRECT - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %test whether CED receives the triggers correctly... - k = 0; - while ~(k == 25 | k == 86 ); - pause(0.1); - outp(p.com.lpt.address,128);% index for start of the experiment - fprintf('=================\nDid the trigger test work?\n\n!!!!!!You MUST observe 5 pulses on the PHYSIOCOMPUTER!!!!!\n\nPress c to send it again, v to continue...\n') - [~, k] = KbStrokeWait(p.ptb.device,GetSecs+2); - if isempty(k) - k = 25; - else - k = find(k); - end - end - fprintf('Continuing...\n'); - % - p.rating.rect = [p.ptb.width*0.2 p.ptb.midpoint(2) p.ptb.width*0.6 100]' -% p.rating.crect = [p.ptb.width*0.31-35 p.ptb.height*0.195 p.ptb.width*0.41-35 p.ptb.height*0.505]'+20; - p.rating.crect =[300 170 400 410]'; -% p.ptb.rateDiam = 0.33*p.ptb.height; -% p.rating.crect = [ p.ptb.midpoint(1)-p.ptb.rateDiam/2 p.ptb.midpoint(2)-p.ptb.rateDiam/2 p.ptb.midpoint(1)-p.ptb.rateDiam/2+p.ptb.rateDiam p.ptb.midpoint(2)-p.ptb.rateDiam/2+p.ptb.rateDiam]; - - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %load the pictures to the memory. - p.ptb.stim_sprites = CreateStimSprites(p.stim.files);% - %% - function [out]=CreateStimSprites(files) - %loads all the stims to video memory - for nStim = 1:p.stim.tFile - fprintf('Making PTB Texture for stimulus %i of %i\n',nStim,p.stim.tFile); - filename = files(nStim,:); - [im , ~, ~] = imread(filename); - out(nStim) = Screen('MakeTexture', p.ptb.w, im ); - end - end - end - function [t]=StopEyelinkRecording - Eyelink('StopRecording'); - t = GetSecs; - %this is the end of the trial scope. - WaitSecs(0.01); - Eyelink('Message', 'TRIAL_RESULT 0'); - % - WaitSecs(0.01); - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('Command', 'clear_screen %d', 0); - Screen('Textsize', p.ptb.w,p.text.fontsize); - Log(t,8,NaN); - end - - function [t]=StartEyelinkRecording(nTrial,nStim,phase,pain,fix) - t = []; - nStim = double(nStim); - Eyelink('Message', 'TRIALID: %04d, PHASE: %04d, FILE: %04d, pain: %04d, FIXX: %04d, FIXY %04d', nTrial, phase, nStim, double(pain),fix(1),fix(2)); - Eyelink('Message', 'FX Onset at %d %d',fix(1),fix(2)); - % an integration message so that an image can be loaded as - % overlay background when performing Data Viewer analysis. - WaitSecs(0.01); - %return - if nStim~=0 - Eyelink('Message', '!V IMGLOAD CENTER %s %d %d', p.stim.files(nStim,:), p.ptb.midpoint(1), p.ptb.midpoint(2)); - end - % This supplies the title at the bottom of the eyetracker display - Eyelink('Command', 'record_status_message "Stim: %02d, Phase: %d"', nStim, phase); - % - %Put the tracker offline and draw the stimuli. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - % clear tracker display and draw box at center - Eyelink('Command', 'clear_screen %d', 0); - %draw the image on the screen but also the two crosses - if (nStim <= 16 && nStim>0) - %Eyelink('ImageTransfer',p.stim.files24(nStim,:),p.ptb.imrect(1),p.ptb.imrect(2),p.stim.width,p.stim.height,p.ptb.imrect(1),p.ptb.imrect(2),0); - end - Eyelink('Command', 'draw_cross %d %d 15',fix(1),fix(2)); - Eyelink('Command', 'draw_cross %d %d 15',fix(1),fix(2)+diff(p.ptb.cross_shift)); - - % - %drift correction - %EyelinkDoDriftCorrection(el,crosspositionx,crosspositiony,0,0); - %start recording following mode transition and a short pause. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('StartRecording'); - t = GetSecs; - Log(t,2,NaN); - end - function [shuffled idx] = Shuffle(vector,N) - %takes first N from the SHUFFLED before outputting. This function - %could be used as a replacement for randsample - if nargin < 2;N = length(vector);end - [~, idx] = sort(rand([1 length(vector)])); - shuffled = vector(idx(1:N)); - shuffled = shuffled(:); - end - function Buzz - outp(p.com.lpt.thermode, 2 ); %D1 on LPT1 - WaitSecs(p.duration.pain); - outp(p.com.lpt.thermode, 0); -% WaitSecs(p.duration.intershockpulse); - end - function MarkCED(socket,port) - %send pulse to SCR# - outp(socket,port); - WaitSecs(0.01); - outp(socket,0); - end - function InitEyeLink - % - if EyelinkInit(0)%use 0 to init normaly - fprintf('=================\nEyelink initialized correctly...\n') - else - fprintf('=================\nThere is problem in Eyelink initialization\n') - keyboard; - end - % - WaitSecs(0.5); - [~, vs] = Eyelink('GetTrackerVersion'); - fprintf('=================\nRunning experiment on a ''%s'' tracker.\n', vs ); - - %load 24bits pictures for eyelink... - dummy = dir([p.path.stim24 '*.bmp']); - p.stim.files24 = [repmat([fileparts(p.path.stim24) filesep],length(dummy),1) vertcat(dummy(:).name)]; - % - el = EyelinkInitDefaults(p.ptb.w); - %update the defaults of the eyelink tracker - el.backgroundcolour = p.stim.bg; - el.msgfontcolour = WhiteIndex(el.window); - el.imgtitlecolour = WhiteIndex(el.window); - el.targetbeep = 0; - el.calibrationtargetcolour = WhiteIndex(el.window); - el.calibrationtargetsize = 1.5; - el.calibrationtargetwidth = 0.5; - el.displayCalResults = 1; - el.eyeimgsize = 50; - el.waitformodereadytime = 25;%ms - el.msgfont = 'Times New Roman'; - el.cal_target_beep = [0 0 0];%[1250 0.6 0.05]; - %shut all sounds off - el.drift_correction_target_beep = [0 0 0]; - el.calibration_failed_beep = [0 0 0]; - el.calibration_success_beep = [0 0 0]; - el.drift_correction_failed_beep = [0 0 0]; - el.drift_correction_success_beep= [0 0 0]; - EyelinkUpdateDefaults(el); - PsychEyelinkDispatchCallback(el); - - % open file. - res = Eyelink('Openfile', p.path.edf); - % - Eyelink('command', 'add_file_preamble_text ''Recorded by EyelinkToolbox FearAmy Experiment (Selim Onat)'''); - Eyelink('command', 'screen_pixel_coords = %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - Eyelink('message', 'DISPLAY_COORDS %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - % set calibration type. - Eyelink('command','auto_calibration_messages = YES'); - Eyelink('command', 'calibration_type = HV13'); - Eyelink('command', 'select_parser_configuration = 1'); - %what do we want to record - Eyelink('command', 'file_sample_data = LEFT,RIGHT,GAZE,HREF,AREA,GAZERES,STATUS,INPUT,HTARGET'); - Eyelink('command', 'file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON,INPUT'); - Eyelink('command', 'use_ellipse_fitter = no'); - % set sample rate in camera setup screen - Eyelink('command', 'sample_rate = %d',1000); - end - function StopEyelink(filename) - try - fprintf('Trying to stop the Eyelink system with StopEyelink\n'); - Eyelink('StopRecording'); - Log(t,8,NaN); - WaitSecs(0.5); - Eyelink('Closefile'); - display('receiving the EDF file...'); - Eyelink('ReceiveFile',filename,p.path.path_edf,1); - display('...finished!') - % Shutdown Eyelink: - Eyelink('Shutdown'); - catch - display('StopEyeLink routine didn''t really run well'); - end - end - function cleanup - % Close window: - sca; - %set back the old resolution - if strcmp(p.hostname,'triostim1') - % Screen('Resolution',p.ptb.screenNumber, p.ptb.oldres.width, p.ptb.oldres.height ); - %show the cursor - ShowCursor(p.ptb.screenNumber); - end - % - commandwindow; - KbQueueStop(p.ptb.device); - KbQueueRelease(p.ptb.device); - end - function CalibrateEL - fprintf('=================\n=================\nEntering Eyelink Calibration\n') - p.var.ExpPhase = 0; - ShowInstruction(0,1); - EyelinkDoTrackerSetup(el); - %Returns 'messageString' text associated with result of last calibration - [~, messageString] = Eyelink('CalMessage'); - Eyelink('Message','%s',messageString);% - WaitSecs(0.05); - fprintf('=================\n=================\nNow we are done with the calibration\n') - end - function Log(ptb_time, event_type, event_info) - %Phases: - %Instruction : 0 - %Test : 1 - %Rating : 5 - %Calibration : 0 - % - %event types are as follows: - % - %Pulse Detection : 0 info: NaN; - %Tracker Onset : 1 - %Cross Onset : 2 info: position - %Stimulus Onset : 3 info: dist_id - %Cross Movement : 4 info: NaN; - %pain Delivery : 5 info: NaN; - %Stimulus Offset : 6 info: NaN; - %Key Presses : 7 info: NaN; - %Tracker Offset : 8 info: NaN; - % - %Text on the screen : -1 info: Which Text? - %RatingScreen Onset : -2 info: NaN; - for iii = 1:length(ptb_time) - p.var.event_count = p.var.event_count + 1; - p.out.log(p.var.event_count,:) = [ptb_time(iii) event_type event_info(iii) p.var.ExpPhase]; - end - % plot(p.out.log(1:p.var.event_count,1) - p.out.log(1,1),p.out.log(1:p.var.event_count,2),'o','markersize',10); - % ylim([-2 8]); - % set(gca,'ytick',[-2:8],'yticklabel',{'Rating On','Text','Pulse','Tracker+','Cross+','Stim+','CrossMov','pain','Stim-','Key+','Tracker-'}); - % grid on - % drawnow; - - end - function [secs]=WaitPulse(keycode,n) - %[secs]=WaitPulse(keycode,n) - % - % This function waits for the Nth upcoming pulse. If N=1, it will wait for - % the very next pulse to arrive. 1 MEANS NEXT PULSE. So if you wish to wait - % for 6 full dummy scans, you should use N = 7 to be sure that at least 6 - % full acquisitions are finished. - % - % The function avoids KbCheck, KbWait functions, but relies on the OS - % level event queues, which are much less likely to skip short events. A - % nice discussion on the topic can be found here: - % http://ftp.tuebingen.mpg.de/pub/pub_dahl/stmdev10_D/Matlab6/Toolboxes/Psychtoolbox/PsychDocumentation/KbQueue.html - - %KbQueueFlush;KbQueueStop;KbQueueRelease;WaitSecs(1); - fprintf('Will wait for %i dummy pulses...\n',n); - if n ~= 0 - secs = nan(1,n); - pulse = 0; - dummy = []; - while pulse < n - dummy = KbTriggerWait(keycode,p.ptb.device); - pulse = pulse + 1; - secs(pulse+1) = dummy; - Log(dummy,0,NaN); - end - else - secs = GetSecs; - end - end - function [keycode, secs] = KbQueueDump; - %[keycode, secs] = KbQueueDump - % Will dump all the events accumulated in the queue. - - keycode = []; - secs = []; - pressed = []; - %fprintf('there are %03d events\n',KbEventAvail(p.ptb.device)); - while KbEventAvail(p.ptb.device) - [evt, n] = KbEventGet(p.ptb.device); - n = n + 1; - keycode(n) = evt.Keycode; - pressed(n) = evt.Pressed; - secs(n) = evt.Time; - % fprintf('Event is: %d\n',keycode(n)); - end - i = pressed == 1; - keycode(~i) = []; - secs(~i) = []; - %fprintf('there are %03d events found...\n',length(keycode)); - end - function [z] = mymod(x,y) - z=mod(x,y); - if ~z - z=y; - end - end -end diff --git a/exp_Triads.m b/exp_Triads.m deleted file mode 100755 index 7a1f9ad..0000000 --- a/exp_Triads.m +++ /dev/null @@ -1,359 +0,0 @@ -function S=Triads(subject,repetition,stim_duration,familiarization) -%S=Triads(subject,repetition,stim_duration,familiarization) -% -%stim_duration is in milliseconds. - -clear mex global functions -cgshut; -StartTime = datestr(now,30); -% -%set the stimulus location -[dummy p.hostname] = system('hostname'); -p.hostname = cell2mat(regexp(p.hostname,'[A-z]','match')); -if strcmp(p.hostname,'isndeab')%laptop - location = ['C:\Users\onat\Documents\Experiments\']; -else%mainly behavioral lab - location = ['C:\USER\onat\Experiments\']; -end -stimfolder = 'Circle11_08Face_Frontal_SkinModerated_Transparent_Normalized'; -path2stim = [location 'Stimuli\Gradients\' stimfolder '\']; -path2experiment = [location 'Triads\']; -files = FileMatrix([path2stim '*.bmp']); -TotalStim = size(files,1); -%set the background gray according to the background of the stimuli -for i = 1:TotalStim;im = imread(files(i,:));bg(i)=im(1,1,1);end -if sum(diff(bg))==0;bg = double([bg(1) bg(1) bg(1)])./255;else;keyboard;end; -% -win = tukeywin(400,.1)*tukeywin(400,.1)'; -EdgeSize = 500; -h = sqrt(3)*EdgeSize./2; -pos_stim = [0 h/2 ; -EdgeSize/2 -h/2 ; EdgeSize/2 -h/2];%(x,y): up, left, right -pos_marker = [-h/4 0 -30; 0 -h/2 90; h/4 0 30];%(x,y): upper-left, bottom, upper-right -% -ConfigCogent; -% -CreateStimSprites(files,1:TotalStim,0);%load stimuli -CreateStimSprites(files,(1:TotalStim)+200,1);%load also the pink noise images that will be used as mask -CreateMarkerSprites; -%load the familiarization faces. -if familiarization - testfolder = 'Circle09_FaceFrontal_4IDnogender'; - path2test = [location 'Stimuli\Gradients\' testfolder '\']; - files = FileMatrix([path2test '*.bmp']); - TotalStim = size(files,1); - CreateStimSprites(files,(1:TotalStim)+10,0); - CreateStimSprites(files,(1:TotalStim)+210,1); -end -% -t = []; -size_stim = []; -size_sprite = []; -keyout = 0; -S = zeros(TotalStim); -index = [1 2; 2 3; 1 3]; -% -green = 60; -red = 91; -space = 71; -%create triplets; -T = []; -for repetition = 1:repetition; - dummy = PAL_MLDS_GenerateStimList(3, TotalStim, TotalStim, 1); - %first randomization - T = [T ; PositionBalancer(dummy)]; -end -tTriplet = size(T,1); - -%second randomization... -T = T(Shuffle(1:tTriplet,tTriplet),:); -%create 5 dummy triplets, these will be used for familiarization. -%save the sequence for later usage -Response.Sequence = T; -% -if familiarization - nFamiliarization = 5; - T = [T(1:nFamiliarization ,:)+10 ; T];%+10 ensures that we use another set of faces. -else - nFamiliarization = 0; -end -%mainloop; -Timer = 1; -tTriplet = size(T,1);%update the triplet number -for nTriplet = 1:tTriplet - - t = T(nTriplet,:);%current triplet - count([red green]) = Shuffle(1:3,2); - ShowStims(stim_duration); - MoveMarker; - %only record the results if passed the familiarization step. - if nTriplet > nFamiliarization - %record the start time with the presentation of the first stim. - if Timer - start_time = time; - Timer = 0; - end - %increment the selected pairs - S(sub2ind([TotalStim TotalStim],t(index(count(green),[1 2])),t(index(count(green),[2 1])))) = ... - S(sub2ind([TotalStim TotalStim],t(index(count(green),[1 2])),t(index(count(green),[2 1])))) + 2; - - red_c = setdiff(1:3,[count(green) count(red)]);%switch to the unselected one - - S(sub2ind([TotalStim TotalStim],t(index(count(red),[1 2])),t(index(count(red),[2 1])))) = ... - S(sub2ind([TotalStim TotalStim],t(index(count(red),[1 2])),t(index(count(red),[2 1])))) + 1; - %save the response to be on the safe side - Response.Green(nTriplet-nFamiliarization,:) = t(index(count(green),[1 2])); - Response.Red(nTriplet-nFamiliarization,:) = t(index(count(red),[1 2])); - % - end - - cgflip(bg); -end -cgtext('Danke...',0,0); -cgflip(bg); - -duration= round(time-start_time)./1000./60;%time since subject first pressed a button. -save([path2experiment '\data\' StartTime '_' stimfolder '_' subject],'S','duration','Response'); -wait(5000); -stop_cogent; -cgshut; - function MoveMarker - ShowMask; - cgrotatesprite(101, pos_marker(count(red) ,1) , pos_marker(count(red),2), pos_marker(count(red),3)); - cgrotatesprite(100, pos_marker(count(green),1) , pos_marker(count(green),2), pos_marker(count(green),3)); - cgflip(bg); - [keyout] = waitkeydown(Inf,[green red space]); - if keyout ~= space%stay inside as long as space is not pressed - Accumulate; - end - - function Accumulate - count(keyout) = count(keyout) + 1; - count(keyout) = mod(count(keyout)-1,3)+1; - if count(green) == count(red) - Accumulate; - else - MoveMarker; - end - end - end - function ShowStims(stim_duration) - for i = 1:3 - cgdrawsprite(t(i), pos_stim(i,1), pos_stim(i,2) ); - end - cgtext([ mat2str(nTriplet) '\' mat2str(tTriplet)],0,0); - cgflip(bg); - Wait(stim_duration); - end - function ShowMask - for i = 1:3 - cgdrawsprite(t(i)+200, pos_stim(i,1), pos_stim(i,2) ); - end - cgtext([ mat2str(nTriplet) '\' mat2str(tTriplet)],0,0); -% cgflip(bg); - end - function CreateStimSprites(files,sprite_index,shuffle) - - %loads all the stims to video memory, Sprites 1 to N are used, - %where N is the total number of stims, - tStim = size(files,1); - if length(sprite_index) ~= tStim - keyboard - end - - for nStim = 1:tStim - filename = files(nStim,:); - im = imread(filename); - if shuffle - im = repmat(maskit(Image2PinkNoise(rgb2gray(im)),win,bg(1)*255),[1 1 3]); - im = uint8(im); - end - size_stim = [size(im,1) size(im,2)]; - size_sprite = size_stim; - cgmakesprite(sprite_index(nStim),size_sprite(2),size_sprite(2),bg); - %cgloadarray(nStim,size_stim(2),size_stim(1),reshape(double(imrotate(im,90))./255,[size_stim(1)*size_stim(2) 3]),size_sprite(1),size_sprite(1)); - cgloadarray(sprite_index(nStim),size_stim(2),size_stim(1),reshape(double(imrotate(im))./255,[size_stim(1)*size_stim(2) 3]),size_sprite(1),size_sprite(1)); - end - function [im]=imrotate(im) - %I define a custom made imrotate because stim computer doesnt have - %one. - im = cat(3,rot90(im(:,:,1)),rot90(im(:,:,2)),rot90(im(:,:,3))); - end - function im = maskit(im,win,bg) - m = mean2(im); - im = (im - repmat(m,size(im))).*win + bg; - end - end - function CreateMarkerSprites - % - cgmakesprite(100,200,200,[0 0 1]); - cgpencol([0 1 0]); - cgsetsprite(100); - cgpolygon([-.5 0 .5].*100,[0 1 0].*-100); - cgpolygon([-.5 0 .5].*100,[0 1 0].*100); - cgtrncol(100, 'b'); - % - cgmakesprite(101,200,200,[0 0 1]); - cgpencol([1 0 0]); - cgsetsprite(101); - cgpolygon([-.5 0 .5].*100,[1 0 1].*-100); - cgpolygon([-.5 0 .5].*100,[1 0 1].*100); - cgtrncol(101, 'b'); - % - cgsetsprite(0); - end - function FM = FileMatrix(path) - %Takes a path with file extension associated to regexp (e.g. - %C:\blabl\bla\*.bmp) returns the file matrix - dummy = dir(path); - FM = [repmat([fileparts(path) filesep],length(dummy),1) vertcat(dummy(:).name)]; - end - function ConfigCogent - % - fs = 1; - res = 0; - config_display( fs, res, bg); - config_keyboard; - start_cogent; - cgfont('Arial',20) - cgpencol([1 1 1]) - cgflip(bg); - cgflip(bg); - end - function shuffled = Shuffle(vector,N) - %takes first N from the SHUFFLED before outputting. This function - %could be used as a replacement for randsample. - if nargin < 2;N = length(vector);end - [dummy, idx] = sort(rand([1 length(vector)])); - shuffled = vector(idx(1:N)); - shuffled = shuffled(:); - end - function [Tnew] = PositionBalancer(T) - %Balances stimulus and locations so that each stimulus is presented - %equally likely at all locations. - % - %number of different stimuli - TotalStim = length(unique(T)); - %number of possible pairs (not respecting position); - tPairs = (TotalStim-1)*(TotalStim-2)./2; - %number of times a given stimuli appears at a given location - tPerPos = tPairs./3; - if tPerPos ~= round(tPerPos) - display('The required balancing is not possible with the current parameters'); - return - end - %matrix to hold the position information organized as Stimulus x Location. - %As long as entries are <1 a given stimulus can be placed at that position. - M = zeros(TotalStim,3); - factor = 1./tPerPos; - for s = 1:size(T,1) - %get the current stimulus index; - y = T(s,:); - ok = 1; - %indices of positions. - x = [1 2 3]; - while ok - %if it is possible to place the stimuli at locations determined by - %X then do it. - %0.99 yapmamizin nedeni bazen factor * tPerPos bire esit gelmiyor - %roundoff errorleri yuzunden - if sum(diag(M(y,x)) > (1-factor*0.5)) == 0 - %increment positions by factor - M(y,x) = M(y,x) + diag(repmat(factor,1,3)); - ok = 0; - else%otherwise reshuffle x and try until it works. - x = Shuffle(x); - end - end - %store the new balanced T - Tnew(s,x) = T(s,1:3); - end - end - function [StimList] = PAL_MLDS_GenerateStimList(ptq, NumLevels, MaxDiff, NumRep) - % - %PAL_MLDS_GenerateStimList Generate stimulus sets of pairs, triads or - % quadruples for use in scaling experiment. - % - % syntax: StimList = PAL_MLDS_GenerateStimList(ptq, NumLevels, MaxDiff, - % NumRep) - % - % 'ptq' should be either 2, 3, or 4 depending on whether one wishes to - % generate pairs, triads or quadruples respectively. - % - % 'NumLevels' is the number of stimulus levels one wishes to utilize in - % experiment. - % - % 'MaxDiff' precludes stimulus combinations that are 'too far apart'. - % Specifically, if 'ptq' is set to 2, all stimulus pairs i-j (i < j) - % for which (j - i) has a value not exceeding 'MaxDiff' will be - % included in stimulus set. If 'ptq' is set to 3, all triads i-j-k - % (i < j < k) for which |(k - j) - (j - i)| has a value not exceeding - % 'MaxDiff' will be included in stimulus set. If 'ptq' is set to 4, - % all quadruples i-j-k-l (i < j < k < l) for which - % |(l - k) - (j - i)| has a value not exceeding 'MaxDiff' will be - % included in stimulus set. - % - % 'NumRep' sets the number of times each possible pair/triad/quadruple - % will be included in the stimulus set. - % - % Example: - % - % StimList = PAL_MLDS_GenerateStimList(2, 4, 1, 2) - % - % returns: - % - % StimList = - % - % 1 2 - % 2 3 - % 3 4 - % 1 2 - % 2 3 - % 3 4 - % - % PAL_randomizeArray may be used to obtain a randomized stimulus list, - % e.g.: - % - % StimList = PAL_randomizeArray(PAL_MLDS_GenerateStimList(2, 4, 1, 2)) - % - % will return the same list as above but now in a random order. - % - %Introduced: Palamedes version 1.0.0 (NP) - - - count = 0; - - if ptq == 2 - for i = 1:NumLevels-1 - for j = i+1:min(i+MaxDiff,NumLevels) - count = count+1; - StimList(count,:) = [i j]; - end - end - end - if ptq == 3 - for i = 1:NumLevels-2 - for j = i+1:NumLevels-1 - for k = j+1:NumLevels - count = count+1; - StimList(count,:) = [i j k]; - end - end - end - StimList = StimList(abs(StimList(:,3)-2*StimList(:,2)+StimList(:,1))<=MaxDiff,:); - end - if ptq == 4 - for i = 1:NumLevels-3 - for j = i+1:NumLevels-2 - for k = j+1:NumLevels-1 - for l = k+1:NumLevels - count = count+1; - StimList(count,:) = [i j k l]; - end - end - end - end - StimList = StimList(abs(StimList(:,4)-StimList(:,3)-StimList(:,2)+StimList(:,1))<=MaxDiff,:); - end - StimList = repmat(StimList,[NumRep 1]); - end -end diff --git a/exp_conton_SOURCE.m b/exp_conton_SOURCE.m deleted file mode 100644 index 908ba17..0000000 --- a/exp_conton_SOURCE.m +++ /dev/null @@ -1,425 +0,0 @@ - -%Contextual Modulation of old/new effects% -%14-Feb-2016, n.herweg@uke.de - -%% CLEAN UP -clear all;close all;clc; -PsychDefaultSetup(2); -sca; - -%seed random nurmber generator based on the current time -rng('shuffle'); - -%% DEFINE VARIABLES -%Phase 1: initial encoding -time.p1.pic = 1; -time.p1.fix = 1.5; -time.p1.resp = 2; - -n.p1.test.pics.targ = 2; -n.p1.test.pics.new = 160; -n.p1.test.shows.reg = 3;%times each regular image will be shown -n.p1.test.shows.targ = n.p1.test.shows.reg*(n.p1.test.pics.new/10); -n.p1.test.trials = n.p1.test.pics.new*n.p1.test.shows.reg + n.p1.test.pics.targ*n.p1.test.shows.targ; -n.p1.test.t2b = 96; %N trials until next break - -n.p1.train.pics.targ = n.p1.test.pics.targ; -n.p1.train.pics.new = 4; -n.p1.train.shows.reg = 3; -n.p1.train.shows.targ = n.p1.train.shows.reg*2; -n.p1.train.trials = n.p1.train.pics.new*n.p1.train.shows.reg + n.p1.train.pics.targ*n.p1.train.shows.targ; -n.p1.train.t2b = n.p1.train.trials; - -%Phase 2: Interleaved encoding/retrieval -time.p2.pic = time.p1.pic; -time.p2.fix = 2.3;%TBD 300ms to save everything & turn on tracker again, distribute trials across TR -time.p2.resp = 2.8;%TBD -time.trackerOff = 1.8;%200 ms to turn off tracker before button presses are recorded - -relnew.p2 = 1;%amount of new pictures relative to old ones - -n.p2.test.pics.old = n.p1.test.pics.new; -n.p2.test.pics.new = n.p2.test.pics.old*relnew.p2; -n.p2.test.tpb = 8; %number of trials per block TBD, Alternativ 16, 20 blocks, dann 5 runs -n.p2.test.trials = n.p2.test.pics.old + n.p2.test.pics.new; -n.p2.test.blocks = n.p2.test.trials/n.p2.test.tpb; -n.p2.test.runs = 5;%TBD Alternativ 10 a 4 Blöcke -n.p2.test.bpr = n.p2.test.blocks/n.p2.test.runs;%blocks per run -n.p2.test.tpr = n.p2.test.trials/n.p2.test.runs;%trials per run -n.p2.test.t2b = n.p2.test.tpr; %make a break after every run - -n.p2.train.pics.old = n.p1.train.pics.new; -n.p2.train.pics.new = n.p2.train.pics.old*relnew.p2; -n.p2.train.trials = n.p2.train.pics.old + n.p2.train.pics.new; -n.p2.train.tpb = 4; -n.p2.train.blocks = n.p2.train.trials/n.p2.train.tpb; -n.p2.train.runs = 1; -n.p2.train.bpr = n.p2.train.blocks/n.p2.train.runs;%blocks per run -n.p2.train.tpr = n.p2.train.trials/n.p2.train.runs;%trials per run -n.p2.train.t2b = n.p2.train.trials; - -%Phase 3: Final retrieval -time.p3.pic = time.p1.pic; -time.p3.fix = 3;%TBD -time.p3.resp = 4;%TBD - -relnew.p3 = 0.5;%amount of new pictures relative to old ones - -n.p3.test.pics.old = n.p2.test.pics.old + n.p2.test.pics.new; -n.p3.test.pics.new = n.p3.test.pics.old*relnew.p3; -n.p3.test.trials = n.p3.test.pics.old + n.p3.test.pics.new; -n.p3.test.t2b = 60; - -n.p3.train.pics.old = n.p2.train.pics.old + n.p2.train.pics.new;% -n.p3.train.pics.new = n.p3.train.pics.old*relnew.p3; -n.p3.train.trials = n.p3.train.pics.old + n.p3.train.pics.new; -n.p3.train.t2b = n.p3.train.trials; - -%General -n.pics.total = n.p1.test.pics.new + n.p1.test.pics.targ + n.p2.test.pics.new + n.p3.test.pics.new + n.p1.train.pics.new + n.p2.train.pics.new + n.p3.train.pics.new; - -inst2load.p1.train = [1,2]; -inst2load.p1.test = 3; -inst2load.p2.train = [4,5]; -inst2load.p2.test = 6; -inst2load.p3.train = [7,8]; -inst2load.p3.test = 9; - -thepart{1} = 'train'; -thepart{2} = 'test'; - -thecat{1} = 'inn'; -thecat{2} = 'out'; - -thecond{1} = 'enc'; -thecond{2} = 'ret'; - -thephase{1} = 'p1'; -thephase{2} = 'p2'; -thephase{3} = 'p3'; - -%% LOAD/CREATE FILEX -%enter subject ID -subID = input('Enter subject ID: ','s'); -if size(subID,2)>7 - error('ID is too long!') -end -fileName = ['CONTON_' num2str(subID) '.mat']; - -%Enter session number -phasei = input('Enter experimental phase (1, 2, or 3): '); -parti = input('Enter subpart (1 for training, 2 for testing): '); - -%specify project path -init = []; -[~, hostname] = system('hostname'); -init.(thephase{phasei}).hostname = deblank(hostname); - -switch init.(thephase{phasei}).hostname - case 'triostim1' - init.(thephase{phasei}).thepath.project = 'C:\USER\herweg\07_conton\MR'; - init.(thephase{phasei}).thepath.inst = [init.(thephase{phasei}).thepath.project '\experiment\instructions\buttonbox']; - addpath('C:\USER\herweg\ptb\exp_conton_functions'); - case 'isnf01faf2bafa4' - init.(thephase{phasei}).thepath.project = 'C:\Users\herweg\Documents\_Projekte\07_conton\MR'; - init.(thephase{phasei}).thepath.inst = [init.(thephase{phasei}).thepath.project '\experiment\instructions\keyboard']; - init.(thephase{phasei}).whichmonitor = input('Which monitor? Type s for small, l for large, e for eyetracking and lab 218.','s'); - addpath('C:\Users\herweg\Documents\GitHub\ptb\exp_conton_functions'); - case 'etpc' - init.(thephase{phasei}).thepath.project = 'C:\USER\herweg\07_conton\MR'; - init.(thephase{phasei}).thepath.inst = [init.(thephase{phasei}).thepath.project '\experiment\instructions\keyboard']; - addpath('C:\USER\herweg\ptb\exp_conton_functions'); -end -init.(thephase{phasei}).thepath.pics_inn = [init.(thephase{phasei}).thepath.project '\pics\inn_color\mean127RGB']; -init.(thephase{phasei}).thepath.pics_out = [init.(thephase{phasei}).thepath.project '\pics\out_color\mean127RGB']; -init.(thephase{phasei}).thepath.results = [init.(thephase{phasei}).thepath.project '\data']; - -init.(thephase{phasei}).debug = 0; %debug mode = 1, testing = 0 - -%init.thepath.scripts = [init.thepath.project '\experiment']; -%addpath(fullfile(init.thepath.project,'experiment\functions')); - - -%check if fileX already exists and warn, if overwriting is confirmed load -if exist(fullfile(init.(thephase{phasei}).thepath.results,fileName),'file') - - resp=input(['The file ' fileName ' already exists. Do you want to overwrite it? [Type ok to overwrite]'], 's'); - - if ~strcmp(resp,'ok') %abort experiment if overwriting was not confirmed - disp('experiment aborted') - return - end - newinit = init; - clear init - - load(fullfile(newinit.(thephase{phasei}).thepath.results,fileName)); %Loads the .m-file containing the subject's data. - load(fullfile(newinit.(thephase{phasei}).thepath.results,[fileName(1:end-4),'_init.mat'])); %Loads the .m-file containing the subject's data. - - init.(thephase{phasei}) = []; %this clears former initialization values (e.g. from training) - init.(thephase{phasei}) = newinit.(thephase{phasei}); - clear newinit -else - - init.continuous = 0; %all phases = 1, only current phase = 0 - %specify MR parameters - init.mr.ndummy = 6; - - fileX.subID = subID; - fileX.fileName = fileName; - fileX.keycond = input('Enter number for key mapping (1-4): ','s'); - - %assign category, condition, targetness and oldnew to trials - for partj = 1:size(thepart,2) - fileX.p1.(thepart{partj})(:,2) = repmat([1;2],n.p1.(thepart{partj}).trials/size(thecat,2),1);% 2 category - fileX.p1.(thepart{partj})(:,3) = [ones(n.p1.(thepart{partj}).pics.targ*n.p1.(thepart{partj}).shows.targ,1);ones(n.p1.(thepart{partj}).pics.new*n.p1.(thepart{partj}).shows.reg,1)*0];%3 targetness 1 = target, 0 = no target - fileX.p1.(thepart{partj})(:,1) = rand(size(fileX.p1.(thepart{partj}),1),1); - fileX.p1.(thepart{partj}) = sortrows(fileX.p1.(thepart{partj}),1); - fileX.p1.(thepart{partj})(:,1) = (1:n.p1.(thepart{partj}).trials);%1 trialnumber - fileX.p1.(thepart{partj})(fileX.p1.(thepart{partj})(:,3)==0,4) = 1; %all trials that are not targets are encoding trials - - fileX.p2.(thepart{partj})(:,1) = (1:n.p2.(thepart{partj}).trials);%1 trialnumber - - for blocki = 1:n.p2.(thepart{partj}).blocks %equal number of in/out and old/new per block - catrand(:,1) = repmat([1;2],n.p2.(thepart{partj}).tpb/size(thecat,2),1);% 2 category - catrand(:,2) = repmat([1;2;2;1],(n.p2.(thepart{partj}).tpb/size(thecat,2))/2,1);% 3 oldnew 1 = new; 2 = old - catrand(:,3) = rand(size(catrand,1),1); - catrand = sortrows(catrand,3); - - fileX.p2.(thepart{partj})(1+((blocki-1)*n.p2.(thepart{partj}).tpb):n.p2.(thepart{partj}).tpb+((blocki-1)*n.p2.(thepart{partj}).tpb),2:3) = catrand(:,1:2); - clear catrand - end - for runi = 1: n.p2.(thepart{partj}).runs - condrand = repmat([1;2],n.p2.(thepart{partj}).bpr/size(thecond,2),1); - condrand(:,2) = rand(size(condrand,1),1); - condrand = sortrows(condrand,2); - - fileX.p2.(thepart{partj})(1+((runi-1)*n.p2.(thepart{partj}).tpr):n.p2.(thepart{partj}).tpr+((runi-1)*n.p2.(thepart{partj}).tpr),4) = kron(condrand(:,1),ones(n.p2.(thepart{partj}).tpb,1));%4 encret 1 = enc; 2 = ret - clear condrand - end - end - - fileX.p3.test(:,2) = repmat([1;2],n.p3.test.trials/size(thecat,2),1);% 2 category - fileX.p3.test(:,3) = repmat([ones(16,1);ones(32,1)*2],10,1);%3 oldnew 1 = new; 2 = old - fileX.p3.test(:,4) = repmat([1;1;2;2],(n.p3.test.trials/size(thecat,2))/2,1);% 4 encret 1 = enc; 2 = ret - fileX.p3.test(:,5) = repmat([1;1;1;1;2;2;2;2],(n.p3.test.trials/size(thecat,2))/4,1);% 5 poldnew 1 = pnew; 2 = pold %% previously old or new in p2 - fileX.p3.test(:,1) = rand(size(fileX.p3.test,1),1); - fileX.p3.test = sortrows(fileX.p3.test,1); - fileX.p3.test(:,1) = (1:n.p3.test.trials);% 1 trialnumber - fileX.p3.test(fileX.p3.test(:,3) == 1,4:5) = 0;%condition 4 and 5 only exist for old images - - fileX.p3.train(:,2) = repmat([1;2],n.p3.train.trials/size(thecat,2),1);%in/outdoor - fileX.p3.train(:,3) = repmat([1;1;2;2;2;2],2,1);%3 old/new - fileX.p3.train(:,4) = repmat([0;0;1;1;2;2],2,1);% 4 encret 1 = enc; 2 = ret - fileX.p3.train(:,5) = [0;0;1;1;1;1;0;0;2;2;2;2];% 5 poldnew 1 = pnew; 2 = pold %% previously old or new in p2 - fileX.p3.train(:,1) = rand(size(fileX.p3.train,1),1); - fileX.p3.train = sortrows(fileX.p3.train,1); - fileX.p3.train(:,1) = 1:n.p3.train.trials; - - for cati = 1:size(thecat,2) - %assign scenes to phases of the experiment - sc.all(:,1) = (1:1:n.pics.total/2); - sc.all(:,2) = rand(size(sc.all,1),1); - sc.all = sortrows(sc.all,2); - sc.all(:,2) = [ones(n.p1.train.pics.new/size(thecat,2),1);ones(n.p1.train.pics.targ/size(thecat,2),1)*2;ones(n.p1.test.pics.new/size(thecat,2),1)*3;... - ones(n.p2.train.pics.new/size(thecat,2),1)*4;ones(n.p2.test.pics.new/size(thecat,2),1)*5;ones(n.p3.train.pics.new/size(thecat,2),1)*6;... - ones(n.p3.test.pics.new/size(thecat,2),1)*7];%1=train p1; 2=target p1; 3=test p1; 4=train p2; 5=test p2; 6=train p3; 7=test p3 - - sc.p1.train.new = sc.all(sc.all(:,2)==1,1); - sc.p1.train.targ = sc.all(sc.all(:,2)==2,1); - sc.p1.test.targ = sc.all(sc.all(:,2)==2,1); - sc.p1.test.new = sc.all(sc.all(:,2)==3,1); - sc.p2.train.new = sc.all(sc.all(:,2)==4,1); - sc.p2.test.new = sc.all(sc.all(:,2)==5,1); - sc.p3.train.new = sc.all(sc.all(:,2)==6,1); - sc.p3.test.new = sc.all(sc.all(:,2)==7,1); - - for partj = 1:size(thepart,2) - %adapt sc to the number of times each scene is shown and include old images from previous phases; randomize - %again - sc.p1.(thepart{partj}).new = repmat(sc.p1.(thepart{partj}).new,n.p1.(thepart{partj}).shows.reg,1); - sc.p1.(thepart{partj}).new(:,2) = rand(size(sc.p1.(thepart{partj}).new,1),1); - sc.p1.(thepart{partj}).new = sortrows(sc.p1.(thepart{partj}).new,2); - sc.p1.(thepart{partj}).new(:,2) = []; - - sc.p1.(thepart{partj}).targ = repmat(sc.p1.(thepart{partj}).targ,n.p1.(thepart{partj}).shows.targ,1); - sc.p1.(thepart{partj}).targ(:,2)= rand(size(sc.p1.(thepart{partj}).targ,1),1); - sc.p1.(thepart{partj}).targ = sortrows(sc.p1.(thepart{partj}).targ,2); - sc.p1.(thepart{partj}).targ(:,2)= []; - - sc.p2.(thepart{partj}).old = unique(sc.p1.(thepart{partj}).new); - sc.p2.(thepart{partj}).old(:,2) = rand(size(sc.p2.(thepart{partj}).old,1),1); - sc.p2.(thepart{partj}).old = sortrows(sc.p2.(thepart{partj}).old,2); - sc.p2.(thepart{partj}).old(:,2) = []; - - %put new and old scenes in fileX - fileX.p1.(thepart{partj})(fileX.p1.(thepart{partj})(:,2)==cati & fileX.p1.(thepart{partj})(:,4)==1,6) = sc.p1.(thepart{partj}).new; - fileX.p1.(thepart{partj})(fileX.p1.(thepart{partj})(:,2)==cati & fileX.p1.(thepart{partj})(:,4)==0,6) = sc.p1.(thepart{partj}).targ; - - fileX.p2.(thepart{partj})(fileX.p2.(thepart{partj})(:,2)==cati & fileX.p2.(thepart{partj})(:,3)==1,6) = sc.p2.(thepart{partj}).new; - fileX.p2.(thepart{partj})(fileX.p2.(thepart{partj})(:,2)==cati & fileX.p2.(thepart{partj})(:,3)==2,6) = sc.p2.(thepart{partj}).old; - - %sort old scenes for p3 according to assigned conditions - sc.p3.(thepart{partj}).old.pold.enc = fileX.p2.(thepart{partj})(fileX.p2.(thepart{partj})(:,2)==cati & fileX.p2.(thepart{partj})(:,3)==2 & fileX.p2.(thepart{partj})(:,4)==1,6); - sc.p3.(thepart{partj}).old.pnew.enc = fileX.p2.(thepart{partj})(fileX.p2.(thepart{partj})(:,2)==cati & fileX.p2.(thepart{partj})(:,3)==1 & fileX.p2.(thepart{partj})(:,4)==1,6); - - sc.p3.(thepart{partj}).old.pold.ret = fileX.p2.(thepart{partj})(fileX.p2.(thepart{partj})(:,2)==cati & fileX.p2.(thepart{partj})(:,3)==2 & fileX.p2.(thepart{partj})(:,4)==2,6); - sc.p3.(thepart{partj}).old.pnew.ret = fileX.p2.(thepart{partj})(fileX.p2.(thepart{partj})(:,2)==cati & fileX.p2.(thepart{partj})(:,3)==1 & fileX.p2.(thepart{partj})(:,4)==2,6); - - sc.p3.(thepart{partj}).old.pold.enc(:,2) = rand(size(sc.p3.(thepart{partj}).old.pold.enc,1),1); - sc.p3.(thepart{partj}).old.pnew.enc(:,2) = rand(size(sc.p3.(thepart{partj}).old.pnew.enc,1),1); - sc.p3.(thepart{partj}).old.pold.ret(:,2) = rand(size(sc.p3.(thepart{partj}).old.pold.ret,1),1); - sc.p3.(thepart{partj}).old.pnew.ret(:,2) = rand(size(sc.p3.(thepart{partj}).old.pnew.ret,1),1); - - sc.p3.(thepart{partj}).old.pold.enc = sortrows(sc.p3.(thepart{partj}).old.pold.enc,2); - sc.p3.(thepart{partj}).old.pnew.enc = sortrows(sc.p3.(thepart{partj}).old.pnew.enc,2); - sc.p3.(thepart{partj}).old.pold.ret = sortrows(sc.p3.(thepart{partj}).old.pold.ret,2); - sc.p3.(thepart{partj}).old.pnew.ret = sortrows(sc.p3.(thepart{partj}).old.pnew.ret,2); - - sc.p3.(thepart{partj}).old.pold.enc(:,2) = []; - sc.p3.(thepart{partj}).old.pnew.enc(:,2) = []; - sc.p3.(thepart{partj}).old.pold.ret(:,2) = []; - sc.p3.(thepart{partj}).old.pnew.ret(:,2) = []; - - fileX.p3.(thepart{partj})(fileX.p3.(thepart{partj})(:,2)==cati & fileX.p3.(thepart{partj})(:,3)==1,6) = sc.p3.(thepart{partj}).new; - fileX.p3.(thepart{partj})(fileX.p3.(thepart{partj})(:,2)==cati & fileX.p3.(thepart{partj})(:,3)==2 & fileX.p3.(thepart{partj})(:,4)==1 & fileX.p3.(thepart{partj})(:,5)==1,6) = sc.p3.(thepart{partj}).old.pnew.enc; - fileX.p3.(thepart{partj})(fileX.p3.(thepart{partj})(:,2)==cati & fileX.p3.(thepart{partj})(:,3)==2 & fileX.p3.(thepart{partj})(:,4)==1 & fileX.p3.(thepart{partj})(:,5)==2,6) = sc.p3.(thepart{partj}).old.pold.enc; - fileX.p3.(thepart{partj})(fileX.p3.(thepart{partj})(:,2)==cati & fileX.p3.(thepart{partj})(:,3)==2 & fileX.p3.(thepart{partj})(:,4)==2 & fileX.p3.(thepart{partj})(:,5)==1,6) = sc.p3.(thepart{partj}).old.pnew.ret; - fileX.p3.(thepart{partj})(fileX.p3.(thepart{partj})(:,2)==cati & fileX.p3.(thepart{partj})(:,3)==2 & fileX.p3.(thepart{partj})(:,4)==2 & fileX.p3.(thepart{partj})(:,5)==2,6) = sc.p3.(thepart{partj}).old.pold.ret; - end - clear sc - end - - clearvars -except fileX n thepart relnew thecat thecond time thephase inst2load init phasei parti - save(fullfile(init.(thephase{phasei}).thepath.results,fileX.fileName),'fileX'); - save(fullfile(init.(thephase{phasei}).thepath.results,[fileX.fileName(1:end-4),'_init.mat']),'init'); -end - -%% INITIALIZE PSYCHTOOLBOX -init.(thephase{phasei}).screens = Screen('Screens'); -init.(thephase{phasei}).screenNumber = max(init.(thephase{phasei}).screens);%The highest display number is a best guess about where you want the stimulus displayed -if init.(thephase{phasei}).debug - PsychDebugWindowConfiguration([],0.7) -else HideCursor; - - if strcmp(init.(thephase{phasei}).hostname,'triostim1') - Screen('Preference', 'SkipSyncTests', 1); - skipsync = input('You are skipping the sync test. Type y if you want to continue.','s'); - if ~strcmp(skipsync,'y') - error('Experiment aborted'); - end - end -end - -try - [init.(thephase{phasei}).expWin,init.(thephase{phasei}).rect] = PsychImaging('OpenWindow',init.(thephase{phasei}).screenNumber,[0.5 0.5 0.5]);%open onscreen Window -catch - [init.(thephase{phasei}).expWin,init.(thephase{phasei}).rect] = PsychImaging('OpenWindow',init.(thephase{phasei}).screenNumber,[0.5 0.5 0.5]);%open onscreen Window -end - -Priority(MaxPriority(init.(thephase{phasei}).expWin)); - -Screen('TextSize', init.(thephase{phasei}).expWin,24); -Screen('TextFont', init.(thephase{phasei}).expWin, 'Helvetica'); -init.(thephase{phasei}).refresh = Screen('GetFlipInterval', init.(thephase{phasei}).expWin); -init.(thephase{phasei}).slack = init.(thephase{phasei}).refresh/2; -[init.(thephase{phasei}).mx, init.(thephase{phasei}).my] = RectCenter(init.(thephase{phasei}).rect); -init.(thephase{phasei}).device = -1;%query all devices and report their merged state - -%Calculate stimulus size -init.(thephase{phasei}).imgsizepix = calcstimsize(init,thephase,phasei); - -%Load mex files now to not do it in the trial loop -KbCheck(init.(thephase{phasei}).device); -disp('======================'); -disp('Press any key to start'); -KbWait(init.(thephase{phasei}).device); -GetSecs; - -%Fixation cross -FixCr=ones(20,20)*0.5; -FixCr(10:11,:)=1;FixCr(:,10:11)=1; - -%% INITIALIZE EYELINK -if phasei == 2 && parti == 2 - - init.el.recmode = init.(thephase{phasei}).debug;%1 = no EL connected, dummy mode; 0 = EL connected - init.el.recal = 0;%just to initialize this variable - init.el.el = EyelinkInitDefaults(init.(thephase{phasei}).expWin); - - init.el.el.targetbeep = 0; % sound a beep when a target is presented - init.el.el.feedbackbeep = 0; - init.el.el.backgroundcolour = WhiteIndex(init.(thephase{phasei}).expWin)/2; - init.el.el.foregroundcolour = WhiteIndex(init.(thephase{phasei}).expWin); - init.el.el.msgfontcolour = WhiteIndex(init.(thephase{phasei}).expWin); - init.el.el.imgtitlecolour = WhiteIndex(init.(thephase{phasei}).expWin); - init.el.el.calibrationtargetcolour = WhiteIndex(init.(thephase{phasei}).expWin); - init.el.el.calibrationtargetsize = 1.5; - init.el.el.calibrationtargetwidth = 0.5; - init.el.el.displayCalResults = 1; - init.el.el.eyeimgsize = 50; - init.el.el.waitformodereadytime = 25;%ms - - EyelinkUpdateDefaults(init.el.el); - PsychEyelinkDispatchCallback(init.el.el); - - if ~EyelinkInit(init.el.recmode,1);%enable callback = 1 is default; if initialization does not work - error('Initialization not successful') - end - [init.el.v,init.el.vs] = Eyelink('GetTrackerVersion'); - - Eyelink('Openfile',[fileX.fileName(8:end-3),'edf']); - % Start recording - Eyelink('Message', 'TRIALID: %04d, NEWOLD: %d, ENCRET: %d, FIXX: %04d, FIXY %04d', 0, 0, 0, init.(thephase{phasei}).mx,init.(thephase{phasei}).my); - Eyelink('command', 'add_file_preamble_text ''Recorded by EyelinkToolbox CONTON Experiment (Nora Herweg)'''); - Eyelink('command', 'screen_pixel_coords = %ld %ld %ld %ld', 0, 0, init.p2.rect(3)-1, init.p2.rect(4)-1); - Eyelink('message', 'DISPLAY_COORDS %ld %ld %ld %ld', 0, 0, init.p2.rect(3)-1, init.p2.rect(4)-1); - % set calibration type. - Eyelink('command','auto_calibration_messages = YES'); - Eyelink('command', 'calibration_type = HV13'); - Eyelink('command', 'select_parser_configuration = 0');%1 = psychophysical setup, 0 = cognitive/standard - %what do we want to record - Eyelink('command', 'file_sample_data = LEFT,RIGHT,GAZE,HREF,AREA,GAZERES,STATUS,INPUT,HTARGET'); - Eyelink('command', 'file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON,INPUT'); - Eyelink('command', 'use_ellipse_fitter = no'); - Eyelink('command', 'pupil_size_diameter = NO'); - - % set sample rate in camera setup screen - Eyelink('command', 'sample_rate = %d',1000); - - insttexture = Screen('MakeTexture',init.(thephase{phasei}).expWin,uint8(imread(fullfile(init.(thephase{phasei}).thepath.inst,'calibration.png')))); - Screen('DrawTexture',init.(thephase{phasei}).expWin,insttexture); - Screen('Flip', init.(thephase{phasei}).expWin); - Screen('Close') - KbWait([], 2); - clear insttexture - - EyelinkDoTrackerSetup(init.el.el); - [~, messageString] = Eyelink('CalMessage'); - Eyelink('Message','%s',messageString); - WaitSecs(0.05); - - [ init.(thephase{phasei}).calibratePupil.sequenceComp,init.(thephase{phasei}).calibratePupil.targetMatX,init.(thephase{phasei}).calibratePupil.targetMatY ] = calibratePupil(round(init.(thephase{phasei}).imgsizepix),ones(3,4),init.(thephase{phasei}).expWin,2,init.el.el,init.(thephase{phasei}).mx,init.(thephase{phasei}).my,fullfile(init.p2.thepath.inst,'calibration_pupil.png'),fullfile(init.(thephase{phasei}).thepath.results,[fileX.fileName(1:end-3),'png']),init.(thephase{phasei}).device,fullfile(init.p2.thepath.inst,'stim_calibration_pupil_1024triostim1.bmp')); -end - -%% START SESSIONS -for numsession = 1:6-((phasei*2)+parti-3) - disp('Starting session'); - DrawFormattedText(init.(thephase{phasei}).expWin,'Laden...','center','center',[1 1 1]); - Screen('Flip',init.(thephase{phasei}).expWin); - cd (init.(thephase{phasei}).thepath.results); - exp_conton_phase123 - if parti == 2 && init.continuous == 1 - phasei = phasei+1; - elseif parti == 2 && init.continuous == 0 || phasei == 2 - break - end - parti = 2/parti; -end - -save(fullfile(init.(thephase{phasei}).thepath.results,fileX.fileName),'fileX'); -save(fullfile(init.(thephase{phasei}).thepath.results,[fileX.fileName(1:end-4),'_init.mat']),'init'); -RestrictKeysForKbCheck(27);%press escape to leave final screen -KbWait([], 2); -RestrictKeysForKbCheck([]); -ShowCursor; -sca \ No newline at end of file diff --git a/exp_conton_functions/LoadStimuli.m b/exp_conton_functions/LoadStimuli.m deleted file mode 100644 index a7f872a..0000000 --- a/exp_conton_functions/LoadStimuli.m +++ /dev/null @@ -1,18 +0,0 @@ -function [thescenepath,thescene,thescenepath_EL] = LoadStimuli(trial,thephase,phasei,thepart,parti,thecat,n,fileX,init) - -for pici = trial:trial-1+n.(thephase{phasei}).(thepart{parti}).t2b - if fileX.(thephase{phasei}).(thepart{parti})(pici,6)<10 - thescenepath{pici} = fullfile(init.(thephase{phasei}).thepath.(['pics_',thecat{fileX.(thephase{phasei}).(thepart{parti})(pici,2)}]),['00',num2str(fileX.(thephase{phasei}).(thepart{parti})(pici,6)),'_',thecat{fileX.(thephase{phasei}).(thepart{parti})(pici,2)},'.bmp']); - thescenepath_EL{pici} = fullfile(init.(thephase{phasei}).thepath.(['pics_',thecat{fileX.(thephase{phasei}).(thepart{parti})(pici,2)}]),'resizedForEyelinkTriostim',['00',num2str(fileX.(thephase{phasei}).(thepart{parti})(pici,6)),'_',thecat{fileX.(thephase{phasei}).(thepart{parti})(pici,2)},'.bmp']); - - elseif fileX.(thephase{phasei}).(thepart{parti})(pici,6)>9 && fileX.(thephase{phasei}).(thepart{parti})(pici,6)<100 - thescenepath{pici} = fullfile(init.(thephase{phasei}).thepath.(['pics_',thecat{fileX.(thephase{phasei}).(thepart{parti})(pici,2)}]),['0',num2str(fileX.(thephase{phasei}).(thepart{parti})(pici,6)),'_',thecat{fileX.(thephase{phasei}).(thepart{parti})(pici,2)},'.bmp']); - thescenepath_EL{pici} = fullfile(init.(thephase{phasei}).thepath.(['pics_',thecat{fileX.(thephase{phasei}).(thepart{parti})(pici,2)}]),'resizedForEyelinkTriostim',['0',num2str(fileX.(thephase{phasei}).(thepart{parti})(pici,6)),'_',thecat{fileX.(thephase{phasei}).(thepart{parti})(pici,2)},'.bmp']); - - elseif fileX.(thephase{phasei}).(thepart{parti})(pici,6)>99 - thescenepath{pici} = fullfile(init.(thephase{phasei}).thepath.(['pics_',thecat{fileX.(thephase{phasei}).(thepart{parti})(pici,2)}]),[num2str(fileX.(thephase{phasei}).(thepart{parti})(pici,6)),'_',thecat{fileX.(thephase{phasei}).(thepart{parti})(pici,2)},'.bmp']); - thescenepath_EL{pici} = fullfile(init.(thephase{phasei}).thepath.(['pics_',thecat{fileX.(thephase{phasei}).(thepart{parti})(pici,2)}]),'resizedForEyelinkTriostim',[num2str(fileX.(thephase{phasei}).(thepart{parti})(pici,6)),'_',thecat{fileX.(thephase{phasei}).(thepart{parti})(pici,2)},'.bmp']); - - end - thescene{pici} = uint8(imread(thescenepath{pici})); -end diff --git a/exp_conton_functions/StartEyelinkRecording.m b/exp_conton_functions/StartEyelinkRecording.m deleted file mode 100644 index 051f70b..0000000 --- a/exp_conton_functions/StartEyelinkRecording.m +++ /dev/null @@ -1,30 +0,0 @@ -function [tpre, tpost]=StartEyelinkRecording(thetrial,init,fileX,thescenepath,thephase,phasei,thepart,parti,t_fix,time)%change this if we only record during testing TBD - -Eyelink('Message', 'TRIALID: %04d, NEWOLD: %d, ENCRET: %d, FIXX: %04d, FIXY %04d', thetrial, fileX.p2.(thepart{parti})(thetrial,3), fileX.p2.(thepart{parti})(thetrial,4), init.(thephase{phasei}).mx, init.(thephase{phasei}).my); -% an integration message so that an image can be loaded as -% overlay background when performing Data Viewer analysis. -WaitSecs(0.01); - -Eyelink('Message', '!V IMGLOAD CENTER %s %d %d', fullfile('C:\Users\herweg\Documents\_Projekte\07_conton',char(regexp(thescenepath{thetrial},'\MR.+','match'))), init.(thephase{phasei}).mx, init.(thephase{phasei}).my); - -% This supplies the title at the bottom of the eyetracker display -Eyelink('Command', 'record_status_message "Stim: %02d"', thetrial); - -%Put the tracker offline and draw the stimuli. -Eyelink('Command', 'set_idle_mode'); -WaitSecs(0.01); - -%clear tracker display and draw box at center -Eyelink('Command', 'clear_screen %d', 0); - -%draw the image on the screen -Eyelink('ImageTransfer',thescenepath{thetrial},round(init.(thephase{phasei}).mx-init.(thephase{phasei}).imgsizepix(2)/2), round(init.(thephase{phasei}).my-init.(thephase{phasei}).imgsizepix(1)/2), round(init.(thephase{phasei}).imgsizepix(2)), round(init.(thephase{phasei}).imgsizepix(1)),round(init.(thephase{phasei}).mx-init.(thephase{phasei}).imgsizepix(2)/2), round(init.(thephase{phasei}).my-init.(thephase{phasei}).imgsizepix(1)/2),0); - -%start recording following mode transition and a short pause. -Eyelink('Command', 'set_idle_mode'); -WaitSecs(0.01); - -WaitSecs('UntilTime',t_fix+time.p2.fix-0.3); -tpre = GetSecs; -Eyelink('StartRecording'); -tpost = GetSecs; diff --git a/exp_conton_functions/StopEyelinkRecording.m b/exp_conton_functions/StopEyelinkRecording.m deleted file mode 100644 index 98a44fc..0000000 --- a/exp_conton_functions/StopEyelinkRecording.m +++ /dev/null @@ -1,11 +0,0 @@ -function [t]=StopEyelinkRecording -Eyelink('StopRecording'); -t = GetSecs; -%this is the end of the trial scope. -WaitSecs(0.01); -Eyelink('Message', 'TRIAL OK'); -WaitSecs(0.01); -Eyelink('Command', 'set_idle_mode'); -WaitSecs(0.01); -Eyelink('Command', 'clear_screen %d', 0); - diff --git a/exp_conton_functions/VASscale_mouse.m b/exp_conton_functions/VASscale_mouse.m deleted file mode 100644 index 2554c69..0000000 --- a/exp_conton_functions/VASscale_mouse.m +++ /dev/null @@ -1,65 +0,0 @@ -function rating = VASscale_mouse(init,mouse_input,keycond) -%Presents sliding scale with a slider that moves along the scale -%according to move_slider input (1 = move right, -1 = move left, 0 = stay) -%Returns slider_position_now, which is to be input as slider_position_old -% the next time sliding_scale is called. - -%prepare everything -scale_length_pix = 1001; %fun requires odd number of intervals -scale_middle = (scale_length_pix+1)/2; -switch keycond - case {'1','4'} - scale_low_label = 'Sicher Alt'; - scale_hi_label = 'Sicher Neu'; - case {'2','3'} - scale_low_label = 'Sicher Neu'; - scale_hi_label = 'Sicher Alt'; -end -low_label_width = RectWidth(Screen('TextBounds',init.p3.expWin,scale_low_label)); -theSlider = zeros(30,10); -theScale = ones(5,scale_length_pix); -theMidpoint = ones(10,3); -sliderTexture = Screen('MakeTexture', init.p3.expWin, theSlider); -scaleTexture = Screen('MakeTexture', init.p3.expWin, theScale); -midpointTexture = Screen('MakeTexture', init.p3.expWin, theMidpoint); -scaleRect = CenterRectOnPoint([1 1 size(theScale,2) size(theScale,1)],init.p3.mx,init.p3.my+init.p3.imgsizepix(1)/2+50); -midpointRect = CenterRectOnPoint([1 1 size(theMidpoint,2) size(theMidpoint,1)],init.p3.mx,init.p3.my+init.p3.imgsizepix(1)/2+50); - -%draw scale, question and labels -Screen('DrawText', init.p3.expWin, scale_hi_label, init.p3.mx + scale_length_pix/2, init.p3.my+init.p3.imgsizepix(1)/2+50 + 24, 1); -Screen('DrawText', init.p3.expWin, scale_low_label, init.p3.mx - scale_length_pix/2 - low_label_width, init.p3.my+init.p3.imgsizepix(1)/2+50 + 24, 1); -Screen('DrawTexture',init.p3.expWin,scaleTexture,[],scaleRect); -Screen('DrawTexture',init.p3.expWin,midpointTexture,[],midpointRect); - -if mouse_input - %restrict input to scale - if mouse_input < init.p3.mx - (scale_middle-1) - mouse_input = init.p3.mx - (scale_middle-1) ; - elseif mouse_input > init.p3.mx + (scale_middle-1) - mouse_input = init.p3.mx + (scale_middle-1); - end - - %get rating - switch keycond - case {'1','4'} - rating = (mouse_input-init.p3.mx)/(scale_middle-1); - case {'2','3'} - rating = (init.p3.mx-mouse_input)/(scale_middle-1); - end - - %draw rating slider - sliderRect = CenterRectOnPoint([1 1 size(theSlider,2) size(theSlider,1)],mouse_input,init.p3.my+init.p3.imgsizepix(1)/2+50); - Screen('DrawTexture',init.p3.expWin,sliderTexture,[],sliderRect); - - %present drawing - Screen('Flip', init.p3.expWin,[],1); - - clearSliderTexture = Screen('MakeTexture', init.p3.expWin, theSlider+0.5); - Screen('DrawTexture',init.p3.expWin,clearSliderTexture,[],sliderRect); -else - %present drawing - Screen('Flip', init.p3.expWin,[],1); - %invalid rating - rating = NaN; -end -end \ No newline at end of file diff --git a/exp_conton_functions/WaitPulse.m b/exp_conton_functions/WaitPulse.m deleted file mode 100644 index 34df8ef..0000000 --- a/exp_conton_functions/WaitPulse.m +++ /dev/null @@ -1,40 +0,0 @@ -function [secs]=WaitPulse(n,device) -% -% This function waits for the Nth upcoming pulse. If N=1, it will wait for -% the very next pulse to arrive. 1 MEANS NEXT PULSE. So if you wish to wait -% for 6 full dummy scans, you should use N = 7 to be sure that at least 6 -% full acquisitions are finished. -% -% The function avoids KbCheck, KbWait functions, but relies on the OS -% level event queues, which are much less likely to skip short events. A -% nice discussion on the topic can be found here: -% http://ftp.tuebingen.mpg.de/pub/pub_dahl/stmdev10_D/Matlab6/Toolboxes/Psychtoolbox/PsychDocumentation/KbQueue.html - -try %to relase running queue - KbQueueCheck(device);%this should throw an error if no queue is running - queuerunning = 1; - KbQueueRelease(device); -catch %notice no queue was running - queuerunning = 0; -end - -keys = zeros(1,256); -keys(1,KbName('5%')) = 1; - -KbQueueCreate(device,keys); -KbQueueStart(device); - -disp('Waiting for dummy pulses...'); -secs = nan(1,n); -pulse = 0; -while pulse < n - KbQueueFlush(device,3); - secs(pulse+1) = KbQueueWait(device); - pulse = pulse + 1; -end -disp('Received dummy pulses!'); -KbQueueRelease(device); - -if queuerunning == 1 - KbQueueCreate(device); -end diff --git a/exp_conton_functions/calcstimsize.m b/exp_conton_functions/calcstimsize.m deleted file mode 100644 index e38fcdc..0000000 --- a/exp_conton_functions/calcstimsize.m +++ /dev/null @@ -1,40 +0,0 @@ -function [pixelyx] = calcstimsize(init, thephase, phasei) - -desang = 16; -resolution = init.(thephase{phasei}).rect(1,3:4); - -switch init.(thephase{phasei}).hostname - case 'triostim1' - if resolution(1) ~= 1024 - warning('Resolution not as expected. Image size might deviate from requested visual angle') - end - vdist = 94.5; - screen_width = 38.2; - - case 'etpc' - - vdist = 50; - screen_width = 40.7; - - case 'isnf01faf2bafa4' - - vdist = 50; - switch init.(thephase{phasei}).whichmonitor - case 's' - screen_width = 31; - case 'l' - screen_width = 51.5; - case 'e' - screen_width = 40.7; - end - - otherwise - error('add behavioral lab') - -end - -stim_cm = tand(desang) * vdist; -pixelx = stim_cm /(screen_width/resolution(1)); -pixely = 300/500 * pixelx;%300/500 is the original size of the images in pixels -pixelyx = [pixely,pixelx]; - diff --git a/exp_conton_functions/calibratePupil.m b/exp_conton_functions/calibratePupil.m deleted file mode 100644 index 50efe71..0000000 --- a/exp_conton_functions/calibratePupil.m +++ /dev/null @@ -1,85 +0,0 @@ -function [ sequenceComp,targetMatX,targetMatY ] = calibratePupil(areaSize,sampGrid,win,nrep,initel,mx,my,inst,imgpath,device,imgpathdrawback) -%UNTITLED Summary of this function goes here -% areaSize should give the size of the area that should be covered as -% [x,y] -% sampGrid should be a matrix of ones(size(x,y)) with x*y = nsamples -% acquired -% init should be a structure with fields mx and my giving the midpoint of -% the screen in pixels - - -% Display the instruction -insttexture = Screen('MakeTexture',win,uint8(imread(inst))); -Screen('DrawTexture',win,insttexture); -Screen('Flip', win); -Screen('Close'); - -% Wait for a button press -KbWait(device,2); - -% an integration message so that an image can be loaded as -% overlay background when performing Data Viewer analysis. -WaitSecs(0.01); -Eyelink('Message', '!V IMGLOAD CENTER %s %d %d', imgpath,mx, my); - -% This supplies the title at the bottom of the eyetracker display -Eyelink('Command', 'record_status_message "Stim: %02d"', 0); - -%Put the tracker offline and draw the stimuli. -Eyelink('Command', 'set_idle_mode'); -WaitSecs(0.01); - -%clear tracker display and draw box at center -Eyelink('Command', 'clear_screen %d', 0); - -try %this might not work when in the wrong environment -%draw the image on the screen -Eyelink('ImageTransfer',imgpathdrawback,1, 1, mx*2, my*2,1,1,0); -catch -end - -%start recording following mode transition and a short pause. -Eyelink('Command', 'set_idle_mode'); -WaitSecs(0.01); - -Eyelink('StartRecording'); -WaitSecs(0.1); - -resolution = Screen('Resolution', win); -% Create a matrix with x and y coordinates of targets to be displayed -targetMatX = repmat(round(linspace(mx-areaSize(2)/2,mx+areaSize(2)/2,size(sampGrid,2))),size(sampGrid,1),1); -targetMatY = repmat(round(linspace(my-areaSize(1)/2,my+areaSize(1)/2,size(sampGrid,1))),size(sampGrid,2),1)'; - -targetImg = ones(resolution.height,resolution.width)/2; -for repi = 1:nrep - % Randomise targets - sequence = (1:size(targetMatX,1)*size(targetMatX,2))'; - sequence(:,2) = rand(1,size(sequence,1)); - sequence = sortrows(sequence,2); - sequenceComp(:,repi) = sequence(:,1); - for targeti = sequence(:,1)' - % Save an image with all targets for overlaying - rect(targeti,:) = EyelinkDrawCalTarget(initel, targetMatX(targeti), targetMatY(targeti)); - Eyelink('Message', 'Stim Onset'); - Eyelink('Message', 'SYNCTIME'); - circ = Ellipse((rect(targeti,3)-rect(targeti,1)+1)/2); - targetImg(rect(targeti,2):rect(targeti,4),rect(targeti,1):rect(targeti,3)) = circ; - WaitSecs(2); - end -end - -imwrite(targetImg,imgpath); - -StopEyelinkRecording; - -DrawFormattedText(win, 'Kalibrierung beendet.\n Es folgt eine kurze erste Messung, danach startet das Experiment.','center','center'); -Screen('Flip',win); -display('Start the localizer now. Press space when finished.'); - -RestrictKeysForKbCheck(KbName('space')); -KbWait(device, 2); -RestrictKeysForKbCheck([]); -Screen('Flip',win); - -end - diff --git a/exp_conton_functions/counterkeys.m b/exp_conton_functions/counterkeys.m deleted file mode 100644 index 11b5c47..0000000 --- a/exp_conton_functions/counterkeys.m +++ /dev/null @@ -1,78 +0,0 @@ -function key = counterkeys(init,fileX,thephase,phasei) - -switch init.(thephase{phasei}).hostname - case 'triostim1' - switch fileX.keycond - case '1' - key.in = KbName('3#');%left - key.out = KbName('1!');%right - key.old = KbName('3#'); - key.new = KbName('1!'); - case '2' - key.in = KbName('3#'); - key.out = KbName('1!'); - key.old = KbName('1!'); - key.new = KbName('3#'); - case '3' - key.in = KbName('1!'); - key.out = KbName('3#'); - key.old = KbName('1!'); - key.new = KbName('3#'); - case '4' - key.in = KbName('1!'); - key.out = KbName('2@'); - key.old = KbName('2@'); - key.new = KbName('1!'); - end - - case 'etpc' - error('add buttons for eye link lab') - - case 'isnf01faf2bafa4' - - switch fileX.keycond - case '1' - key.in = KbName('LeftArrow'); - key.out = KbName('DownArrow'); - key.old = KbName('LeftArrow'); - key.new = KbName('DownArrow'); - case '2' - key.in = KbName('LeftArrow'); - key.out = KbName('DownArrow'); - key.old = KbName('DownArrow'); - key.new = KbName('LeftArrow'); - case '3' - key.in = KbName('DownArrow'); - key.out = KbName('LeftArrow'); - key.old = KbName('DownArrow'); - key.new = KbName('LeftArrow'); - case '4' - key.in = KbName('DownArrow'); - key.out = KbName('LeftArrow'); - key.old = KbName('LeftArrow'); - key.new = KbName('DownArrow'); - end - otherwise - switch fileX.keycond - case '1' - key.in = KbName('LeftArrow'); - key.out = KbName('DownArrow'); - key.old = KbName('LeftArrow'); - key.new = KbName('DownArrow'); - case '2' - key.in = KbName('LeftArrow'); - key.out = KbName('DownArrow'); - key.old = KbName('DownArrow'); - key.new = KbName('LeftArrow'); - case '3' - key.in = KbName('DownArrow'); - key.out = KbName('LeftArrow'); - key.old = KbName('DownArrow'); - key.new = KbName('LeftArrow'); - case '4' - key.in = KbName('DownArrow'); - key.out = KbName('LeftArrow'); - key.old = KbName('LeftArrow'); - key.new = KbName('DownArrow'); - end -end \ No newline at end of file diff --git a/exp_conton_functions/exp_conton_phase123.m b/exp_conton_functions/exp_conton_phase123.m deleted file mode 100644 index 7af7ecc..0000000 --- a/exp_conton_functions/exp_conton_phase123.m +++ /dev/null @@ -1,331 +0,0 @@ -%Contextual Modulation of old/new effects% -%14-Feb-2016, n.herweg@uke.de - -%% Initialization -%Timestamp -fileX.timestamp.(thephase{phasei}).(thepart{parti}) = datestr(now,30); - -%Preallocation -thescene{n.(thephase{phasei}).(thepart{parti}).trials} = 0; -fileX.(thephase{phasei}).(thepart{parti})(n.(thephase{phasei}).(thepart{parti}).trials,19)=0; - -%Counterbalance keys -key = counterkeys(init,fileX,thephase,phasei); - -%Load images for first block -[thescenepath,thescene,thescenepath_EL] = LoadStimuli(1,thephase,phasei,thepart,parti,thecat,n,fileX,init); - -%Get text length to center text position -texttodraw{1,1} = 'Kurze Pause!'; - -for k = 1:size(texttodraw,1) - [newx, ~] = Screen('DrawText', init.(thephase{phasei}).expWin,texttodraw{k,1},init.(thephase{phasei}).mx, init.(thephase{phasei}).my, [0.5 0.5 0.5]); - texttodraw{k,2} = init.(thephase{phasei}).mx-(newx-init.(thephase{phasei}).mx)/2; - texttodraw{k,3} = init.(thephase{phasei}).my-60; -end -Screen('Close') - -clear Inst insttexture trial newx newy k - -%Create cover (needed due to incremental drawing of stimuli) -thecover = zeros(size(thescene{1}))+0.5; - -%% Instruction -for k = inst2load.(thephase{phasei}).(thepart{parti}) - insttexture = Screen('MakeTexture',init.(thephase{phasei}).expWin,uint8(imread(fullfile(init.(thephase{phasei}).thepath.inst,['keycond',fileX.keycond],['Folie', num2str(k), '.png'])))); - Screen('DrawTexture',init.(thephase{phasei}).expWin,insttexture); - Screen('Flip', init.(thephase{phasei}).expWin); - Screen('Close') - KbWait([], 2); - Screen('Flip', init.(thephase{phasei}).expWin); - clear insttexture -end - -%Display the target -if strcmp(thephase{phasei},'p1') - targstim = unique(fileX.(thephase{phasei}).(thepart{parti})(fileX.(thephase{phasei}).(thepart{parti})(:,3)==1,[2,6]),'rows'); - targtrial{1} = fileX.(thephase{phasei}).(thepart{parti})(fileX.(thephase{phasei}).(thepart{parti})(:,2) == targstim(1,1) & fileX.(thephase{phasei}).(thepart{parti})(:,6) == targstim(1,2),1); - targtrial{2} = fileX.(thephase{phasei}).(thepart{parti})(fileX.(thephase{phasei}).(thepart{parti})(:,2) == targstim(2,1) & fileX.(thephase{phasei}).(thepart{parti})(:,6) == targstim(2,2),1); - targtexture = Screen('MakeTexture',init.(thephase{phasei}).expWin,[thescene{targtrial{1}(1)},uint8(ones(300,20,3).*255/2),thescene{targtrial{2}(1)}]); - Screen('DrawTexture',init.(thephase{phasei}).expWin,targtexture); - DrawFormattedText(init.(thephase{phasei}).expWin,'Dies sind deine Zielbilder. Drücke die Leertaste, sobald du eines dieser Bilder siehst!','center',init.(thephase{phasei}).my+200,[1 1 1]); - t_targ = Screen('Flip', init.(thephase{phasei}).expWin); - Screen('Close') -else - t_targ = GetSecs-12; -end - -if phasei == 2 && parti == 2 && strcmp(init.p2.hostname,'triostim1') - %Wait for dummy scans - fileX.MRtiming.start.block1 = WaitPulse(init.mr.ndummy+1,init.(thephase{phasei}).device);%Waits for 6 dummys scans, the 7th is the first scan for analysis -end -if phasei ~= 3 - %Create Queue for button presses - KbQueueCreate(init.(thephase{phasei}).device);%uses the default device -end - -%Show fix cross -fixcross = Screen('MakeTexture',init.(thephase{phasei}).expWin,FixCr); -Screen('DrawTexture',init.(thephase{phasei}).expWin,fixcross); -t_fix = Screen('Flip', init.(thephase{phasei}).expWin,t_targ+12); -Screen('Close') - -clear targstim targtrial targettexture t_targ - -%% Start trial loop -for trial=1:n.(thephase{phasei}).(thepart{parti}).trials - - %Break - if (phasei==2 && rem(trial,n.(thephase{phasei}).test.tpb)==1 && trial>1) || (phasei ~= 2 && rem(trial,n.(thephase{phasei}).test.t2b)==1 && trial>1)%short break after every nth trial and after every block in p2 - - coverTexture = Screen('MakeTexture',init.(thephase{phasei}).expWin,thecover);%cover the fixation cross - Screen('DrawTexture',init.(thephase{phasei}).expWin,coverTexture); - - if rem(trial,n.(thephase{phasei}).test.t2b)==1 - KbQueueStop(init.(thephase{phasei}).device);%Stop and flush running cueue for communication in the break - KbQueueFlush(init.(thephase{phasei}).device); - Screen('DrawText', init.(thephase{phasei}).expWin, texttodraw{1,1},texttodraw{1,2},texttodraw{1,3}, [1 1 1]); - %Wait for last scans - if phasei == 2 && parti == 2 &&strcmp(init.p2.hostname,'triostim1') && rem(trial,n.(thephase{phasei}).test.tpr)==1 - fileX.MRtiming.end.(['block',num2str(floor(trial/n.(thephase{phasei}).test.tpr))]) = WaitPulse(init.mr.ndummy+1,init.(thephase{phasei}).device); - end - - fileX.(thephase{phasei}).(thepart{parti})(trial,11) = Screen('Flip', init.(thephase{phasei}).expWin, t_fix+time.(thephase{phasei}).fix-init.(thephase{phasei}).slack);%t_pause - else - fixcross = Screen('MakeTexture',init.(thephase{phasei}).expWin,FixCr); - Screen('DrawTexture',init.(thephase{phasei}).expWin,fixcross); - fileX.(thephase{phasei}).(thepart{parti})(trial,11) = Screen('Flip', init.(thephase{phasei}).expWin, t_fix+time.(thephase{phasei}).fix-init.(thephase{phasei}).slack);%t_pause - end - - Screen('Close') - clear t_fix %this has been saved during the end of the last trial - - if rem(trial,n.(thephase{phasei}).test.t2b)==1 - %Load images for next block (timing & memory issue) - [thescenepath,thescene,thescenepath_EL] = LoadStimuli(trial,thephase,phasei,thepart,parti,thecat,n,fileX,init); - - save(fullfile(init.(thephase{phasei}).thepath.results,fileX.fileName),'fileX'); - save(fullfile(init.(thephase{phasei}).thepath.results,[fileX.fileName(1:end-4),'_init.mat']),'init'); - - if phasei == 2 %do drift correction and if necessary repeat calibration after the break - status = Eyelink('DriftCorrStart', init.(thephase{phasei}).mx, init.(thephase{phasei}).my , 1, 1, 1);%open setup for new calibration on press of escape - - if status == 27 - init.el.recal = init.el.recal+1; - Eyelink('Message', 'TRIALID: %04d, NEWOLD: %d, ENCRET: %d, FIXX: %04d, FIXY %04d', 900+init.el.recal, 0, 0, init.(thephase{phasei}).mx,init.(thephase{phasei}).my); - WaitSecs(0.01); - [~, messageString] = Eyelink('CalMessage'); - Eyelink('Message','%s',messageString);% - WaitSecs(0.01); - Eyelink('Message', 'TRIAL OK'); - WaitSecs(0.01); - end - - display('Press ''c'' to continue.') - RestrictKeysForKbCheck(KbName('c')); - else - display('Press any key to continue.') - end - - KbWait(init.(thephase{phasei}).device); - - if phasei == 2 - RestrictKeysForKbCheck([]); - end - - time2flip = 0; - else - time2flip = 20; - end - if phasei == 2 && parti == 2 && strcmp(init.p2.hostname,'triostim1') && rem(trial,n.(thephase{phasei}).test.tpr)==1 - %Wait for dummy scans - fileX.MRtiming.start.(['block',num2str(1+floor(trial/n.(thephase{phasei}).test.tpr))]) = WaitPulse(init.mr.ndummy+1,init.(thephase{phasei}).device);%Waits for 6 dummys scans, the 7th is the first scan for analysis - end - - fixcross = Screen('MakeTexture',init.(thephase{phasei}).expWin,FixCr); - Screen('DrawTexture',init.(thephase{phasei}).expWin,fixcross); - t_fix = Screen('Flip', init.(thephase{phasei}).expWin,fileX.(thephase{phasei}).(thepart{parti})(trial,11)+time2flip-init.(thephase{phasei}).slack); - Screen('Close') - end - - %Instruction - if phasei == 2 && rem(trial,n.(thephase{phasei}).(thepart{parti}).tpb)==1 %if this is the first trial of a block in phase 2 show instruction for the next block - - insttexture = Screen('MakeTexture',init.(thephase{phasei}).expWin,uint8(imread(fullfile(init.(thephase{phasei}).thepath.inst,['keycond',fileX.keycond],['Folie',num2str((9+fileX.(thephase{phasei}).(thepart{parti})(trial,4))),'.png']))));%4 encret 1 = enc; 2 = ret - Screen('DrawTexture',init.(thephase{phasei}).expWin,insttexture); - fileX.(thephase{phasei}).(thepart{parti})(trial,12) = Screen('Flip', init.(thephase{phasei}).expWin, t_fix+time.(thephase{phasei}).fix-init.(thephase{phasei}).slack);%t_instr - Screen('Close') - - clear t_fix - - fixcross = Screen('MakeTexture',init.(thephase{phasei}).expWin,FixCr); - Screen('DrawTexture',init.(thephase{phasei}).expWin,fixcross); - t_fix = Screen('Flip', init.(thephase{phasei}).expWin,fileX.(thephase{phasei}).(thepart{parti})(trial,12)+3-init.(thephase{phasei}).slack); - Screen('Close') - end - - if phasei == 2 && parti == 2 - %Turn the eye tracker on prior to stimulus onset - [t_trackerOnPre, t_trackerOnPost] = StartEyelinkRecording(trial,init,fileX,thescenepath_EL,thephase,phasei,thepart,parti,t_fix,time); - end - - %Scene presentation - scenetexture = Screen('MakeTexture',init.(thephase{phasei}).expWin,imresize(thescene{trial},init.(thephase{phasei}).imgsizepix)); - Screen('DrawTexture',init.(thephase{phasei}).expWin,scenetexture); - [t_scene,sceneOnset] = Screen('Flip', init.(thephase{phasei}).expWin,t_fix+time.(thephase{phasei}).fix-init.(thephase{phasei}).slack,1);%show scene and keep it in the back buffer for presentation with analogue scale - if phasei == 2 && parti == 2 - Eyelink('Message', 'Stim Onset'); - Eyelink('Message', 'SYNCTIME'); - end - Screen('Close') - clear scenetexture t_fix - - %Collect input - if phasei ~= 3 - %start collecting input - KbQueueFlush(init.(thephase{phasei}).device); - KbQueueStart(init.(thephase{phasei}).device); - else - SetMouse(init.(thephase{phasei}).mx,init.(thephase{phasei}).my+250,init.(thephase{phasei}).screenNumber); - ShowCursor('Hand'); - - VASscale_mouse(init,0,fileX.keycond); - - while GetSecs1 - current_chain = RandSample(chains,[1 1]); - end - if tt~=tchain*p.psi.presentation.numtrials_chain - tt=tt+1; - % enter in break loop - if (tt~=1 && mod(tt,breakpoint)==1 && simulation_mode==0); - save(p.path.path_param,'p'); - ShowInstruction(4); - CalibrateEL; - end - cc(current_chain)=cc(current_chain)+1; - fprintf('Chain %4.2f , Chain trial %03d/%03d...',current_chain,cc(current_chain),p.psi.presentation.numtrials_chain) - - %Present trial here at stimulus intensity x and collect - %response - fprintf('x is now %4.2f \n',x(cc(current_chain),current_chain)) - test = x(cc(current_chain),current_chain) + csn_shift(current_chain) + csp_degree; - dummy = test; - test = mod(test,360); - % the reference is csp or csn - ref = csn_shift(current_chain) + csp_degree; - ref = mod(ref,360); - - % start Trial - fprintf('Starting Trial %03d/%03d.\n',tt,tchain*p.psi.presentation.numtrials_chain) - - [test_face, ref_face, signal,trialID] = Trial_YN(trialID,ref,test,p.stim.tFace,tt); - - fprintf('Rating.\n') - Screen('Textsize', p.ptb.w,p.text.fontsize); - %Rating Slider - % - message1 = 'Waren die Gesichter unterschiedlich oder gleich?\n'; - message2 = 'Bewegen Sie den "Zeiger" mit der rechten und linken Pfeiltaste\n und bestätigen Sie Ihre Einschätzung mit der oberen Pfeiltaste.'; - if ~simulation_mode - rect = [p.ptb.width*0.2 p.ptb.midpoint(2) p.ptb.width*0.6 100]; - [response_subj] = RatingSlider(rect,2,Shuffle(1:2,1),p.keys.increase,p.keys.decrease,p.keys.confirm,{ 'unterschiedlich' 'gleich'},message1,message2,0); - - % see if subject found the different pair of faces... - % buttonpress left (Yes) is response_subj=2, right alternative (No) outputs a 1. - % note that response=1 only means "yes", and not correct or anything - sdt = NaN; - if (response_subj == 2 && signal == 1) - response=1; - fprintf('...Hit. \n') - sdt=1; - elseif (response_subj==1 && signal == 1) - response=0; - fprintf('...Miss. \n') - sdt=3; - elseif (response_subj == 2 && signal==0) - response=1; - fprintf('...False Alarm. \n') - sdt=2; - elseif (response_subj == 1 && signal == 0) - response=0; - fprintf('...Correct Rejection. \n') - sdt=4; - else - fprintf('error in the answer algorithm! \n') - end - - else - true_a = 45; - true_s = 5; - true_g = 0.2; - true_l = 0.02; - response = ObserverResponseFunction(@PAL_CumulativeNormal,true_a,1/true_s,true_g,true_l,abs(x(cc(current_chain),current_chain))); - sdt = nan; - end - - % store everything in the Log - row = find(unique(x)==x(cc(current_chain),current_chain)); - p.psi.log.trial_counter(row,current_chain) = p.psi.log.trial_counter(row,current_chain) + 1; - p.psi.log.xrounded(row,p.psi.log.trial_counter(row,current_chain),current_chain) = response; - SetLog; - %iteration control - STOP = sum(cc >= p.psi.presentation.numtrials_chain) == tchain; - end - %final save of parameter-/logfile - save(p.path.path_param,'p'); -end - -%end of Experiment, shown to subject -ShowInstruction(2); -%Print summary of results to screen -% for chain=1:tchain -% fprintf('Chain %g: Estimated Threshold (alpha): %4.2f \n',chain,PM{chain}.threshold(end)); -% fprintf('Chain %g: Estimated Slope (beta): %4.2f \n',chain,PM{chain}.slope(end)); -% end -%get the eyelink file back to this computer -StopEyelink(p.path.edf); - -%close everything down -cleanup; -%move the folder to appropriate location -movefile(p.path.subject,p.path.finalsubject); -% subplot(2,1,1) -% errorbar(p.psi.presentation.uniquex,nanmean(p.psi.log.xrounded(:,:,1),2),nanstd(p.psi.log.xrounded(:,:,1),0,2),'b.','MarkerSize',20) -% title('CSP chain') -% subplot(2,1,2) -% errorbar(p.psi.presentation.uniquex,nanmean(p.psi.log.xrounded(:,:,2),2),nanstd(p.psi.log.xrounded(:,:,2),0,2),'r.','MarkerSize',20) -% title('CSN chain') - - function [test_face,ref_face,signal,trialID] = Trial_YN(trialID,ref_stim,test_stim,last_face_of_circle,tt) - Screen('Textsize', p.ptb.w,p.text.fixsize); - % computes the trial FACES, using the test/ref information input - % values (in Deg) - - trial = [ref_stim test_stim]/p.stim.delta; - % correct face number within circle - trial = mod(round(trial),last_face_of_circle)+1; - ref_face = trial(1); - test_face = trial(2); - [trial,idx]= Shuffle(trial); - fprintf('Faces: %d %d \n',trial(1),trial(2)); - %compute if trial had different faces or not - %if trial(1)=trial(2), they were the same and subject has to - %answer with 'no' (right option, is 1), else means correct hit - - if trial(1)==trial(2) - signal = 0; - else - signal = 1; - end - - - trial_deg = [ref_stim test_stim]; - isref = double(trial==ref_face) ; - delta_ref = MinimumAngleQuartile([trial_deg(idx(1)) trial_deg(idx(2))],ref); - delta_csp = MinimumAngleQuartile([trial_deg(idx(1)) trial_deg(idx(2))],csp_degree); % ... - abs_FGangle = [trial_deg(idx(1)) trial_deg(idx(2))]; - - trialID=trialID+1; - - %get fixation crosses and onsets from p parameter - - - %GetSecs so that the onsets can be defined - if fixjump ==1 - onsets = 0.25+GetSecs; %fix1 onset - onsets = [onsets onsets(end)+p.duration.fix+rand(1)*.25];%stim1 onset - onsets = [onsets onsets(end)+p.duration.crossmoves]; %fix jump - onsets = [onsets onsets(end)+p.duration.crossmoves]; %stim offset - fixdelta = p.duration.fix+rand(1)*.25; - onsets = [onsets onsets(end)+p.duration.isi-fixdelta]; %fix2 onset - onsets = [onsets onsets(end)+fixdelta]; %stim2 onset - onsets = [onsets onsets(end)+p.duration.crossmoves]; %fix jump - onsets = [onsets onsets(end)+p.duration.crossmoves]; %stim offset - else - onsets = 0.25+GetSecs;%fix1 onset - onsets = [onsets onsets(end)+p.duration.fix+rand(1)*.25];%stim1 onset - onsets = [onsets onsets(end)+p.duration.stim];%stim1 offset - fixdelta = p.duration.fix+rand(1)*.25; - onsets = [onsets onsets(end)+p.duration.isi-fixdelta];%fix2 onset - onsets = [onsets onsets(end)+fixdelta];%stim2 onset - onsets = [onsets onsets(end)+p.duration.stim];%stim2 offset - end - - if fixjump ==1 - fix_i = p.psi.presentation.fix_start(cc(current_chain),current_chain); - fix = round([p.ptb.CrossPosition_x p.ptb.CrossPosition_y(fix_i)]); - FixCross = [fix(1)-1,fix(2)-p.ptb.fc_size,fix(1)+1,fix(2)+p.ptb.fc_size;fix(1)-p.ptb.fc_size,fix(2)-1,fix(1)+p.ptb.fc_size,fix(2)+1]; - %fixation cross 1 - %FixCross = [fix(1,1)-1,fix(1,2)-p.ptb.fc_size,fix(1,1)+1,fix(1,2)+p.ptb.fc_size;fix(1,1)-p.ptb.fc_size,fix(1,2)-1,fix(1,1)+p.ptb.fc_size,fix(1,2)+1]; - Screen('FillRect', p.ptb.w, [255,255,255], FixCross'); - Eyelink('Message', 'FX Onset at %d %d',fix(1),fix(2)); - Screen('Flip',p.ptb.w,onsets(1),0); - StartEyelinkRecording(trialID,phase,cc(current_chain),tt,current_chain,isref(1),trial(1),delta_ref(1),delta_csp(1),abs_FGangle(1),fix(1,1),fix(1,2)); - %face trial(1) - Screen('DrawTexture',p.ptb.w,p.ptb.stim_sprites(trial(1))); - Screen('FillRect', p.ptb.w, [255,255,255], FixCross'); - Screen('Flip',p.ptb.w,onsets(2),0); - Eyelink('Message', 'Stim Onset'); - Eyelink('Message', 'SYNCTIME'); - %fixJUMP trial(1) - fix = [p.ptb.CrossPosition_x p.ptb.CrossPosition_y(setdiff(1:2,fix_i))];%take the other position - FixCross = [fix(1)-1,fix(2)-p.ptb.fc_size,fix(1)+1,fix(2)+p.ptb.fc_size;fix(1)-p.ptb.fc_size,fix(2)-1,fix(1)+p.ptb.fc_size,fix(2)+1]; - %FixCross = [fix(2,1)-1,fix(2,2)-p.ptb.fc_size,fix(2,1)+1,fix(2,2)+p.ptb.fc_size; fix(2,1)-p.ptb.fc_size,fix(2,2)-1,fix(2,1)+p.ptb.fc_size,fix(2,2)+1]; - Screen('DrawTexture',p.ptb.w,p.ptb.stim_sprites(trial(1))); - Screen('FillRect', p.ptb.w, [255,255,255], FixCross'); - Screen('Flip',p.ptb.w,onsets(3),0); - while GetSecscross2onset->onset2shock->shock2offset - %these (duration.BLA) are average duration values: -% 1.5 0.5 0.5 - p.duration.stim = 1.5;%s - p.duration.fix = .7; - p.duration.crossmoves = p.duration.stim./2; - p.duration.isi = 1.0; - if simulation_mode - p.duration.stim = .001;%s - p.duration.crossmoves = .001; - p.duration.fix = .001; - p.duration.isi = 0.001; - %p.duration.gray = .001; - end - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - %create the randomized design - p.stim.cs_plus = csp_degree;%index of cs stimulus, this is the one paired to shock - %p.stim.cs_neg = csn; - - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %Set up Constant Stimuli procedure - csn_shift = [0 180]; - tchain = 2; - interval = 22.5; - maxdegree = 180; - maxtrials = 100; - addzeros = 18; - - tsteps = (2*maxdegree./interval)+1; - if maxdegree == 180 - tsteps = tsteps - 2;%spares out the CSN - end - rep = floor(maxtrials./(tsteps+1));%+1 so that zero can be doubled... - steps = [repmat(0:interval:180-interval,1,rep) repmat(0:interval:180-interval,1,rep)*-1 zeros(1,addzeros)]; - steps(steps== 157.5) = 11.25; - steps(steps== -157.5) = -11.25; - - for n = 1:tchain - x(:,n) = Shuffle(steps); - %fix_start(:,n) = seq_BalancedDist(x(:,n)',[1 2])'; - fix_start(:,n) = ones(length(x(:,n)),1); - end - - fprintf('This is the distribution of stimuli we will use:\n') - histi = histc(x,unique(x)); - uniquex = unique(x); - for l = 1:length(unique(x)) - fprintf('Level %g: %02d repetitions. \n',uniquex(l,1),histi(l,1)) - end - fprintf('---------------------------\nTotal trials: %03d per chain.\n',sum(histi(:,1))) - WaitSecs(3); - %store everything in p - p.psi.presentation.x = x; - p.psi.presentation.interval = interval; - p.psi.presentation.numtrials_chain = length(x(:,1)); - p.psi.presentation.tsteps = tsteps; - p.psi.presentation.rep = histi(:,1); - p.psi.presentation.uniquex = unique(x); - p.psi.presentation.fix_start = fix_start; - p.var.current_bg = p.stim.bg;%current background to be used. - %Save the stuff - save(p.path.path_param,'p'); - % - - end - function [rating]=RatingSlider(rect,tSection,position,up,down,confirm,labels,message1,message2,numbersOn) - % - %Detect the bounding boxes of the labels. - for nlab = 1:2 - [nx, ny, bb(nlab,:)]=DrawFormattedText(p.ptb.w,labels{nlab}, 'center', 'center', p.stim.white,[],[],[],2); - Screen('FillRect',p.ptb.w,p.stim.bg); - end - bb = max(bb); - bb_size = bb(3)-bb(1);%vertical size of the bb. - % - DrawSkala; - ok = 1; - while ok == 1 - [secs, keyCode, deltaSecs] = KbStrokeWait; - - keyCode = find(keyCode); - if (keyCode == up) | (keyCode == down) - next = position + increment(keyCode); - if next < (tSection+1) & next > 0 - position = position + increment(keyCode); - rating = tSection - position + 1; - end - DrawSkala; - elseif keyCode == confirm - WaitSecs(0.1); - ok = 0; - Screen('FillRect',p.ptb.w,p.stim.bg); - Screen('Flip',p.ptb.w); - end - end - - function DrawSkala - rating = tSection - position + 1; - increment([up down]) = [1 -1];%delta - tick_x = linspace(rect(1),rect(1)+rect(3),tSection+1);%tick positions - tick_size = rect(3)./tSection; - ss = tick_size/5*0.9;%slider size. - % - for tick = 1:length(tick_x)%draw ticks - Screen('DrawLine', p.ptb.w, [255 0 0], tick_x(tick), rect(2), tick_x(tick), rect(2)+rect(4) , 3); - if tick <= tSection && numbersOn - Screen('TextSize', p.ptb.w,p.text.fontsize./2); - DrawFormattedText(p.ptb.w, mat2str(tick) , tick_x(tick)+ss/2, rect(2)+rect(4), p.stim.white); - Screen('TextSize', p.ptb.w,p.text.fontsize); - end - if tick == 1 - DrawFormattedText(p.ptb.w, labels{1},tick_x(tick)-bb_size*1.6,rect(2), p.stim.white); - elseif tick == tSection+1 - DrawFormattedText(p.ptb.w, labels{2},tick_x(tick)+bb_size*0.2,rect(2), p.stim.white); - end - end - %slider coordinates - slider = [ tick_x(position)+tick_size*0.1 rect(2) tick_x(position)+tick_size*0.9 rect(2)+rect(4)]; - %draw the slider - Screen('FillRect',p.ptb.w, p.stim.white, round(slider)); - Screen('TextSize', p.ptb.w,p.text.fontsize); - DrawFormattedText(p.ptb.w,message1, 'center', p.ptb.midpoint(2)*0.2, p.stim.white,[],[],[],2); - Screen('TextSize', p.ptb.w,p.text.fontsize./2); - DrawFormattedText(p.ptb.w,message2, 'center', p.ptb.midpoint(2)*0.4, p.stim.white,[],[],[],2); - Screen('TextSize', p.ptb.w,p.text.fontsize); - Screen('Flip',p.ptb.w); - end - end - - function [shuffled,idx] = Shuffle(vector,N) - %takes first N from the SHUFFLED before outputting. This function - %could be used as a replacement for randsample - if nargin < 2;N = length(vector);end - [dummy, idx] = sort(rand([1 length(vector)])); - shuffled = vector(idx(1:N)); - shuffled = shuffled(:); - end - - function [a]=MinimumAngleQuartile(y,x) - %[a]=MinimumAngle(x,y); - % - %finds the minimum angle between two angles given in degrees, the answer is - %also in degrees. The clockwise distances from Y to X are considered as - %positive. Opposite angles are considered as positive 180. - - x = deg2rad(x); - y = deg2rad(y); - - a = atan2(sin(x-y), cos(x-y)); - - a = -round(((180/pi)*a)*4)/4; - - if any(abs(a) == 180); - a(abs(a) == 180) = 180; - end - end - - function ShowInstruction(nInstruct) - - [text]=GetText(nInstruct); - ShowText(text); - %let subject read it and ask confirmation to proceed. - if nInstruct ~= 2 - KbStrokeWait; - else - WaitSecs(2) - end - Screen('FillRect',p.ptb.w,p.stim.bg); - Screen('Flip',p.ptb.w); - - end - function ShowText(text) - - - Screen('FillRect',p.ptb.w,p.stim.bg); - %DrawFormattedText(p.ptb.w, text, p.text.start_x, 'center',p.stim.white,[],[],[],2,[]); - DrawFormattedText(p.ptb.w, text, 'center', 'center',p.stim.white,[],[],[],2,[]); - Screen('Flip',p.ptb.w); - - %show the messages at the experimenter screen - fprintf([repmat('=',1,50) '\n']); - fprintf('Subject''s monitor:\n'); - fprintf(text); - fprintf([repmat('=',1,50) '\n']); - - end - - - function [text]=GetText(nInstruct) - - if nInstruct == 0%Eyetracking calibration - - text = ['Um Ihre Augenbewegungen zu messen, \n' ... - 'müssen wir jetzt den Eye-Tracker kalibrieren.\n' ... - 'Dazu zeigen wir Ihnen einige Punkte auf dem Bildschirm, \n' ... - 'bei denen Sie sich wie folgt verhalten:\n' ... - 'Bitte fixieren Sie den Fixationspunkt und \n' ... - 'bleiben Sie so lange darauf, wie er zu sehen ist.\n' ... - 'Bitte drücken Sie jetzt den oberen Knopf, \n' ... - 'um mit der Kalibrierung weiterzumachen.\n' ... - ]; - - elseif nInstruct == 1 - text = ['In diesem Experiment sehen Sie nacheinander jeweils zwei Gesichter.\n'... - '\n'... - 'Danach werden Sie gefragt, ob die Gesichter unterschiedlich oder gleich waren.\n'... - '\n'... - 'Benutzen Sie zum Antworten die Pfeiltasten (links, rechts) und die obere Taste zum Bestätigen.\n'... - '\n'... - 'Sie erhalten in diesem Teil keine Schocks.\n'... - 'Folgen Sie aber bitte auch hier streng den Fixationskreuzen!\n'... - '\n'... - 'Sie werden alle ' num2str(breakpoint) ' Durchgänge eine Pause machen können,\nnach der der Eyetracker neu kalibriert wird.\n'... - 'Das heißt, Sie können in der Pause den Kopf ruhig aus der Kopfstütze nehmen und sich entspannen. \n'... - '\n'... - 'Wenn Sie noch Fragen haben, können Sie jetzt die Versuchsleiterin fragen.\n'... - 'Wir können Sie jederzeit hören.\n'... - '\n'... - 'Drücken Sie ansonsten die obere Taste,\n'... - ' um das Experiment zu starten.\n' ... - ]; - elseif nInstruct == 3 - text = ['Der Eyetracker ist nun kalibiert.\n'... - '\n'... - 'Bitte verändern Sie Ihre Kopfposition nun nicht mehr.\n'... - '\n'... - 'Zur Erinnerung: Im Experiment sehen Sie jeweils zwei Gesichter und geben anschließend an,\n'... - '\n'... - 'ob die Gesichter gleich oder unterschiedlich waren.\n'... - '\n'... - 'Benutzen Sie dazu die Pfeiltasten (links, rechts) und die obere Taste zum Bestätigen.\n'... - '\n'... - 'Zusätzlich folgen Sie auch hier immer den Fixationskreuzen.\n'... - '\n'... - 'Drücken Sie nun die obere Taste,\n'... - ' um das Experiment zu starten!\n' ... - ]; - elseif nInstruct == 2%end - text = 'Experiment beendet!\n'; - elseif nInstruct==4%break - text = [sprintf('Sie haben bereits %g von %g Durchgängen geschafft!\n',tt-1,p.psi.presentation.numtrials_chain*tchain)... - 'Machen Sie eine kurze Pause, lehnen Sie sich gern einen Moment zurück\n'... - 'und schließen Sie die Augen, um diese zu entspannen.\n'... - 'Drücken Sie anschließend die mittlere Taste, um weiterzumachen.\n']; - end - end - - function SetupLog - - p.psi.log.globaltrial= NaN(tchain,length(x)); - p.psi.log.signal = NaN(tchain,length(x)); - p.psi.log.x = NaN(tchain,length(x)); - p.psi.log.refface = NaN(tchain,length(x)); - p.psi.log.testface = NaN(tchain,length(x)); - p.psi.log.response = NaN(tchain,length(x)); -% p.psi.log.xrounded = NaN(p.stim.tFace/tchain+1,p.psi.presentation.numtrials_chain,tchain); - p.psi.log.xrounded = NaN(length(unique(x)),max(p.psi.presentation.rep),tchain); - p.psi.log.sdt = NaN(tchain,length(x)); - p.psi.log.trial_counter = zeros(length(unique(x)),tchain); - end - - function SetLog - - p.psi.log.globaltrial(current_chain,cc(current_chain))= tt; - p.psi.log.signal(current_chain,cc(current_chain)) = signal; - p.psi.log.x(current_chain,cc(current_chain)) = x(cc(current_chain),current_chain); - p.psi.log.refface(current_chain,cc(current_chain)) = ref_face; - p.psi.log.testface(current_chain,cc(current_chain)) = test_face; - p.psi.log.response(current_chain,cc(current_chain)) = response; - p.psi.log.sdt(current_chain,cc(current_chain)) = sdt;%1=hit 2=FA 3=miss 4=CR - - - end -% function PlotProcedure -% plotproc=figure(1); -% % title(sprintf('Threshold Estimation for subject %02d',tchain),'FontSize',14) -% for sub=1:tchain; -% subplot(2,2,sub) -% t = 1:length(p.log.x(sub)); -% hold on; -% plot(t,abs(p.log.x(sub)),'bo-'); -% errorbar(t,p.log.alpha(sub),p.log.seAlpha(sub),'r--') -% plot(t(p.log.response(sub) == 1),p.log.x(sub)(p.log.response(sub) == 1),'ko', ... -% 'MarkerFaceColor','k'); -% plot(t(p.log.response(sub) == 0),p.log.x(sub)(p.log.response(sub) == 0),'ko', ... -% 'MarkerFaceColor','w'); -% -% set(gca,'FontSize',12); -% axis([0 max(t)+1 0 max(p.log{sub}.alpha)+max(p.log{sub}.seAlpha)+20]) -% xlabel('Trial'); -% ylabel('xCurrent (Deg)'); -% -% end -% annotation('textbox', [0 0.9 1 0.1], 'String',... -% (sprintf('Threshold Estimation for subject %02d',tchain)), ... -% 'EdgeColor', 'none', ... -% 'HorizontalAlignment', 'center','FontSize',14) -% legend('xCurrent','estimated Threshold','Response = 1','Response = 0','Location','northeast'); -% -% % end -% function Plot_Fit -% plotfit=figure(2); -% for sub=1:tchain; -% subplot(2,2,sub) -% t = 1:length(p.log{sub}.x); -% hold on; -% plot(t,abs(p.log{sub}.x),'bo-'); -% errorbar(t,p.log{1}.alpha,p.log{1}.seAlpha,'r--') -% plot(t(p.log{sub}.response == 1),p.log{sub}.x(p.log{sub}.response == 1),'ko', ... -% 'MarkerFaceColor','k'); -% plot(t(p.log{sub}.response == 0),p.log{sub}.x(p.log{sub}.response == 0),'ko', ... -% 'MarkerFaceColor','w'); -% -% set(gca,'FontSize',12); -% axis([0 max(t)+1 0 max(p.log{sub}.alpha)+max(p.log{sub}.seAlpha)+20]) -% xlabel('Trial'); -% ylabel('xCurrent (Deg)'); -% -% end - -function [t]=StartEyelinkRecording(trialID,phase,cc,tt,current_chain,isref,file,delta_ref,delta_csp,abs_FGangle,fixx,fixy) - - t = []; - - - Eyelink('Message', 'TRIALID:%04d, PHASE:%04d, CHAIN:%04d, CHAINTRIAL:%04d, TTRIAL:%04d, ISREF:%04d, FILE:%04d, DELTAREF:%04d, DELTACSP:%04d, FGDEG:%04d, FXX:%04d, FXY:%04d',trialID, phase,... - current_chain, cc, tt, isref, file, delta_ref*100, delta_csp*100, abs_FGangle*100,fixx,fixy); - % an integration message so that an image can be loaded as - % overlay background when performing Data Viewer analysis. - WaitSecs(0.01); - Eyelink('Message', '!V IMGLOAD CENTER %s %d %d', p.stim.files(file,:), p.ptb.midpoint(1), p.ptb.midpoint(2)); - % This supplies the title at the bottom of the eyetracker display - Eyelink('Command', 'record_status_message "Stim: %d, Phase: %d"',file, phase); - % - %Put the tracker offline and draw the stimuli. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - % clear tracker display and draw box at center - Eyelink('Command', 'clear_screen %d', 0); - %draw the image on the screen - Eyelink('ImageTransfer',p.stim.files24(file,:),p.ptb.imrect(1),p.ptb.imrect(2),p.ptb.imrect(3),p.ptb.imrect(4),p.ptb.imrect(1),p.ptb.imrect(2)); - Eyelink('Command', 'draw_cross %d %d %d',p.ptb.midpoint(1),p.ptb.CrossPositionET_y(1),p.ptb.fc_size); - Eyelink('Command', 'draw_cross %d %d %d',p.ptb.midpoint(1),p.ptb.CrossPositionET_y(2),p.ptb.fc_size); - % - %drift correction - %EyelinkDoDriftCorrection(el,crosspositionx,crosspositiony,0,0); - %start recording following mode transition and a short pause. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('StartRecording'); - - t = GetSecs; - Log(t,8,NaN); -end - -function [t] = StopEyelinkRecording - - Eyelink('Message', 'Stim Offset'); - Eyelink('Message', 'BLANK_SCREEN'); - Eyelink('StopRecording'); - t = GetSecs; - %this is the end of the trial scope. - WaitSecs(0.01); - Eyelink('Message', 'TRIAL_RESULT 0'); - % - WaitSecs(0.01); - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('Command', 'clear_screen %d', 0); - - Log(t,-8,NaN); -end - -function InitEyeLink - % - if EyelinkInit(0)%use 0 to init normaly - fprintf('=================\nEyelink initialized correctly...\n') - else - fprintf('=================\nThere is problem in Eyelink initialization\n') - keyboard; - end - % - WaitSecs(0.5); - [~, vs] = Eyelink('GetTrackerVersion'); - fprintf('=================\nRunning experiment on a ''%s'' tracker.\n', vs ); - - %load 24bits pictures for eyelink... - dummy = dir([p.path.stim24 '*.bmp']); - p.stim.files24 = [repmat([fileparts(p.path.stim24) filesep],length(dummy),1) vertcat(dummy(:).name)]; -% for i=1:32 -% filename = p.stim.files24(nStim,:); -% [im , ~, ~] = imread(filename); -% end -% - % - el = EyelinkInitDefaults(p.ptb.w); - %update the defaults of the eyelink tracker - el.backgroundcolour = p.stim.bg; - el.msgfontcolour = WhiteIndex(el.window); - el.imgtitlecolour = WhiteIndex(el.window); - el.targetbeep = 0; - el.calibrationtargetcolour = WhiteIndex(el.window); - el.calibrationtargetsize = 1.5; - el.calibrationtargetwidth = 0.5; - el.displayCalResults = 1; - el.eyeimgsize = 50; - el.waitformodereadytime = 25;%ms - el.msgfont = 'Times New Roman'; - el.cal_target_beep = [0 0 0];%[1250 0.6 0.05]; - %shut all sounds off - el.drift_correction_target_beep = [0 0 0]; - el.calibration_failed_beep = [0 0 0]; - el.calibration_success_beep = [0 0 0]; - el.drift_correction_failed_beep = [0 0 0]; - el.drift_correction_success_beep= [0 0 0]; - EyelinkUpdateDefaults(el); - %PsychEyelinkDispatchCallback(el) - - % open file. - res = Eyelink('Openfile', p.path.edf); - if res == -3 - fprintf('File cannot be created!!!!\n'); - return; - end - % - Eyelink('command', 'add_file_preamble_text ''Recorded by EyelinkToolbox FearCloud Experiment'''); - Eyelink('command', 'screen_pixel_coords = %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - Eyelink('message', 'DISPLAY_COORDS %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - % set calibration type. - Eyelink('command', 'calibration_type = HV5'); - Eyelink('command','auto_calibration_messages = YES'); - Eyelink('command', 'select_parser_configuration = 1'); - %what do we want to record - Eyelink('command', 'file_sample_data = LEFT,RIGHT,GAZE,HREF,AREA,GAZERES,STATUS,INPUT,HTARGET'); - Eyelink('command', 'file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON,INPUT'); - Eyelink('command', 'use_ellipse_fitter = no'); - % set sample rate in camera setup screen - Eyelink('command', 'sample_rate = %d',1000); - end -function StopEyelink(filename) - try - fprintf('Trying to stop the Eyelink system with StopEyelink\n'); - Eyelink('StopRecording'); - WaitSecs(0.5); - Eyelink('Closefile'); - display('receiving the EDF file...'); - Eyelink('ReceiveFile',filename,[p.path.subject '\eye\'],1); - display('...finished!') - % Shutdown Eyelink: - Eyelink('Shutdown'); - catch - display('StopEyeLink routine didn''t really run well'); - end - end -function CalibrateEL - fprintf('=================\n=================\nEntering Eyelink Calibration\n') - p.var.ExpPhase = 0; - ShowInstruction(0); - EyelinkDoTrackerSetup(el); - %Returns 'messageString' text associated with result of last calibration - [~, messageString] = Eyelink('CalMessage'); - Eyelink('Message','%s',messageString);% - WaitSecs(0.05); - fprintf('=================\n=================\nNow we are done with the calibration\n') -end - - - -function Log(ptb_time, event_type, event_info) - %Phases: - %Pre-Experiment : 1 - %Post-Experiment : 2 -% %Instruction : 1 -% %Baseline : 2 -% %Conditioning : 3 -% %Test : 4 -% %Rating : 5 -% %Calibration : 0 - % - %event types are as follows: - % - %Scan Detection : 0 info: NaN; - %Cross Onset : 1 info: position - %Stimulus Onset/Offset: 2/-2 info: stim_id - %Cross Movement : 3 info: NaN; - %Stimulus Offset : -2 info: NaN; - %UCS Delivery : 4 info: NaN; - %Key Presses : 7 info: NaN; - %Tracker Onset/Offset : 8 info: NaN; - % - %Text on the screen : 5 info: Which Text? - %RatingScreen Onset : 6 info: NaN; - - p.var.event_count = p.var.event_count + 1; - p.out.log(p.var.event_count,:) = [ptb_time event_type event_info phase]; - % % p_out_log(p.out.event_counter,:) - %logstring([ 'Logged: ' mat2str(p_out_log(p.out.event_counter,:)) ' - Type: ' p.verbose.eventtype{abs(event_type)} ' - Phase: ' p.verbose.eventphase{CurrentExperimentalPhase}]) - %for i = 1:3;subplot(3,1,i);plot(p_out_log(1:p.out.event_counter ,i),'o-');drawnow;end - % - - end -function cleanup - - % Close window: - sca; - %set back the old resolution - if strcmp(p.hostname,'triostim1') - Screen('Resolution',p.ptb.screenNumber, p.ptb.oldres.width, p.ptb.oldres.height ); - %show the cursor - ShowCursor(p.ptb.screenNumber); - end - % -% %IOPort('ConfigureSerialPort', p.com.serial,' StopBackgroundRead'); -% %IOPort('Close',p.com.serial); -% commandwindow; -% ListenChar(0); -% KbQueueRelease(p_ptb_device); -end - -end diff --git a/exp_fearcloud_stereotype.m b/exp_fearcloud_stereotype.m deleted file mode 100644 index 17e842d..0000000 --- a/exp_fearcloud_stereotype.m +++ /dev/null @@ -1,1134 +0,0 @@ -function [p]=exp_fearcloud_stereotype(subject,counterbal) - -% -% Used for 'revision' (SO LK) of fearcloud_eyelab (MSc LK), based on the FearAmy code. -% Not scannerproof, minimal logging. -% - -debug = 1;%debug mode -%set some formerly needed inputs to an arbitrary value, so we don't have to -%change it all in SetParams -phase = 1; -csp = 1; - -%replace parallel port function with a dummy function -if ismac -% outp = @(x,y) fprintf('[%i %i]\n',x,y); -end -if nargin ~= 2 - fprintf('Wrong number of inputs\n'); - keyboard; -end - -csn = mod( csp + 8/2-1, 8)+1; -commandwindow; -%clear everything -clear mex global functions -if ~ismac - cgshut; - global cogent; -end -%%%%%%%%%%%load the GETSECS mex files so call them at least once -GetSecs; -WaitSecs(0.001); -% -el = []; -p = []; -SetParams; -SetPTB; -% -%init all the variables -t = []; -nTrial = 0; -%% -%Time Storage -TimeEndStim = []; -TimeStartShock = []; -TimeTrackerOff = []; -TimeCrossOn = []; -p.var.event_count = 0; -%% -% InitEyeLink; -WaitSecs(2); -KbQueueStop(p.ptb.device); -KbQueueRelease(p.ptb.device); -%save again the parameter file -save(p.path.path_param,'p'); -if phase == 1 - % - p.var.ExpPhase = phase;%set this after the calibration; - ShowInstruction(0,1) - order = [3 1 4 2 3 1 4 2; 3 2 4 1 3 2 4 1]; - for cond = order(counterbal,:) - AskDetectionSelectable(cond); - end - ShowInstruction(14,0,10); - -end - -%get the eyelink file back to this computer -% StopEyelink(p.path.edf); -%trim the log file and save -p.out.log = p.out.log(sum(isnan(p.out.log),2) ~= size(p.out.log,2),:); -%shift the time so that the first timestamp is equal to zero -p.out.log(:,1) = p.out.log(:,1) - p.out.log(1); -p.out.log = p.out.log;%copy it to the output variable. -save(p.path.path_param,'p'); -% -%move the file to its final location. -movefile(p.path.subject,p.path.finalsubject); -%close everything down -cleanup; - - function AskDetectionSelectable(cond) - %asks subjects to select the face that was associated with a shocks - positions = circshift(1:8,[1 PsychRandSample(1:8,[1 1])]);%position of the marker - p.var.ExpPhase = 4; - ShowInstruction(cond,1); - %% - increment([p.keys.increase p.keys.decrease]) = [1 -1];%key to increment mapping - %% - ok = 1; - ii = Shuffle(1:8); - p.stim.circle_file_id = p.stim.circle_file_id(ii); - p.stim.circle_order = p.stim.circle_order(ii); - while ok - DrawCircle; - Screen('FrameOval', p.ptb.w, [1 1 0], p.stim.circle_rect(positions(1),:), 2);%draw the marker circle somewhere random initially. - Screen('Flip',p.ptb.w); - [~, keyCode, ~] = KbStrokeWait(p.ptb.device);%observe key presses - keyCode = find(keyCode); - if length(keyCode) == 1%this loop avoids crashes to accidential presses of meta keys - if (keyCode == p.keys.increase) || (keyCode == p.keys.decrease) - positions = circshift(positions,[0 increment(keyCode)]); - elseif keyCode == p.keys.confirm - WaitSecs(0.1); - ok = 0; - end - end - end - %% - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.imrect ); - Screen('Flip',p.ptb.w); - p.out.selectedface = [p.out.selectedface p.stim.circle_order(positions(1))]; - p.out.cond = [p.out.cond cond]; - fprintf('Subject chose face... %g \n',p.out.selectedface(end)); - end - function DrawCircle - for npos = 1:p.stim.tFace - Screen('DrawTexture', p.ptb.w, p.ptb.stim_sprites_cut(p.stim.circle_file_id(npos)),[],p.stim.circle_rect(npos,:)); - Screen('DrawText', p.ptb.w, sprintf('%i_%i_%i',p.stim.circle_order(npos),p.stim.circle_file_id(npos),npos),mean(p.stim.circle_rect(npos,[1 3])) ,mean(p.stim.circle_rect(npos,[2 4]))); - end - end - - function [myrect]=angle2rect(A) - radius = 430; - factor = 3.1;%1.9;%factor resize the images - [x y] = pol2cart(A./180*pi,radius);%randomly shift the circle - left = x+p.ptb.midpoint(1)-p.stim.width/2/factor; - top = y+p.ptb.midpoint(2)-p.stim.height/2/factor; - right = left+p.stim.width/factor; - bottom = top+p.stim.height/factor; - myrect = [left top right bottom]; - end - - function AskDetection - % - p.var.ExpPhase = 3; - ShowInstruction(801,1); - %% show a fixation cross - fix = [p.ptb.CrossPosition_x p.ptb.CrossPosition_y(1)];%show the fixation cross at the lip position to ease the subsequent drift correction. - FixCross = [fix(1)-1,fix(2)-p.ptb.fc_size,fix(1)+1,fix(2)+p.ptb.fc_size;fix(1)-p.ptb.fc_size,fix(2)-1,fix(1)+p.ptb.fc_size,fix(2)+1]; - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.imrect ); %always create a gray background - Screen('FillRect', p.ptb.w, [255,255,255], FixCross');%draw the prestimus cross atop - - Screen('DrawingFinished',p.ptb.w,0); - Screen('Flip',p.ptb.w); - StartEyelinkRecording(1,0,p.var.ExpPhase,0,0,0,fix,0); - WaitSecs(1.5); - %% - DrawCircle; - %Stimulus onset - Screen('Flip',p.ptb.w); - Eyelink('Message', 'Stim Onset'); - Eyelink('Message', 'SYNCTIME'); - %% - WaitSecs(30); - Screen('Flip',p.ptb.w); - Eyelink('Message', 'Stim Offset'); - Eyelink('Message', 'BLANK_SCREEN'); - StopEyelinkRecording; - end - - function ConfirmIntensity - %Compute the intensity we want to deliver to the subject. - p.var.ShockIntensity = p.out.PainThreshold*p.out.ShockFactor; - % - ShowInstruction(9,1); - % - fprintf([repmat('=',1,50) '\n']); - fprintf('TEST SHOCK:\n'); - fprintf('!!! ADJUST THE SHOCK INTENSITY ON THE DIGITIMER !!!\n'); - fprintf(' The intensity is now: %g mA\n',p.var.ShockIntensity); - fprintf(' Experimenter: Press any key to deliver a shock.\n'); - fprintf([repmat('=',1,50) '\n']); - % - [secs, keyCode, deltaSecs] = KbStrokeWait(p.ptb.device); - ShowInstruction(10,0,1+rand(1));%shock is coming message... - t = GetSecs + p.duration.shock; - while GetSecs < t; - Buzz; - end - % - message = 'Bewege den "Zeiger" mit der rechten und linken Pfeiltaste\n und bestätige deine Einschätzung mit der mit der oberen Pfeiltaste.'; - rect = [p.ptb.width*0.2 p.ptb.midpoint(2) p.ptb.width*0.6 100]; - response = RatingSlider(rect,2,1,p.keys.increase,p.keys.decrease,p.keys.confirm,{ 'nicht\nerträglich' 'erträglich'},message,0); - if response == 2 - fprintf('All is fine :)\n'); - fprintf('Subject confirmed the shock intensity inside the scanner...\n'); - fprintf('INTENSITY TO BE USED FOR THE MAIN EXPERIMENT: %g mA\n',p.var.ShockIntensity); - p.out.ShockIntensity = p.var.ShockIntensity; - return; - elseif response == 1 - fprintf('Shit... :(, %g is too much for the subject\n',p.var.ShockIntensity); - fprintf('We will try a little milder intensity.\n'); - p.out.ShockFactor = p.out.ShockFactor - 0.05; - ConfirmIntensity; - end - - - end - function PresentStimuli - %Enter the presentation loop and wait for the first pulse to - %arrive. - %wait for the dummy scans - [secs] = WaitPulse(p.keys.pulse,p.mrt.dummy_scan);%will log it - KbQueueStop(p.ptb.device); - WaitSecs(.05); - KbQueueCreate(p.ptb.device); - KbQueueStart(p.ptb.device); - %log the pulse timings. - mblock_jumps = logical([1 diff(p.presentation.mblock)]); - TimeEndStim = secs(end)- p.ptb.slack;%take the first valid pulse as the end of the last stimulus. - for nTrial = 1:p.presentation.tTrial; - - %Get the variables that Trial function needs. - stim_id = p.presentation.stim_id(nTrial); - fix_y = p.presentation.CrossPosition(nTrial); - ISI = p.presentation.isi(nTrial); - ucs = p.presentation.ucs(nTrial); - oddball = p.presentation.oddball(nTrial); - prestimdur = p.duration.prestim+rand(1)*.25; - dist = p.presentation.dist(nTrial); - mblock_jump = mblock_jumps(nTrial); - block_id = p.presentation.mblock(nTrial); - %prestimdur = p_presentation_prestim_dur(nTrial); - % - OnsetTime = TimeEndStim + ISI-p.duration.stim - p.ptb.slack; - fprintf('%d of %d, S: %d, ISI: %d, UCS: %d, ODD: %d, OnsetTime: %05.8gs, ',nTrial,p.presentation.tTrial,stim_id,ISI,ucs,oddball, OnsetTime); - - %Start with the trial, here is time-wise sensitive must be - %optimal - [TimeEndStim] = Trial(nTrial,OnsetTime, prestimdur, stim_id , ucs , fix_y, oddball,dist,mblock_jump,block_id); - %(nTrial,TimeStimOnset , prestimdur, stim_id , ucs , fix_i, oddball, dist ) - fprintf('OffsetTime: %05.8gs, Difference of %05.8gs\n',TimeEndStim,TimeEndStim-OnsetTime-p.duration.stim); - % - %dump it - [keycode, secs] = KbQueueDump;%this contains both the pulses and keypresses. - %log everything but "pulse keys" as pulses, not as keypresses. - pulses = (keycode == p.keys.pulse); - if any(~pulses);%log keys presses if only there is one - Log(secs(~pulses),7,keycode(~pulses)); - end - if any(pulses);%log pulses if only there is one - Log(secs(pulses),0,keycode(pulses)); - end - %now we have to detect if the subject has pressed the CONFIRM - %key while the ODDBALL stimulus was on the screen. - if any((keycode == p.keys.confirm) & (secs > OnsetTime) & (secs <= TimeEndStim)) - p.out.response(nTrial) = 1; - fprintf('Subject Pressed the Hit Key!!\n'); - end - end - %wait 6 seconds for the BOLD signal to come back to the baseline... - KbQueueStop(p.ptb.device); - KbQueueRelease(p.ptb.device); - - if p.var.ExpPhase > 0 - WaitPulse(p.keys.pulse,p.mrt.dummy_scan);% - fprintf('OK!! Stop the Scanner\n'); - end - %dump the final events - [keycode, secs] = KbQueueDump;%this contains both the pulses and keypresses. - %log everything but "pulse keys" as pulses, not as keypresses. - pulses = (keycode == p.keys.pulse); - if any(~pulses);%log keys presses if only there is one - Log(secs(~pulses),7,keycode(~pulses)); - end - if any(pulses);%log pulses if only there is one - Log(secs(pulses),0,keycode(pulses)); - end - %stop the queue - KbQueueStop(p.ptb.device); - KbQueueRelease(p.ptb.device); - WaitSecs(10); - end - function [TimeEndStim]=Trial(nTrial,TimeStimOnset , prestimdur, stim_id , ucs , fix_i, oddball, dist,microblock_jump,mblock_id) - %get all the times - TimeCrossOnset = TimeStimOnset - prestimdur; - TimeCrossJump = TimeStimOnset + p.duration.stim/2; - TimeEndStim = TimeStimOnset + p.duration.stim- p.ptb.slack; - TimeStartShock = TimeStimOnset + p.duration.onset2shock; - TimeTrackerOff = TimeStimOnset + p.duration.keep_recording; - - %% Fixation Onset - fix = [p.ptb.CrossPosition_x p.ptb.CrossPosition_y(fix_i)]; - FixCross = [fix(1)-1,fix(2)-p.ptb.fc_size,fix(1)+1,fix(2)+p.ptb.fc_size;fix(1)-p.ptb.fc_size,fix(2)-1,fix(1)+p.ptb.fc_size,fix(2)+1]; - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.imrect ); %always create a gray background - Screen('FillRect', p.ptb.w, [255,255,255], FixCross');%draw the prestimus cross atop - - Screen('DrawingFinished',p.ptb.w,0); - TimeCrossOn = Screen('Flip',p.ptb.w,TimeCrossOnset,0); - Log(TimeCrossOn,1,fix_i);%cross onset. - %turn the eye tracker on - StartEyelinkRecording(nTrial,stim_id,p.var.ExpPhase,dist,oddball,ucs,fix,mblock_id); - %% Draw the stimulus to the buffer - if ~stim_id==0 - Screen('DrawTexture', p.ptb.w, p.ptb.stim_sprites(stim_id)); - end - %draw also the fixation cross - Screen('FillRect', p.ptb.w, [255,255,255], FixCross'); - Screen('DrawingFinished',p.ptb.w,0); - %% STIMULUS ONSET - TimeStimOnset = Screen('Flip',p.ptb.w,TimeStimOnset,0);%asap and dont clear - %send eyelink and ced a marker asap - Eyelink('Message', 'Stim Onset'); - Eyelink('Message', 'SYNCTIME'); - MarkCED( p.com.lpt.address, p.com.lpt.StimOnset ); - if oddball - MarkCED( p.com.lpt.address, p.com.lpt.oddball ); - end - if ucs - MarkCED(p.com.lpt.address, p.com.lpt.ucs); - end - if microblock_jump - MarkCED( p.com.lpt.address, p.com.lpt.mBlock ); - Log(TimeStimOnset,9,mblock_id) - end - Log(TimeStimOnset,3,dist);%log the stimulus onset - - %% CROSS JUMPS (same as before but with a different fix position) - if ~stim_id==0 - Screen('DrawTexture', p.ptb.w, p.ptb.stim_sprites(stim_id)); - end - fix = [p.ptb.CrossPosition_x p.ptb.CrossPosition_y(setdiff(1:2,fix_i))];%take the other position - %draw also the fixation cross - FixCross = [fix(1)-1,fix(2)-p.ptb.fc_size,fix(1)+1,fix(2)+p.ptb.fc_size;fix(1)-p.ptb.fc_size,fix(2)-1,fix(1)+p.ptb.fc_size,fix(2)+1]; - Screen('FillRect', p.ptb.w, [255,255,255], FixCross'); - Screen('DrawingFinished',p.ptb.w,0); - TimeCrossJump = Screen('Flip',p.ptb.w,TimeCrossJump,0);%asap and dont clear - Log(TimeCrossJump,4,0);%log the stimulus onset - %% - if ucs == 1 - %%%%%%%%%%%%%%%%%%%%%%% - %Deliver shock and stim off immediately - TimeStartShock = WaitSecs('UntilTime',TimeStartShock); - Eyelink('Message', 'UCS Onset'); - - while GetSecs < TimeEndStim; - Buzz;%this is anyway sent to CED. - end - end - - %% STIM OFF immediately - TimeEndStim = Screen('Flip',p.ptb.w,TimeEndStim,0); - %send eyelink and ced a marker - Log(TimeEndStim,6,stim_id);%log the stimulus offset - % - %% record some more eye data after stimulus offset. - WaitSecs('UntilTime',TimeTrackerOff); - Eyelink('Message', 'Stim Offset'); - Eyelink('Message', 'BLANK_SCREEN'); - TimeTrackerOff = StopEyelinkRecording; - - - if oddball == 1 - fprintf('This was an oddball trial!\n'); - end - if ucs == 1 - fprintf('This was a UCS trial!\n'); - Log(TimeStartShock,5,NaN);%UCS delivery...This is done here to not waste time there - end - - end - - function SetParams - %mrt business - p.mrt.dummy_scan = 7;%this will wait until the 6th image is acquired. - p.mrt.LastScans = 5;%number of scans after the offset of the last stimulus - p.mrt.tr = 1;%in seconds. - %will count the number of events to be logged - p.var.event_count = 0; - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %% relative path to stim and experiments - %Path Business. - [~, hostname] = system('hostname'); - p.hostname = deblank(hostname); - if strcmp(p.hostname,'triostim1') - p.path.baselocation = 'C:\USER\onat\Experiments\fearamy'; - elseif strcmp(p.hostname,'etpc') - p.path.baselocation = 'C:\Users\onat\Documents\Experiments\'; - elseif ismac - p.path.baselocation = '/Users/onat/Desktop/fearamy'; - elseif ispc - p.path.baselocation = 'C:\Users\user\Documents\Experiments\FearCloud_Eyelab\stereotype\'; - end - - p.path.experiment = [p.path.baselocation filesep]; - p.path.stim = [p.path.baselocation filesep 'stimuli' filesep]; - p.path.stim24 = [p.path.stim '24bit' filesep]; - p.path.stim_cut = [p.path.stim 'cut' filesep]; - % - p.subID = sprintf('s%02d',subject); - timestamp = datestr(now,30); - p.path.subject = [p.path.experiment 'tmp' filesep p.subID '_' timestamp filesep ]; - p.path.finalsubject = [p.path.experiment 'data' filesep p.subID '_' timestamp filesep ]; - p.path.path_edf = [p.path.subject 'eye' filesep]; - p.path.edf = sprintf([p.subID 'p%02d.edf' ],phase); - p.path.path_param = [p.path.subject 'stimulation' filesep 'data.mat']; - %create folder hierarchy - mkdir(p.path.subject); - mkdir([p.path.subject 'scr']); - mkdir([p.path.subject 'eye']); - mkdir([p.path.subject 'stimulation']); - mkdir([p.path.subject 'midlevel']); - %% %%%%%%%%%%%%%%%%%%%%%%%%% - %get stim files - [p.stim.files p.stim.label] = FileMatrix([p.path.stim '*.bmp']); - [p.stim.files_cut p.stim.label] = FileMatrix([p.path.stim_cut '*.bmp']); - p.stim.tFile = size(p.stim.files,1);%number of different files (including the UCS symbol) - p.stim.tFace = 8;%number of faces. - % - display([mat2str(p.stim.tFile) ' found in the destination.']); - %set the background gray according to the background of the stimuli - for i = 1:p.stim.tFace; - im = imread(p.stim.files(i,:)); - bg(i) = im(1,1,1); - end - %is all the captured bg values the same? - if sum(diff(bg))==0; - %if so take it as the bg color - p.stim.bg = double([bg(1) bg(1) bg(1)]); - else - fprintf('background luminance was not successfully detected...\n') - keyboard; - end - %bg of the rating screen. - p.stim.bg_rating = p.stim.bg; - p.stim.white = [255 255 255]; - %% font size and background gray level - p.text.fontname = 'Times New Roman'; - p.text.fontsize = 18;%30; - p.text.fixsize = 60; - %rating business - p.rating.division = 10;%number of divisions for the rating slider - p.rating.repetition = 2;%how many times a given face has to be repeated... - %% get the actual stim size (assumes all the same) - info = imfinfo(p.stim.files(1,:)); - p.stim.width = info.Width; - p.stim.height = info.Height; - %% keys to be used during the experiment - %1, 6 ==> Right - %2, 7 ==> Left - %3, 8 ==> Down - %4, 9 ==> Up (confirm) - %5 ==> Pulse from the scanner - p.keys.confirm = KbName('return'); - p.keys.increase = KbName('left'); - p.keys.decrease = KbName('right'); - p.keys.pulse = KbName('5%'); - p.keys.el_calib = KbName('v'); - p.keys.el_valid = KbName('c'); - if ismac - p.keys.escape = KbName('escape'); - else - p.keys.escape = KbName('esc'); - end - - %% %%%%%%%%%%%%%%%%%%%%%%%%% - %Communication business - %parallel port - p.com.lpt.address = 888; - %codes for different events - p.com.lpt.digitimer = 12;%8 - p.com.lpt.mBlock = 128; - p.com.lpt.StimOnset = 64; - p.com.lpt.oddball = 32; - p.com.lpt.ucs = 16; - - % - %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %timing business - %these are the intervals of importance - %time2fixationcross->cross2onset->onset2shock->shock2offset - %these (duration.BLA) are average duration values: - p.duration.stim = 1.5;%2;%s - p.duration.shock = 0.1;%s;x - p.duration.shockpulse = 0.005;%ms; duration of each individual pulses - p.duration.intershockpulse = 0.01;%ms; and the time between each pulse - p.duration.onset2shock = p.duration.stim - p.duration.shock; - p.duration.crossmoves = p.duration.stim./2; - p.duration.keep_recording = 0.25;%this is the time we will keep recording (eye data) after stim offset. - p.duration.prestim = .85; - %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %stimulus sequence - if phase == 0 - seq(subject,csp).cond_id = Shuffle([0 1 2 3 4 5 6 7 8 10]); - seq(subject,csp).tTrial = length(seq(subject,csp).cond_id); - seq(subject,csp).ucs = zeros(1,seq(subject,csp).tTrial); - seq(subject,csp).oddball = seq(subject,csp).cond_id == 10; - seq(subject,csp).isi = PsychRandSample([3 4.5],[1 seq(subject,csp).tTrial]); - seq(subject,csp).stim_id = seq(subject,csp).cond_id; - seq(subject,csp).stim_id(seq(subject,csp).cond_id == 10) = 9; - seq(subject,csp).dist = 1:10; - seq(subject,csp).CrossPosition = ones(1,seq(subject,csp).tTrial); - seq(subject,csp).mblock = ones(1,seq(subject,csp).tTrial); - elseif phase == 1 - load([fileparts(which('exp_FearAmy.m')) '/bin/fearamy_seq.mat']); - end - %this will deal all the presentation sequence related information - p.presentation = seq(subject,csp); - clear seq - %% create the randomized design - p.stim.cs_plus = csp;%index of cs stimulus, this is the one paired to shock - p.stim.cs_neg = csn; - %Record which Phase are we going to run in this run. - p.stim.phase = phase; - - - p.out.rating = []; - p.out.log = zeros(1000000,4).*NaN; - p.out.response = zeros(p.presentation.tTrial,1); - p.out.ShockFactor = 2; - p.out.selectedface = []; - p.out.cond = []; - p.out.counterbal = counterbal; - %% -% p.out.PainThreshold = PainThreshold; - p.var.current_bg = p.stim.bg;%current background to be used. - %Save the stuff - save(p.path.path_param,'p'); - % - function [FM labels] = FileMatrix(path) - %Takes a path with file extension associated to regexp (e.g. - %C:\blabl\bla\*.bmp) returns the file matrix - dummy = dir(path); - FM = [repmat([fileparts(path) filesep],length(dummy),1) vertcat(dummy(:).name)]; - labels = {dummy(:).name}; - end - end - function AskStimRating - - - p.var.ExpPhase = 5; - p.var.current_bg = p.stim.bg_rating; - %% create the order of presentation and balance the position of fixation cross - nseq = 0; - rating_seq = []; - pos1_seq = []; - idx = []; - face_order = 1:p.stim.tFace; - while nseq < p.rating.repetition - nseq = nseq + 1; - [dummy idx] = Shuffle( face_order ); - rating_seq = [rating_seq dummy]; - %this balances both directions - pos1_seq = [pos1_seq ones(1,p.stim.tFace)];%+1 to make [0 1] --> [1 2] - end - rating_seq = rating_seq(:); - pos1_seq = pos1_seq(:); - %% - message = GetText(11); - SliderTextL = GetText(13); - SliderTextR = GetText(12); - % set the background to different color - Screen('FillRect', p.ptb.w , p.var.current_bg ); - Screen('Flip',p.ptb.w); - WaitSecs(2); - % - ShowInstruction(7,1); - rect = [p.ptb.width*0.2 p.ptb.midpoint(2) p.ptb.width*0.6 100];%for the rating slider - tRatend = length(rating_seq); - %save the rating sequence just for security - p.out.rating_seq = rating_seq; - p.out.pos1_seq = pos1_seq; - - %run over all the pictures to be rated. - for nRatend = 1:tRatend; - % - %the variable that are used by Trial function - stim_id = rating_seq(nRatend); - fix_y = pos1_seq(nRatend); - % - next_stim_id = [];%this is a trick, otherwise a fixation cross appears right before the rating :( - next_pos1 = []; - % - %to send know the distance here, little dummy setup: - dummy = -135:45:180; - dist = dummy(stim_id); - % show the picture - %Trial(nTrial ,TimeStimOnset , prestimdur, stim_id , ucs , fix_i, oddball, dist,microblock_jump,mblock_id) - Trial(1000+nRatend,GetSecs+1,p.duration.prestim,stim_id,0,fix_y,0,dist,0,0); - % show the slider - rate(nRatend,1) = RatingSlider(rect, p.rating.division, Shuffle(1:p.rating.division,1), p.keys.increase, p.keys.decrease, p.keys.confirm, {SliderTextL{1} SliderTextR{1}},message,1); - - %%%%%%%%%%%%%%%%%%%%%%%%%%%% - %Verbose the rating of the subject - fprintf('============\nRating Results %d (%d/%d):\n', stim_id, nRatend, tRatend); - dummy = rating_seq(1:nRatend);%trials shown so far - for iii = 1:p.stim.tFace - r = round(mean(rate(dummy == iii))); - if isnan(r) - r = 0; - end - if iii == p.stim.cs_plus - fprintf('Stimulus %02d: * %s \n',iii,repmat('+',1,1+r)); - else - fprintf('Stimulus %02d: %s \n',iii,repmat('+',1,1+r)); - end - end - end - %sort the stim_ids and then sort the same the rates and make a - %matrix out of that to store - [~, i] = sort(rating_seq); - rate = reshape(rate(i),p.rating.repetition,p.stim.tFace)'; - p.out.rating = rate; - save(p.path.path_param,'p'); - Screen('FillRect',p.ptb.w,p.var.current_bg); - % - save(p.path.path_param,'p'); - end - function [rating] = RatingSlider(rect,tSection,position,up,down,confirm,labels,message,numbersOn) - % - %Detect the bounding boxes of the labels. - for nlab = 1:2 - [~ , ~, bb(nlab,:)]=DrawFormattedText(p.ptb.w,labels{nlab}, 'center', 'center', p.stim.white,[],[],[],2); - Screen('FillRect',p.ptb.w,p.var.current_bg); - end - bb = max(bb); - bb_size = bb(3)-bb(1);%vertical size of the bb. - % - DrawSkala; - ok = 1; - while ok == 1 - [secs, keyCode, ~] = KbStrokeWait(p.ptb.device); - keyCode = find(keyCode); - Log(secs,7,keyCode); - if length(keyCode) == 1%this loop avoids crashes to accidential presses of meta keys - if (keyCode == up) || (keyCode == down) - next = position + increment(keyCode); - if next < (tSection+1) && next > 0 - position = position + increment(keyCode); - end - DrawSkala; - elseif keyCode == confirm - WaitSecs(0.1); - ok = 0; - Screen('FillRect',p.ptb.w,p.var.current_bg); - t=Screen('Flip',p.ptb.w); - end - end - end - - function DrawSkala - %rating = tSection - position + 1; - rating = position ; - increment([up down]) = [1 -1];%delta - tick_x = linspace(rect(1),rect(1)+rect(3),tSection+1);%tick positions - tick_size = rect(3)./tSection; - ss = tick_size/5*0.9;%slider size. - % - for tick = 1:length(tick_x)%draw ticks - Screen('DrawLine', p.ptb.w, [255 0 0], tick_x(tick), rect(2), tick_x(tick), rect(2)+rect(4) , 3); - if tick <= tSection && numbersOn - Screen('TextSize', p.ptb.w,p.text.fontsize); - DrawFormattedText(p.ptb.w, mat2str(tick) , tick_x(tick)+ss/2, rect(2)+rect(4), p.stim.white); - Screen('TextSize', p.ptb.w,p.text.fontsize); - end - if tick == 1 - DrawFormattedText(p.ptb.w, labels{1},tick_x(tick)-bb_size*1.4,rect(2), p.stim.white); - elseif tick == tSection+1 - DrawFormattedText(p.ptb.w, labels{2},tick_x(tick)+bb_size*0.4,rect(2), p.stim.white); - end - end - %slider coordinates - slider = [ tick_x(position)+tick_size*0.1 rect(2) tick_x(position)+tick_size*0.9 rect(2)+rect(4)]; - %draw the slider - Screen('FillRect',p.ptb.w, p.stim.white, round(slider)); - Screen('TextSize', p.ptb.w,p.text.fontsize); - DrawFormattedText(p.ptb.w,message, 'center', p.ptb.midpoint(2)*0.2, p.stim.white,[],[],[],2); - Screen('TextSize', p.ptb.w,p.text.fontsize); - t = Screen('Flip',p.ptb.w); - Log(t,-2,NaN); - end - end - function ShowInstruction(nInstruct,waitforkeypress,varargin) - %ShowInstruction(nInstruct,waitforkeypress) - %if waitforkeypress is 1, ==> subject presses a button to proceed - %if waitforkeypress is 0, ==> text is shown for VARARGIN seconds. - - - [text]= GetText(nInstruct); - ShowText(text); - if waitforkeypress %and blank the screen as soon as the key is pressed - KbStrokeWait(p.ptb.device); - else - WaitSecs(varargin{1}); - end - Screen('FillRect',p.ptb.w,p.var.current_bg); - t = Screen('Flip',p.ptb.w); - - function ShowText(text) - - Screen('FillRect',p.ptb.w,p.var.current_bg); - DrawFormattedText(p.ptb.w, text, 'center', 'center',p.stim.white,[],[],[],2,[]); - t=Screen('Flip',p.ptb.w); - Log(t,-1,nInstruct); - %show the messages at the experimenter screen - fprintf('=========================================================\n'); - fprintf('Text shown to the subject:\n'); - fprintf(text); - fprintf('=========================================================\n'); - - end - end - function [text]=GetText(nInstruct) - - if nInstruct == 0%intro - - text = ['Thanks for participating in this short poll. \n\n' ... - 'In the following few trials, you will see a circle of faces,\n' ... - 'from which we ask you to choose one regarding a given question.\n\n' ... - 'The questions differ from trial to trial, so read each instruction carefully!\n\n' ... - 'Please confirm that you want to start by pressing ENTER.\n' ... - ]; - elseif nInstruct == 1%male - - text = ['Which face do you think is the most MALE face? \n\n' ... - 'Please use the left/right arrow key to move the marker to the face of your choice\n' ... - 'and confirm with ENTER.\n' ... - ]; - elseif nInstruct == 2%male - - text = ['Which face do you think is the most FEMALE face? \n\n' ... - 'Please use the left/right arrow key to move the marker to the face of your choice\n' ... - 'and confirm with ENTER.\n' ... - ]; - - elseif nInstruct == 3%age-young - text = ['Which face do you think is the YOUNGEST face? \n\n' ... - 'Please use the left/right arrow key to move the marker to the face of your choice\n' ... - 'and confirm with ENTER.\n' ... - ]; - elseif nInstruct == 4%age-old - text = ['Which face do you think is the OLDEST face? \n\n' ... - 'Please use the left/right arrow key to move the marker to the face of your choice\n' ... - 'and confirm with ENTER.\n' ... - ]; - elseif nInstruct == 14 - text = ['Thanks!\n'... - 'Danke!']; - else - text = {''}; - end - end - function SetPTB - %KbName('UnifyKeyNames'); - %Sets the parameters related to the PTB toolbox. Including - %fontsizes, font names. - %Default parameters - Screen('Preference', 'SkipSyncTests', 1); - Screen('Preference', 'DefaultFontSize', p.text.fontsize); - Screen('Preference', 'DefaultFontName', p.text.fontname); - Screen('Preference', 'TextAntiAliasing',2);%enable textantialiasing high quality - Screen('Preference', 'VisualDebuglevel', 0); - Screen('Preference', 'SkipSyncTests', 1); - Screen('Preference', 'SuppressAllWarnings', 1); - %%Find the number of the screen to be opened - screens = Screen('Screens'); - p.ptb.screenNumber = max(screens);%the maximum is the second monitor - %Make everything transparent for debugging purposes. - if debug - commandwindow; - PsychDebugWindowConfiguration; - end - %set the resolution correctly - res = Screen('resolution',p.ptb.screenNumber); - HideCursor(p.ptb.screenNumber); - %spit out the resolution - fprintf('Resolution of the screen is %dx%d...\n',res.width,res.height); - - %Open a graphics window using PTB - [p.ptb.w p.ptb.rect] = Screen('OpenWindow', p.ptb.screenNumber, p.var.current_bg); - %Screen('BlendFunction', p.ptb.w, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - Screen('Flip',p.ptb.w);%make the bg - p.ptb.slack = Screen('GetFlipInterval',p.ptb.w)./2; - [p.ptb.width, p.ptb.height] = Screen('WindowSize', p.ptb.screenNumber); - - %find the mid position on the screen. - p.ptb.midpoint = [ p.ptb.width./2 p.ptb.height./2]; - %NOTE about RECT: - %RectLeft=1, RectTop=2, RectRight=3, RectBottom=4. - p.ptb.imrect = [ p.ptb.midpoint(1)-p.stim.width/2 p.ptb.midpoint(2)-p.stim.height/2 p.ptb.midpoint(1)-p.stim.width/2+p.stim.width p.ptb.midpoint(2)-p.stim.height/2+p.stim.height]; - p.ptb.cross_shift = [180 -120]./2.5;%incremental upper and lower cross positions - p.ptb.CrossPosition_x = p.ptb.midpoint(1);%bb(1);%always the same - p.ptb.CrossPosition_y = p.ptb.midpoint(2)+p.ptb.cross_shift;%bb(1);%always the same - %cross position for the eyetracker screen. - p.ptb.CrossPositionET_x = [p.ptb.midpoint(1) p.ptb.midpoint(1)]; - p.ptb.CrossPositionET_y = [p.ptb.midpoint(2)-p.ptb.cross_shift(2) p.ptb.midpoint(2)+p.ptb.cross_shift(2)]; - p.ptb.fc_size = 10; - % - %% - %priorityLevel=MaxPriority(['GetSecs'],['KbCheck'],['KbWait'],['GetClicks']); - Priority(MaxPriority(p.ptb.w)); - %this is necessary for the Eyelink calibration - %InitializePsychSound(0) - %sound('Open') - % Beeper(1000) - LoadPsychHID - %%%%%%%%%%%%%%%%%%%%%%%%%%%Prepare the keypress queue listening. - p.ptb.device = []; - %get all the required keys in a vector - p.ptb.keysOfInterest = [];for i = fields(p.keys)';p.ptb.keysOfInterest = [p.ptb.keysOfInterest p.keys.(i{1})];end - fprintf('Key listening will be restricted to %d\n',p.ptb.keysOfInterest) - RestrictKeysForKbCheck(p.ptb.keysOfInterest); - - p.ptb.keysOfInterest=zeros(1,256); - p.ptb.keysOfInterest(p.keys.confirm) = 1; - %create a queue sensitive to only relevant keys. - % KbQueueCreate(p.ptb.device,p.ptb.keysOfInterest);%default device. - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %prepare parallel port communication. This relies on cogent i - %think. We could do it with PTB as well. -% if ~ismac -% config_io; -% outp(p.com.lpt.address,0); -% if( cogent.io.status ~= 0 ) -% error('inp/outp installation failed'); -% end -% end -% - %CORRECT - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %test whether CED receives the triggers correctly... -% k = 0; -% while ~(k == 25 | k == 86 ); -% pause(0.1); -% outp(p.com.lpt.address,244);%244 means all but the UCS channel (so that we dont shock the subject during initialization). -% fprintf('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'); -% fprintf('1/ Red cable has to be connected to the Cogent BOX\n'); -% fprintf('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'); -% fprintf('2/ D2 Connection not to forget on the LPT panel\n'); -% fprintf('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'); -% fprintf('3/ Switch the SCR cable\n'); -% fprintf('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'); -% fprintf('4/ Button box has to be on\n'); -% fprintf('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'); -% fprintf('5/ Did the trigger test work?\n!!!!!!You MUST observe 5 pulses on the PHYSIOCOMPUTER!!!!!\n\n\nPress c to send it again, v to continue...\n') -% [~, k] = KbStrokeWait(p.ptb.device); -% k = find(k); -% end -% fprintf('Continuing...\n'); - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %load the pictures to the memory. - p.ptb.stim_sprites = CreateStimSprites(p.stim.files);% - p.ptb.stim_sprites_cut = CreateStimSprites(p.stim.files_cut);% - %% take care of the circle presentation - %order of faces on the circle that will be shown at the end. - if phase ~= 0 - keyboard - circle_order = Shuffle(unique(p.presentation.dist(p.presentation.dist < 500)));% - circle_order(end+1)=circle_order(1); - while any(abs(diff(circle_order)) < 50);%check that neighbors will not be neighbors in the next order. - circle_order = Shuffle(unique(p.presentation.dist(p.presentation.dist < 500))); - circle_order(end+1) = circle_order(1);%to be successful the check has to consider the circularity. - end - p.stim.circle_order = circle_order(1:end-1);%conditions in distances from CSP, 0 = CS+, randomized - p.stim.circle_angles = sort(p.stim.circle_order);%this is just angles with steps of 45 - %transform the angles to rects - for nc = 1:p.stim.tFace - p.stim.circle_rect(nc,:) = angle2rect(p.stim.circle_angles(nc)); - p.stim.circle_file_id(nc) = unique(p.presentation.stim_id(p.presentation.dist == p.stim.circle_order(nc)));%the file that corresponds to different conditions - end - %one to one mappings: - %now we have: circle_order ==> file_id - %circle_angles ==> circle_rect - end - - %% - function [out]=CreateStimSprites(files) - %loads all the stims to video memory - for nStim = 1:p.stim.tFile - filename = files(nStim,:); - [im , ~, ~] = imread(filename); - out(nStim) = Screen('MakeTexture', p.ptb.w, im ); - end - end - end - function [t]=StopEyelinkRecording - Eyelink('StopRecording'); - t = GetSecs; - %this is the end of the trial scope. - WaitSecs(0.01); - Eyelink('Message', 'TRIAL_RESULT 0'); - % - WaitSecs(0.01); - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('Command', 'clear_screen %d', 0); - Screen('Textsize', p.ptb.w,p.text.fontsize); - Log(t,8,NaN); - end - - function [t]=StartEyelinkRecording(nTrial,nStim,phase,dist,oddball,ucs,fix,block_id) - t = []; - if isnan(dist) - dist=3000; - end - nStim = double(nStim); - Eyelink('Message', 'TRIALID: %04d, PHASE: %04d, FILE: %04d, DELTACSP: %04d, ODDBALL: %04d, UCS: %04d, FIXX: %04d, FIXY %04d, MBLOCK %04d', nTrial, phase, nStim, dist, double(oddball), double(ucs),fix(1),fix(2),block_id); - Eyelink('Message', 'FX Onset at %d %d',fix(1),fix(2)); - % an integration message so that an image can be loaded as - % overlay background when performing Data Viewer analysis. - WaitSecs(0.01); - %return - if nStim~=0 - Eyelink('Message', '!V IMGLOAD CENTER %s %d %d', p.stim.files(nStim,:), p.ptb.midpoint(1), p.ptb.midpoint(2)); - end - % This supplies the title at the bottom of the eyetracker display - Eyelink('Command', 'record_status_message "Stim: %02d, Phase: %d"', nStim, phase); - % - %Put the tracker offline and draw the stimuli. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - % clear tracker display and draw box at center - Eyelink('Command', 'clear_screen %d', 0); - %draw the image on the screen but also the two crosses - if (nStim <= 16 && nStim>0) - Eyelink('ImageTransfer',p.stim.files24(nStim,:),p.ptb.imrect(1),p.ptb.imrect(2),p.stim.width,p.stim.height,p.ptb.imrect(1),p.ptb.imrect(2),0); - end - Eyelink('Command', 'draw_cross %d %d 15',fix(1),fix(2)); - Eyelink('Command', 'draw_cross %d %d 15',fix(1),fix(2)+diff(p.ptb.cross_shift)); - - % - %drift correction - %EyelinkDoDriftCorrection(el,crosspositionx,crosspositiony,0,0); - %start recording following mode transition and a short pause. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('StartRecording'); - t = GetSecs; - Log(t,2,NaN); - end - function [shuffled idx] = Shuffle(vector,N) - %takes first N from the SHUFFLED before outputting. This function - %could be used as a replacement for randsample - if nargin < 2;N = length(vector);end - [~, idx] = sort(rand([1 length(vector)])); - shuffled = vector(idx(1:N)); - shuffled = shuffled(:); - end - function Buzz - outp(p.com.lpt.address, p.com.lpt.digitimer ); - WaitSecs(p.duration.shockpulse); - outp(p.com.lpt.address, 0); - WaitSecs(p.duration.intershockpulse); - end - function MarkCED(socket,port) - %send pulse to SCR# - outp(socket,port); - WaitSecs(0.01); - outp(socket,0); - end - function InitEyeLink - % - if EyelinkInit(0)%use 0 to init normaly - fprintf('=================\nEyelink initialized correctly...\n') - else - fprintf('=================\nThere is problem in Eyelink initialization\n') - keyboard; - end - % - WaitSecs(0.5); - [~, vs] = Eyelink('GetTrackerVersion'); - fprintf('=================\nRunning experiment on a ''%s'' tracker.\n', vs ); - - %load 24bits pictures for eyelink... - dummy = dir([p.path.stim24 '*.bmp']); - p.stim.files24 = [repmat([fileparts(p.path.stim24) filesep],length(dummy),1) vertcat(dummy(:).name)]; - % - el = EyelinkInitDefaults(p.ptb.w); - %update the defaults of the eyelink tracker - el.backgroundcolour = p.stim.bg; - el.msgfontcolour = WhiteIndex(el.window); - el.imgtitlecolour = WhiteIndex(el.window); - el.targetbeep = 0; - el.calibrationtargetcolour = WhiteIndex(el.window); - el.calibrationtargetsize = 1.5; - el.calibrationtargetwidth = 0.5; - el.displayCalResults = 1; - el.eyeimgsize = 50; - el.waitformodereadytime = 25;%ms - el.msgfont = 'Times New Roman'; - el.cal_target_beep = [0 0 0];%[1250 0.6 0.05]; - %shut all sounds off - el.drift_correction_target_beep = [0 0 0]; - el.calibration_failed_beep = [0 0 0]; - el.calibration_success_beep = [0 0 0]; - el.drift_correction_failed_beep = [0 0 0]; - el.drift_correction_success_beep= [0 0 0]; - EyelinkUpdateDefaults(el); - PsychEyelinkDispatchCallback(el); - - % open file. - res = Eyelink('Openfile', p.path.edf); - % - Eyelink('command', 'add_file_preamble_text ''Recorded by EyelinkToolbox FearAmy Experiment (Selim Onat)'''); - Eyelink('command', 'screen_pixel_coords = %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - Eyelink('message', 'DISPLAY_COORDS %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - % set calibration type. - Eyelink('command','auto_calibration_messages = YES'); - Eyelink('command', 'calibration_type = HV13'); - Eyelink('command', 'select_parser_configuration = 1'); - %what do we want to record - Eyelink('command', 'file_sample_data = LEFT,RIGHT,GAZE,HREF,AREA,GAZERES,STATUS,INPUT,HTARGET'); - Eyelink('command', 'file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON,INPUT'); - Eyelink('command', 'use_ellipse_fitter = no'); - % set sample rate in camera setup screen - Eyelink('command', 'sample_rate = %d',1000); - end - function StopEyelink(filename) - try - fprintf('Trying to stop the Eyelink system with StopEyelink\n'); - Eyelink('StopRecording'); - Log(t,8,NaN); - WaitSecs(0.5); - Eyelink('Closefile'); - display('receiving the EDF file...'); - Eyelink('ReceiveFile',filename,p.path.path_edf,1); - display('...finished!') - % Shutdown Eyelink: - Eyelink('Shutdown'); - catch - display('StopEyeLink routine didn''t really run well'); - end - end - function cleanup - % Close window: - sca; - %set back the old resolution - if strcmp(p.hostname,'triostim1') - % Screen('Resolution',p.ptb.screenNumber, p.ptb.oldres.width, p.ptb.oldres.height ); - %show the cursor - ShowCursor(p.ptb.screenNumber); - end - % - commandwindow; - KbQueueStop(p.ptb.device); - KbQueueRelease(p.ptb.device); - end - function CalibrateEL - fprintf('=================\n=================\nEntering Eyelink Calibration\n') - p.var.ExpPhase = 0; - ShowInstruction(0,1); - EyelinkDoTrackerSetup(el); - %Returns 'messageString' text associated with result of last calibration - [~, messageString] = Eyelink('CalMessage'); - Eyelink('Message','%s',messageString);% - WaitSecs(0.05); - fprintf('=================\n=================\nNow we are done with the calibration\n') - end - function Log(ptb_time, event_type, event_info) - %Phases: - %Instruction : 0 - %Test : 1 - %Rating : 5 - %Calibration : 0 - % - %event types are as follows: - % - %Pulse Detection : 0 info: NaN; - %Tracker Onset : 1 - %Cross Onset : 2 info: position - %Stimulus Onset : 3 info: dist_id - %Cross Movement : 4 info: NaN; - %UCS Delivery : 5 info: NaN; - %Stimulus Offset : 6 info: NaN; - %Key Presses : 7 info: NaN; - %Tracker Offset : 8 info: NaN; - %MicroBlock : 9 info:rank - % - %Text on the screen : -1 info: Which Text? - %RatingScreen Onset : -2 info: NaN; - for iii = 1:length(ptb_time) - p.var.event_count = p.var.event_count + 1; - p.out.log(p.var.event_count,:) = [ptb_time(iii) event_type event_info(iii) p.var.ExpPhase]; - end -% plot(p.out.log(1:p.var.event_count,1) - p.out.log(1,1),p.out.log(1:p.var.event_count,2),'o','markersize',10); -% ylim([-2 8]); -% set(gca,'ytick',[-2:8],'yticklabel',{'Rating On','Text','Pulse','Tracker+','Cross+','Stim+','CrossMov','UCS','Stim-','Key+','Tracker-'}); -% grid on -% drawnow; - - end - function [secs]=WaitPulse(keycode,n) - %[secs]=WaitPulse(keycode,n) - % - % This function waits for the Nth upcoming pulse. If N=1, it will wait for - % the very next pulse to arrive. 1 MEANS NEXT PULSE. So if you wish to wait - % for 6 full dummy scans, you should use N = 7 to be sure that at least 6 - % full acquisitions are finished. - % - % The function avoids KbCheck, KbWait functions, but relies on the OS - % level event queues, which are much less likely to skip short events. A - % nice discussion on the topic can be found here: - % http://ftp.tuebingen.mpg.de/pub/pub_dahl/stmdev10_D/Matlab6/Toolboxes/Psychtoolbox/PsychDocumentation/KbQueue.html - - %KbQueueFlush;KbQueueStop;KbQueueRelease;WaitSecs(1); - fprintf('Will wait for %i dummy pulses...\n',n); - if n ~= 0 - secs = nan(1,n); - pulse = 0; - dummy = []; - while pulse < n - dummy = KbTriggerWait(keycode,p.ptb.device); - pulse = pulse + 1; - secs(pulse+1) = dummy; - Log(dummy,0,NaN); - end - else - secs = GetSecs; - end - end - function [keycode, secs] = KbQueueDump; - %[keycode, secs] = KbQueueDump - % Will dump all the events accumulated in the queue. - - keycode = []; - secs = []; - pressed = []; - %fprintf('there are %03d events\n',KbEventAvail(p.ptb.device)); - while KbEventAvail(p.ptb.device) - [evt, n] = KbEventGet(p.ptb.device); - n = n + 1; - keycode(n) = evt.Keycode; - pressed(n) = evt.Pressed; - secs(n) = evt.Time; - % fprintf('Event is: %d\n',keycode(n)); - end - i = pressed == 1; - keycode(~i) = []; - secs(~i) = []; - %fprintf('there are %03d events found...\n',length(keycode)); - end -end diff --git a/exp_feargen_PFfitting_YN.m b/exp_feargen_PFfitting_YN.m deleted file mode 100644 index 49fd2d4..0000000 --- a/exp_feargen_PFfitting_YN.m +++ /dev/null @@ -1,1008 +0,0 @@ -function [p]=exp_feargen_PFfitting_YN(subject,phase,csp_degree) - -% Diskrimination Task estimating the Threshold alpha and Slope beta of an -% observer's underlying Psychometric Function (PF). -% Enter the subject Number as well as the CS+ Face in Degrees (where 00 is -% 1st face, and so) -simulation_mode = 0; -ncircle=1; - -ListenChar(2);%disable pressed keys to be spitted around -commandwindow; -%clear everything -clear mex global functions -cgshut; -global cogent; -%%%%%%%%%%%load the GETSECS mex files so call them at least once -GetSecs; -WaitSecs(0.001); - -el = []; -p = []; -SetParams; -SetPTB; - -InitEyeLink; -WaitSecs(2); -%calibrate if we are at the scanner computer. -if strcmp(p.hostname,'triostim1') || strcmp(p.hostname,'etpc'); - CalibrateEL; -end - -%save again the parameter file -save(p.path.path_param,'p'); - -% make a break every ....th Trial -breakpoint=50; - - -% counter for within chain trials (cc) and global trials (tt) -cc=zeros(1,tchain); -tt=0; -%trialID is counting every single face (2 per Trial_YN), need that for -%Eyelink -trialID=0; - - -for nc = 1:tchain -%set up procedure -PM{nc} = PAL_AMPM_setupPM('priorAlphaRange',p.psi.prioraaRange,'priorBetaRange',... - p.psi.priorBetaRange, 'priorLambdaRange', p.psi.priorLambdaRange,'priorGammaRange',... - p.psi.priorGammaRange,'numtrials',p.psi.numtrials, 'PF' , p.psi.PFfit, 'stimRange',p.psi.stimRange,... - 'marginalize', [3 4]); - -% -PM{nc}.reference_face = face_shift(nc); -PM{nc}.reference_circle = circle_shift(nc); -if p.psi.p0 ~= 0 - -shuffledummy=Shuffle(1:p.psi.numtrials); -p.psi.zerotrials(:,nc)=shuffledummy(1:ceil(p.psi.numtrials*p.psi.p0)); -end -% set up Log Variable -SetupLog(nc); -end - -ShowInstruction(1); - -OK = 1; -while OK - - current_chain = RandSample(1:tchain,[1 1]); - - - if PM{current_chain}.stop ~= 1 - tt=tt+1; - % enter in break loop - if (tt~=1 && mod(tt,breakpoint)==1 && simulation_mode==0); - save(p.path.path_param,'p'); - memory - ShowInstruction(4); - CalibrateEL; - end - cc(current_chain)=cc(current_chain)+1; - fprintf('Chain %4.2f , Trial %02d\n',current_chain,cc(current_chain)) - fprintf('Original PM.x: %4.2f \n',PM{current_chain}.x(cc(current_chain))) - % manually force x=0 trial, if it fits the zerotrial condition - if p.psi.p0 ~= 0 - if any(p.psi.zerotrials(:,current_chain)==cc(current_chain)) - fprintf('Forcing x=0 Trial...\n') - PM{current_chain}.xCurrent=0; - PM{current_chain}.x(cc(current_chain))=0; - - end - end - - - %Present trial here at stimulus intensity PM.xCurrent and collect - %response - direction = RandSample([-1 1],[1 1]); - fprintf('PM.x is now %4.2f \n',direction*PM{current_chain}.x(cc(current_chain))) - test = PM{current_chain}.xCurrent * direction + PM{current_chain}.reference_face + csp_degree + PM{current_chain}.reference_circle; - dummy = test; - % the computed degree has to stay in the same circle: - % whenever it goes left from the 00 degrees (360 at foreign), - % there's a problem - % for chain 1 and 2, values below 0 have to be shifted 360 - % degrees, - % for chain 3 and 4, values below 360 have to be shifted 360 degrees - % e.g., -45 has to be 315 in chain 1; 315 has to be 675 in chain 3 - % was done using mod... adding (0 0 360 360) (this is the last part) - test = mod(test,360)+ PM{current_chain}.reference_circle; - - % the reference is one of the four faces - %(cs+ local, cs- local, cs+ foreign, cs- forein) - ref = PM{current_chain}.reference_face + csp_degree + PM{current_chain}.reference_circle; - ref = mod(ref,360)+ PM{current_chain}.reference_circle; - - % fprintf('Chain: %03d\nxCurrent: %6.2f\nDirection:%6.2f\n %6.2f -> %6.2f vs. %6.2f\n',current_chain,PM{current_chain}.xCurrent,direction,dummy,test,ref); - % start Trial - fprintf('Starting Trial %03d/%03d.\n',tt,tchain*p.psi.numtrials) - - [test_face, ref_face, signal,trialID] = Trial_YN(trialID,ref,test,circle_id(current_chain),tt); - - fprintf('Rating.\n') - Screen('Textsize', p.ptb.w,p.text.fontsize); - %Rating Slider - % - message1 = 'Waren die Gesichter unterschiedlich oder gleich?\n'; - message2 = 'Bewege den "Zeiger" mit der rechten und linken Pfeiltaste\n und bestätige deine Einschätzung mit der oberen Pfeiltaste.'; - if ~simulation_mode - [response_subj] = RatingSlider(p.ptb.rect,2,Shuffle(1:2,1),p.keys.increase,p.keys.decrease,p.keys.confirm,{ 'unterschiedlich' 'gleich'},message1,message2,0); - - % see if subject found the different pair of faces... - % buttonpress left (Yes) is response_subj=2, right alternative (No) outputs a 1. - % note that response=1 only means "yes", and not correct or anything - sdt=NaN; - if (response_subj == 2 && signal == 1) - response=1; - fprintf('...Hit. \n') - sdt=1; - elseif (response_subj==1 && signal == 1) - response=0; - fprintf('...Miss. \n') - sdt=3; - elseif (response_subj == 2 && signal==0) - response=1; - fprintf('...False Alarm. \n') - sdt=2; - elseif (response_subj == 1 && signal == 0) - response=0; - fprintf('...Correct Rejection. \n') - sdt=4; - else - fprintf('error in the answer algorithm! \n') - end - - else - true_a = 45; - true_s = 10; - true_g = 0.2; - true_l = 0.02; - response = ObserverResponseFunction(p.psi.PFfit,true_a,1/true_s,true_g,true_l,PM{current_chain}.xCurrent); - - - - end - - - - % store everything in the Log - row = round(PM{current_chain}.xCurrent/p.stim.delta+1); - p.psi.log.trial_counter(row,current_chain) = p.psi.log.trial_counter(row,current_chain) + 1; - p.psi.log.xrounded(row,p.psi.log.trial_counter(row,current_chain),current_chain) = response; - - - %updating PM - PM{current_chain} = PAL_AMPM_updatePM(PM{current_chain},response); - SetLog; - %iteration control - dummy = cell2mat(PM); - OK = sum([dummy(:).stop]) ~= tchain; - end - - - %save Logfile here - - %save([p.path.path_param 'Log' num2str(subject) '.mat'],'p.psi.log'); - - %save again the parameter file - save(p.path.path_param,'p'); - -end -%end of Experiment, shown to subject -ShowInstruction(2); -%Print summary of results to screen -for chain=1:tchain -fprintf('Chain %g: Estimated Threshold (alpha): %4.2f \n',chain,PM{chain}.threshold(end)); -fprintf('Chain %g: Estimated Slope (beta): %4.2f \n',chain,PM{chain}.slope(end)); -end - -%get the eyelink file back to this computer -StopEyelink(p.path.edf); - - -%save([p.path.dropbox 'Log' num2str(subject) '.mat'],'p.psi.log') -% save PF Fit Plot -%feargenET_PFfitting_Fitplot(num2str(subject),p.log) - - -%clear the screen -%close everything down -cleanup; -%move the folder to appropriate location -movefile(p.path.subject,p.path.finalsubject); - - - - function [test_face,ref_face,signal,trialID] = Trial_YN(trialID,ref_stim,test_stim,last_face_of_circle,tt) - Screen('Textsize', p.ptb.w,p.text.fixsize); - % computes the trial FACES, using the test/ref information input - % values (in Deg) - - trial = [ref_stim test_stim]/p.stim.delta; - % correct face number within circle - trial = mod(round(trial),last_face_of_circle)+1; - ref_face = trial(1); - test_face = trial(2); - [trial,idx]= Shuffle(trial); - fprintf('Faces: %d %d \n',trial(1),trial(2)); - %compute if trial had different faces or not - %if trial(1)=trial(2), they were the same and subject has to - %answer with 'no' (right option, is 1), else means correct hit - - if trial(1)==trial(2) - signal = 0; - else - signal = 1; - end - - - trial_deg = [ref_stim test_stim]; - isref=double(trial==ref_face) ; - delta_ref = MinimumAngleQuartile([trial_deg(idx(1)) trial_deg(idx(2))],ref); - delta_csp = MinimumAngleQuartile([trial_deg(idx(1)) trial_deg(idx(2))],csp_degree); % ... - abs_FGangle = [trial_deg(idx(1)) trial_deg(idx(2))]; - - - %get fixation crosses and onsets from p parameter - fix = round(p.ptb.CrossPositions(tt,:)); - - trialID=trialID+1; - - - %GetSecs so that the onsets can be defined - - onsets = 0.25+GetSecs;%fix1 onset - onsets = [onsets onsets(end)+p.duration.fix+rand(1)*.25];%stim1 onset - onsets = [onsets onsets(end)+p.duration.stim];%stim1 offset - fixdelta=p.duration.fix+rand(1)*.25; - onsets = [onsets onsets(end)+1.5-fixdelta];%fix2 onset - onsets = [onsets onsets(end)+fixdelta];%stim2 onset - onsets = [onsets onsets(end)+p.duration.stim];%stim2 offset - - - - - %fixation cross 1 - FixCross = [fix(1)-1,fix(2)-20,fix(1)+1,fix(2)+20;fix(1)-20,fix(2)-1,fix(1)+20,fix(2)+1]; - Screen('FillRect', p.ptb.w, [255,255,255], FixCross'); - Eyelink('Message', 'FX Onset at %d %d',fix(1),fix(2)); - Screen('Flip',p.ptb.w,onsets(1),0); - StartEyelinkRecording(trialID,phase,cc(current_chain),tt,current_chain,isref(1),trial(1),delta_ref(1),delta_csp(1),abs_FGangle(1),fix(1),fix(2)); - - - %face trial(1) - Screen('DrawTexture',p.ptb.w,p.ptb.stim_sprites(trial(1))); - Screen('Flip',p.ptb.w,onsets(2),0); - - Eyelink('Message', 'Stim Onset'); - Eyelink('Message', 'SYNCTIME'); - while GetSecs < onsets(3) - end - Screen('Flip',p.ptb.w,onsets(3),0); - - StopEyelinkRecording; - %second face of the trial - trialID=trialID+1; - - - - %fixation cross 2 - FixCross = [fix(3)-1,fix(4)-20,fix(3)+1,fix(4)+20;fix(3)-20,fix(4)-1,fix(3)+20,fix(4)+1]; - Screen('FillRect', p.ptb.w, [255,255,255], FixCross'); - Eyelink('Message', 'FX Onset at %d %d',fix(3),fix(4)); - Screen('Flip',p.ptb.w,onsets(4),0); - StartEyelinkRecording(trialID,phase,cc(current_chain),tt,current_chain,isref(2),trial(2),delta_ref(2),delta_csp(2),abs_FGangle(2),fix(3),fix(4)); - - %face trial(2) - Screen('DrawTexture', p.ptb.w, p.ptb.stim_sprites(trial(2))); - Screen('Flip',p.ptb.w,onsets(5),0); - - Eyelink('Message', 'Stim Onset'); - Eyelink('Message', 'SYNCTIME'); - - while GetSecscross2onset->onset2shock->shock2offset - %these (duration.BLA) are average duration values: -% 1.5 0.5 0.5 - p.duration.stim = 0.6;%s - %p.duration.pink = 0.7;%0.7 - p.duration.fix = .85; - %p.duration.gray = 0; - if simulation_mode - p.duration.stim = .001;%s - p.duration.pink = .001; - p.duration.fix = .001; - %p.duration.gray = .001; - end - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - %create the randomized design - p.stim.cs_plus = csp_degree;%index of cs stimulus, this is the one paired to shock - %p.stim.cs_neg = csn; - - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %priors for the PSI fitting structure PM - - %% Define prior, these are always the same so defining once is enough. - p.psi.prioraaRange = linspace(0,169,50); %values of aa to include in prior - %IS THIS RANGE OF BETA VALUES REASONABLE? - p.psi.priorBetaRange = linspace(-2,0,50); %values of log_10(beta) to include in prior - %Range of lapse rates for the marginalized estimation of lambda - %Prins(2013) uses 0:0.01:0.1; - p.psi.priorLambdaRange = 0:0.01:0.05; - %Range of guess rates (Prins: 0:0.03:0.3); - p.psi.priorGammaRange = 0:0.03:0.3; - % Stimulus values to select from (need not be equally spaced) - p.psi.stimRange = 0:11.25:169; - %Function to be fitted during procedure - p.psi.PFfit = @PAL_CumulativeNormal; %Shape to be assumed - - %Termination after n Trials - p.psi.numtrials = 100; - % percentage of obligatory x=0 trials - p.psi.p0 = .2; - - %set up procedure - PM = []; - face_shift = [0 180 0 180]; - circle_shift = [0 0 360 360]; - circle_id = [1 1]*p.stim.tFace; - %circle_id = [1 1 2 2]*p.stim.tFace/2 % for 2 circles; - tchain = 2; - - - - - - - - - - - - %Save the stuff - save(p.path.path_param,'p'); - % - - end - function [rating]=RatingSlider(rect,tSection,position,up,down,confirm,labels,message1,message2,numbersOn) - % - %Detect the bounding boxes of the labels. - for nlab = 1:2 - [nx, ny, bb(nlab,:)]=DrawFormattedText(p.ptb.w,labels{nlab}, 'center', 'center', p.stim.white,[],[],[],2); - Screen('FillRect',p.ptb.w,p.stim.bg); - end - bb = max(bb); - bb_size = bb(3)-bb(1);%vertical size of the bb. - % - DrawSkala; - ok = 1; - while ok == 1 - [secs, keyCode, deltaSecs] = KbStrokeWait; - - keyCode = find(keyCode); - if (keyCode == up) | (keyCode == down) - next = position + increment(keyCode); - if next < (tSection+1) & next > 0 - position = position + increment(keyCode); - rating = tSection - position + 1; - end - DrawSkala; - elseif keyCode == confirm - WaitSecs(0.1); - ok = 0; - Screen('FillRect',p.ptb.w,p.stim.bg); - Screen('Flip',p.ptb.w); - end - end - - function DrawSkala - rating = tSection - position + 1; - increment([up down]) = [1 -1];%delta - tick_x = linspace(rect(1),rect(1)+rect(3),tSection+1);%tick positions - tick_size = rect(3)./tSection; - ss = tick_size/5*0.9;%slider size. - % - for tick = 1:length(tick_x)%draw ticks - Screen('DrawLine', p.ptb.w, [255 0 0], tick_x(tick), rect(2), tick_x(tick), rect(2)+rect(4) , 3); - if tick <= tSection && numbersOn - Screen('TextSize', p.ptb.w,p.text.fontsize./2); - DrawFormattedText(p.ptb.w, mat2str(tick) , tick_x(tick)+ss/2, rect(2)+rect(4), p.stim.white); - Screen('TextSize', p.ptb.w,p.text.fontsize); - end - if tick == 1 - DrawFormattedText(p.ptb.w, labels{1},tick_x(tick)-bb_size*1.6,rect(2), p.stim.white); - elseif tick == tSection+1 - DrawFormattedText(p.ptb.w, labels{2},tick_x(tick)+bb_size*0.2,rect(2), p.stim.white); - end - end - %slider coordinates - slider = [ tick_x(position)+tick_size*0.1 rect(2) tick_x(position)+tick_size*0.9 rect(2)+rect(4)]; - %draw the slider - Screen('FillRect',p.ptb.w, p.stim.white, round(slider)); - Screen('TextSize', p.ptb.w,p.text.fontsize); - DrawFormattedText(p.ptb.w,message1, 'center', p.ptb.midpoint(2)*0.2, p.stim.white,[],[],[],2); - Screen('TextSize', p.ptb.w,p.text.fontsize./2); - DrawFormattedText(p.ptb.w,message2, 'center', p.ptb.midpoint(2)*0.4, p.stim.white,[],[],[],2); - Screen('TextSize', p.ptb.w,p.text.fontsize); - Screen('Flip',p.ptb.w); - end - end - - function [shuffled,idx] = Shuffle(vector,N) - %takes first N from the SHUFFLED before outputting. This function - %could be used as a replacement for randsample - if nargin < 2;N = length(vector);end - [dummy, idx] = sort(rand([1 length(vector)])); - shuffled = vector(idx(1:N)); - shuffled = shuffled(:); - end - - function [a]=MinimumAngleQuartile(y,x) - %[a]=MinimumAngle(x,y); - % - %finds the minimum angle between two angles given in degrees, the answer is - %also in degrees. The clockwise distances from Y to X are considered as - %positive. Opposite angles are considered as positive 180. - - x = deg2rad(x); - y = deg2rad(y); - - a = atan2(sin(x-y), cos(x-y)); - - a = -round(((180/pi)*a)*4)/4; - - if any(abs(a) == 180); - a(abs(a) == 180) = 180; - end - end - - function ShowInstruction(nInstruct) - - [text]=GetText(nInstruct); - ShowText(text); - %let subject read it and ask confirmation to proceed. - - KbStrokeWait; - - Screen('FillRect',p.ptb.w,p.stim.bg); - Screen('Flip',p.ptb.w); - - end - function ShowText(text) - - - Screen('FillRect',p.ptb.w,p.stim.bg); - %DrawFormattedText(p.ptb.w, text, p.text.start_x, 'center',p.stim.white,[],[],[],2,[]); - DrawFormattedText(p.ptb.w, text, 'center', 'center',p.stim.white,[],[],[],2,[]); - Screen('Flip',p.ptb.w); - - %show the messages at the experimenter screen - fprintf([repmat('=',1,50) '\n']); - fprintf('Subject''s monitor:\n'); - fprintf(text); - fprintf([repmat('=',1,50) '\n']); - - end - - - function [text]=GetText(nInstruct) - - if nInstruct == 0%Eyetracking calibration - - text = ['Um Ihre Augenbewegungen zu messen, \n' ... - 'müssen wir jetzt den Eye-Tracker kalibrieren.\n' ... - 'Dazu zeigen wir Ihnen einige Punkte auf dem Bildschirm, \n' ... - 'bei denen Sie sich wie folgt verhalten:\n' ... - 'Bitte fixieren Sie das Fixationskreuz und \n' ... - 'bleiben Sie so lange darauf, wie es zu sehen ist.\n' ... - 'Bitte drücken Sie jetzt den mittleren Knopf, \n' ... - 'um mit der Kalibrierung weiterzumachen.\n' ... - ]; - - elseif nInstruct == 1 - text = ['Sie sehen nun nacheinander zwei Gesichter.\n'... - '\n'... - 'Danach werden Sie gefragt, ob die Gesichter unterschiedlich oder gleich waren.\n'... - '\n'... - 'Benutzen Sie dazu die Pfeiltasten (links, rechts) und die obere Taste zum Bestätigen.\n'... - '\n'... - 'Wenn Sie noch Fragen haben, können Sie jetzt die Versuchsleiterin fragen.\n'... - 'Wir können Sie jederzeit hören.\n'... - '\n'... - 'Drücken Sie ansonsten die mittlere Taste,\n'... - ' um das Experiment zu starten.\n' ... - ]; - elseif nInstruct == 3 - text = ['You will now see two faces after each other.\n'... - '\n'... - 'Please state, if they were different (left) or the same (right).\n'... - '\n'... - 'Use the arrow keys to move the marker and confirm with the UP button.\n'... - '\n'... - 'Please press UP\n'... - ' to start the experiment!\n' ... - ]; - elseif nInstruct == 2%end - text = 'Experiment beendet!\n'; - - elseif nInstruct==4%break - text = [sprintf('Sie haben bereits %g von %g Durchgängen geschafft!\n',tt-1,p.psi.numtrials*tchain)... - 'Machen Sie eine kurze Pause, lehnen Sie sich gern einen Moment zurück\n'... - 'und schließen Sie die Augen, um diese zu entspannen.\n'... - 'Drücken Sie anschließend die mittlere Taste, um weiterzumachen.\n']; - end - end - - function SetupLog(nc) - - - p.psi.log.globaltrial= NaN(nc,p.psi.numtrials); - p.psi.log.signal = NaN(nc,p.psi.numtrials); - p.psi.log.x = NaN(nc,p.psi.numtrials); - p.psi.log.refface = NaN(nc,p.psi.numtrials); - p.psi.log.testface = NaN(nc,p.psi.numtrials); - - p.psi.log.response = NaN(nc,p.psi.numtrials); - p.psi.log.alpha = NaN(nc,p.psi.numtrials); - p.psi.log.seAlpha = NaN(nc,p.psi.numtrials); - p.psi.log.beta = NaN(nc,p.psi.numtrials); - p.psi.log.seBeta = NaN(nc,p.psi.numtrials); - p.psi.log.gamma = NaN(nc,p.psi.numtrials); - p.psi.log.seGamma = NaN(nc,p.psi.numtrials); - p.psi.log.lambda = NaN(nc,p.psi.numtrials); - p.psi.log.seLambda = NaN(nc,p.psi.numtrials); - p.psi.log.xrounded = NaN(p.stim.tFace/tchain+1,p.psi.numtrials,nc); - p.psi.log.sdt = NaN(nc,p.psi.numtrials); - p.psi.log.trial_counter = zeros(p.stim.tFace/tchain+1,nc); - - - end - - function SetLog - - - p.psi.log.globaltrial(current_chain,cc(current_chain))= tt; - p.psi.log.signal(current_chain,cc(current_chain)) = signal; - p.psi.log.x(current_chain,cc(current_chain)) = PM{current_chain}.x(cc(current_chain))*direction; - p.psi.log.refface(current_chain,cc(current_chain)) = ref_face; - p.psi.log.testface(current_chain,cc(current_chain)) = test_face; - p.psi.log.response(current_chain,cc(current_chain)) = response; - p.psi.log.alpha(current_chain,cc(current_chain)) = PM{current_chain}.threshold(end); - p.psi.log.seAlpha(current_chain,cc(current_chain)) = PM{current_chain}.seThreshold(end); - p.psi.log.beta(current_chain,cc(current_chain)) = PM{current_chain}.slope(end); - p.psi.log.seBeta(current_chain,cc(current_chain)) = PM{current_chain}.seSlope(end); - p.psi.log.gamma(current_chain,cc(current_chain)) = PM{current_chain}.guess(end); - p.psi.log.seGamma(current_chain,cc(current_chain)) = PM{current_chain}.seGuess(end); - p.psi.log.lambda(current_chain,cc(current_chain)) = PM{current_chain}.lapse(end); - p.psi.log.seLambda(current_chain,cc(current_chain)) = PM{current_chain}.seLapse(end); - p.psi.log.sdt(current_chain,cc(current_chain)) = sdt;%1=hit 2=FA 3=miss 4=CR - - - end -% function PlotProcedure -% plotproc=figure(1); -% % title(sprintf('Threshold Estimation for subject %02d',tchain),'FontSize',14) -% for sub=1:tchain; -% subplot(2,2,sub) -% t = 1:length(p.log.x(sub)); -% hold on; -% plot(t,abs(p.log.x(sub)),'bo-'); -% errorbar(t,p.log.alpha(sub),p.log.seAlpha(sub),'r--') -% plot(t(p.log.response(sub) == 1),p.log.x(sub)(p.log.response(sub) == 1),'ko', ... -% 'MarkerFaceColor','k'); -% plot(t(p.log.response(sub) == 0),p.log.x(sub)(p.log.response(sub) == 0),'ko', ... -% 'MarkerFaceColor','w'); -% -% set(gca,'FontSize',12); -% axis([0 max(t)+1 0 max(p.log{sub}.alpha)+max(p.log{sub}.seAlpha)+20]) -% xlabel('Trial'); -% ylabel('xCurrent (Deg)'); -% -% end -% annotation('textbox', [0 0.9 1 0.1], 'String',... -% (sprintf('Threshold Estimation for subject %02d',tchain)), ... -% 'EdgeColor', 'none', ... -% 'HorizontalAlignment', 'center','FontSize',14) -% legend('xCurrent','estimated Threshold','Response = 1','Response = 0','Location','northeast'); -% -% % end -% function Plot_Fit -% plotfit=figure(2); -% for sub=1:tchain; -% subplot(2,2,sub) -% t = 1:length(p.log{sub}.x); -% hold on; -% plot(t,abs(p.log{sub}.x),'bo-'); -% errorbar(t,p.log{1}.alpha,p.log{1}.seAlpha,'r--') -% plot(t(p.log{sub}.response == 1),p.log{sub}.x(p.log{sub}.response == 1),'ko', ... -% 'MarkerFaceColor','k'); -% plot(t(p.log{sub}.response == 0),p.log{sub}.x(p.log{sub}.response == 0),'ko', ... -% 'MarkerFaceColor','w'); -% -% set(gca,'FontSize',12); -% axis([0 max(t)+1 0 max(p.log{sub}.alpha)+max(p.log{sub}.seAlpha)+20]) -% xlabel('Trial'); -% ylabel('xCurrent (Deg)'); -% -% end - -function [t]=StartEyelinkRecording(trialID,phase,cc,tt,current_chain,isref,file,delta_ref,delta_csp,abs_FGangle,fixx,fixy) - - t = []; - - - Eyelink('Message', 'TRIALID:%04d, PHASE:%04d, CHAIN:%04d, CHAINTRIAL:%04d, TTRIAL:%04d, ISREF:%04d, FILE:%04d, DELTAREF:%04d, DELTACSP:%04d, FGDEG:%04d, FXX:%04d, FXY:%04d',trialID, phase,... - current_chain, cc, tt, isref, file, delta_ref*100, delta_csp*100, abs_FGangle*100,fixx,fixy); - % an integration message so that an image can be loaded as - % overlay background when performing Data Viewer analysis. - WaitSecs(0.01); - Eyelink('Message', '!V IMGLOAD CENTER %s %d %d', p.stim.files(file,:), p.ptb.midpoint(1), p.ptb.midpoint(2)); - % This supplies the title at the bottom of the eyetracker display - Eyelink('Command', 'record_status_message "Stim: %d, Phase: %d"',file, phase); - % - %Put the tracker offline and draw the stimuli. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - % clear tracker display and draw box at center - Eyelink('Command', 'clear_screen %d', 0); - %draw the image on the screen - Eyelink('ImageTransfer',p.stim.files24(file,:),p.ptb.imrect(1),p.ptb.imrect(2),p.ptb.imrect(3),p.ptb.imrect(4),p.ptb.imrect(1),p.ptb.imrect(2)); - Eyelink('Command', 'draw_cross %d %d 15',fixx,fixy); - % - %drift correction - %EyelinkDoDriftCorrection(el,crosspositionx,crosspositiony,0,0); - %start recording following mode transition and a short pause. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('StartRecording'); - - t = GetSecs; - Log(t,8,NaN); -end - -function [t]=StopEyelinkRecording - - Eyelink('Message', 'Stim Offset'); - Eyelink('Message', 'BLANK_SCREEN'); - Eyelink('StopRecording'); - t = GetSecs; - %this is the end of the trial scope. - WaitSecs(0.01); - Eyelink('Message', 'TRIAL_RESULT 0'); - % - WaitSecs(0.01); - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('Command', 'clear_screen %d', 0); - - Log(t,-8,NaN); -end - -function InitEyeLink - % - if EyelinkInit(0)%use 0 to init normaly - fprintf('=================\nEyelink initialized correctly...\n') - else - fprintf('=================\nThere is problem in Eyelink initialization\n') - keyboard; - end - % - WaitSecs(0.5); - [~, vs] = Eyelink('GetTrackerVersion'); - fprintf('=================\nRunning experiment on a ''%s'' tracker.\n', vs ); - - %load 24bits pictures for eyelink... - dummy = dir([p.path.stim24 '*.bmp']); - p.stim.files24 = [repmat([fileparts(p.path.stim24) filesep],length(dummy),1) vertcat(dummy(:).name)]; -% for i=1:32 -% filename = p.stim.files24(nStim,:); -% [im , ~, ~] = imread(filename); -% end -% - % - el = EyelinkInitDefaults(p.ptb.w); - %update the defaults of the eyelink tracker - el.backgroundcolour = p.stim.bg; - el.msgfontcolour = WhiteIndex(el.window); - el.imgtitlecolour = WhiteIndex(el.window); - el.targetbeep = 0; - el.calibrationtargetcolour = WhiteIndex(el.window); - el.calibrationtargetsize = 1.5; - el.calibrationtargetwidth = 0.5; - el.displayCalResults = 1; - el.eyeimgsize = 50; - el.waitformodereadytime = 25;%ms - el.msgfont = 'Times New Roman'; - el.cal_target_beep = [0 0 0];%[1250 0.6 0.05]; - %shut all sounds off - el.drift_correction_target_beep = [0 0 0]; - el.calibration_failed_beep = [0 0 0]; - el.calibration_success_beep = [0 0 0]; - el.drift_correction_failed_beep = [0 0 0]; - el.drift_correction_success_beep= [0 0 0]; - EyelinkUpdateDefaults(el); - %PsychEyelinkDispatchCallback(el) - - % open file. - res = Eyelink('Openfile', p.path.edf); - if res == -3 - fprintf('File cannot be created!!!!\n'); - return; - end - % - Eyelink('command', 'add_file_preamble_text ''Recorded by EyelinkToolbox FearCloud Experiment'''); - Eyelink('command', 'screen_pixel_coords = %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - Eyelink('message', 'DISPLAY_COORDS %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - % set calibration type. - Eyelink('command', 'calibration_type = HV13'); - Eyelink('command','auto_calibration_messages = YES'); - Eyelink('command', 'select_parser_configuration = 1'); - %what do we want to record - Eyelink('command', 'file_sample_data = LEFT,RIGHT,GAZE,HREF,AREA,GAZERES,STATUS,INPUT,HTARGET'); - Eyelink('command', 'file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON,INPUT'); - Eyelink('command', 'use_ellipse_fitter = no'); - % set sample rate in camera setup screen - Eyelink('command', 'sample_rate = %d',1000); - end -function StopEyelink(filename) - try - fprintf('Trying to stop the Eyelink system with StopEyelink\n'); - Eyelink('StopRecording'); - WaitSecs(0.5); - Eyelink('Closefile'); - display('receiving the EDF file...'); - Eyelink('ReceiveFile',filename,[p.path.subject '\eye\'],1); - display('...finished!') - % Shutdown Eyelink: - Eyelink('Shutdown'); - catch - display('StopEyeLink routine didn''t really run well'); - end - end -function CalibrateEL - fprintf('=================\n=================\nEntering Eyelink Calibration\n') - p.var.ExpPhase = 0; - ShowInstruction(0); - EyelinkDoTrackerSetup(el); - %Returns 'messageString' text associated with result of last calibration - [~, messageString] = Eyelink('CalMessage'); - Eyelink('Message','%s',messageString);% - WaitSecs(0.05); - fprintf('=================\n=================\nNow we are done with the calibration\n') -end - - - -function Log(ptb_time, event_type, event_info) - %Phases: - %Pre-Experiment : 1 - %Post-Experiment : 2 -% %Instruction : 1 -% %Baseline : 2 -% %Conditioning : 3 -% %Test : 4 -% %Rating : 5 -% %Calibration : 0 - % - %event types are as follows: - % - %Scan Detection : 0 info: NaN; - %Cross Onset : 1 info: position - %Stimulus Onset/Offset: 2/-2 info: stim_id - %Cross Movement : 3 info: NaN; - %Stimulus Offset : -2 info: NaN; - %UCS Delivery : 4 info: NaN; - %Key Presses : 7 info: NaN; - %Tracker Onset/Offset : 8 info: NaN; - % - %Text on the screen : 5 info: Which Text? - %RatingScreen Onset : 6 info: NaN; - - p.var.event_count = p.var.event_count + 1; - p.out.log(p.var.event_count,:) = [ptb_time event_type event_info phase]; - % % p_out_log(p.out.event_counter,:) - %logstring([ 'Logged: ' mat2str(p_out_log(p.out.event_counter,:)) ' - Type: ' p.verbose.eventtype{abs(event_type)} ' - Phase: ' p.verbose.eventphase{CurrentExperimentalPhase}]) - %for i = 1:3;subplot(3,1,i);plot(p_out_log(1:p.out.event_counter ,i),'o-');drawnow;end - % - - end -function cleanup - - % Close window: - sca; - %set back the old resolution - if strcmp(p.hostname,'triostim1') - Screen('Resolution',p.ptb.screenNumber, p.ptb.oldres.width, p.ptb.oldres.height ); - %show the cursor - ShowCursor(p.ptb.screenNumber); - end - % -% %IOPort('ConfigureSerialPort', p.com.serial,' StopBackgroundRead'); -% %IOPort('Close',p.com.serial); -% commandwindow; -% ListenChar(0); -% KbQueueRelease(p_ptb_device); -end - -end diff --git a/exp_feargen_PFfitting_YN_laptop.m b/exp_feargen_PFfitting_YN_laptop.m deleted file mode 100644 index 22d945a..0000000 --- a/exp_feargen_PFfitting_YN_laptop.m +++ /dev/null @@ -1,962 +0,0 @@ -function [p]=exp_feargen_PFfitting_YN_laptop(subject,phase,csp_degree) - -% Diskrimination Task estimating the Threshold alpha and Slope beta of an -% observer's underlying Psychometric Function (PF). -% Enter the subject Number as well as the CS+ Face in Degrees (where 00 is -% 1st face, and so) -simulation_mode = 0; -ncircle=1; - -ListenChar(2);%disable pressed keys to be spitted around -commandwindow; -%clear everything -clear mex global functions -cgshut; -global cogent; -%%%%%%%%%%%load the GETSECS mex files so call them at least once -GetSecs; -WaitSecs(0.001); - -el = []; -p = []; -SetParams; -SetPTB; - -%InitEyeLink; -WaitSecs(2); -%calibrate if we are at the scanner computer. -if strcmp(p.hostname,'triostim1') || strcmp(p.hostname,'etpc'); - CalibrateEL; -end - -%save again the parameter file -save(p.path.path_param,'p'); - -% make a break every ....th Trial -breakpoint=50; - - -% counter for within chain trials (cc) and global trials (tt) -cc=zeros(1,tchain); -tt=0; - - -for nc = 1:tchain -%set up procedure -PM{nc} = PAL_AMPM_setupPM('priorAlphaRange',p.psi.prioraaRange,'priorBetaRange',... - p.psi.priorBetaRange, 'priorLambdaRange', p.psi.priorLambdaRange,'priorGammaRange',... - p.psi.priorGammaRange,'numtrials',p.psi.numtrials, 'PF' , p.psi.PFfit, 'stimRange',p.psi.stimRange,... - 'marginalize', [3 4]); - -% -PM{nc}.reference_face = face_shift(nc); -PM{nc}.reference_circle = circle_shift(nc); -if p.psi.p0 ~= 0 - -shuffledummy=Shuffle(1:p.psi.numtrials); -p.psi.zerotrials(:,nc)=shuffledummy(1:ceil(p.psi.numtrials*p.psi.p0)); -end -% set up Log Variable -SetupLog(nc); -end - -ShowInstruction(1); - -OK = 1; -while OK - - current_chain = PsychRandSample(1:tchain,[1 1]); - - - if PM{current_chain}.stop ~= 1 - tt=tt+1; - % enter in break loop - if (tt~=1 && mod(tt,breakpoint)==1 && simulation_mode==0); - ShowInstruction(4); - ShowInstruction(1); - %CalibrateEL; - end - cc(current_chain)=cc(current_chain)+1; - fprintf('Chain %4.2f , Trial %02d\n',current_chain,cc(current_chain)) - fprintf('Original PM.x: %4.2f \n',PM{current_chain}.x(cc(current_chain))) - % manually force x=0 trial, if it fits the zerotrial condition - if p.psi.p0 ~= 0 - if any(p.psi.zerotrials(:,current_chain)==cc(current_chain)) - fprintf('Forcing x=0 Trial...\n') - PM{current_chain}.xCurrent=0; - PM{current_chain}.x(cc(current_chain))=0; - - end - end - fprintf('PM.x is now %4.2f \n',PM{current_chain}.x(cc(current_chain))) - - %Present trial here at stimulus intensity PM.xCurrent and collect - %response - direction = PsychRandSample([-1 1],[1 1]); - test = PM{current_chain}.xCurrent * direction + PM{current_chain}.reference_face + csp_degree + PM{current_chain}.reference_circle; - dummy = test; - % the computed degree has to stay in the same circle: - % whenever it goes left from the 00 degrees (360 at foreign), - % there's a problem - % for chain 1 and 2, values below 0 have to be shifted 360 degrees, - % for chain 3 and 4, values below 360 have to be shifted 360 degrees - % e.g., -45 has to be 315 in chain 1; 315 has to be 675 in chain 3 - % was done using mod... adding (0 0 360 360) (this is the last part) - test = mod(test,360)+ PM{current_chain}.reference_circle; - - % the reference is one of the four faces - %(cs+ local, cs- local, cs+ foreign, cs- forein) - ref = PM{current_chain}.reference_face + csp_degree + PM{current_chain}.reference_circle; - ref = mod(ref,360)+ PM{current_chain}.reference_circle; - - % fprintf('Chain: %03d\nxCurrent: %6.2f\nDirection:%6.2f\n %6.2f -> %6.2f vs. %6.2f\n',current_chain,PM{current_chain}.xCurrent,direction,dummy,test,ref); - % start Trial - fprintf('Starting Trial %03d/%03d.\n',tt,tchain*p.psi.numtrials) - - [test_face, ref_face, signal] = Trial_YN(ref,test,circle_id(current_chain),tt); - - fprintf('Rating.\n') - %Rating Slider - % - message1 = 'Waren die Gesichter unterschiedlich oder gleich?\n'; - message2 = 'Bewege den "Zeiger" mit der rechten und linken Pfeiltaste\n und bestätige deine Einschätzung mit der oberen Pfeiltaste.'; - if ~simulation_mode - [response_subj] = RatingSlider(p.ptb.rect,2,Shuffle(1:2,1),p.keys.increase,p.keys.decrease,p.keys.confirm,{ 'unterschiedlich' 'gleich'},message1,message2,0); - - % see if subject found the different pair of faces... - % buttonpress left (Yes) is response_subj=2, right alternative (No) outputs a 1. - if (response_subj == 2 && signal == 1) - response=1; -% fprintf('...Hit. \n') - elseif (response_subj==1 && signal == 1) - response=0; -% fprintf('...Miss. \n') - elseif (response_subj == 2 && signal==0) - response=1; -% fprintf('...False Alarm. \n') - elseif (response_subj == 1 && signal == 0) - response=0; -% fprintf('...Correct Rejection. \n') - else -% fprintf('error in the answer algorithm! \n') - end - - else - true_a = 45; - true_s = 10; - true_g = 0.2; - true_l = 0.02; - response = ObserverResponseFunction(p.psi.PFfit,true_a,1/true_s,true_g,true_l,PM{current_chain}.xCurrent); - - - - end - - - - % store everything in the Log - row = round(PM{current_chain}.xCurrent/p.stim.delta+1); - p.psi.log.trial_counter(row,current_chain) = p.psi.log.trial_counter(row,current_chain) + 1; - p.psi.log.xrounded(row,p.psi.log.trial_counter(row,current_chain),current_chain) = response; - - - %updating PM - PM{current_chain} = PAL_AMPM_updatePM(PM{current_chain},response); - SetLog; - %iteration control - dummy = cell2mat(PM); - OK = sum([dummy(:).stop]) ~= tchain; - end - - - %save Logfile here - - %save([p.path.path_param 'Log' num2str(subject) '.mat'],'p.psi.log'); - - %save again the parameter file - save(p.path.path_param,'p'); - -end -ShowInstruction(2); -%Print summary of results to screen -for chain=1:tchain -fprintf('Chain %g: Estimated Threshold (alpha): %4.2f \n',chain,PM{chain}.threshold(end)); -fprintf('Chain %g: Estimated Slope (beta): %4.2f \n',chain,PM{chain}.slope(end)); -end - -%get the eyelink file back to this computer -%StopEyelink(p.path.edf); - - -%save([p.path.dropbox 'Log' num2str(subject) '.mat'],'p.psi.log') -% save PF Fit Plot -%feargenET_PFfitting_Fitplot(num2str(subject),p.log) - - -%clear the screen -%close everything down -cleanup; -%move the folder to appropriate location -movefile(p.path.subject,p.path.finalsubject); - - - - function [test_face, ref_face, signal] = Trial_YN(ref_stim,test_stim,last_face_of_circle,tt) - % computes the trial FACES, using the test/ref information input - % values (in Deg) - - trial = [ref_stim test_stim]/p.stim.delta; - % correct face number within circle - trial = mod(round(trial),last_face_of_circle)+1; - ref_face = trial(1); - test_face = trial(2); - trial = Shuffle(trial); - %compute if trial had different faces or not - %if trial(1)=trial(2), they were the same and subject has to - %answer with 'no' (right option, is 1), else means correct hit - - if trial(1)==trial(2) - signal = 0; - else - signal = 1; - end - - % %create two pink noise textures -% pink_noise = Image2PinkNoise(p.stim.stim(:,:,trial(1))); -% pink_noise = repmat((pink_noise-mean(pink_noise(:))).*p.ptb.tw+mean(pink_noise(:)),[1 1 3]); -% p.ptb.stim_sprites(p.stim.tFile+1) = Screen('MakeTexture', p.ptb.w, pink_noise); -% pink_noise = Image2PinkNoise(p.stim.stim(:,:,trial(2))); -% pink_noise = repmat((pink_noise-mean(pink_noise(:))).*p.ptb.tw+mean(pink_noise(:)),[1 1 3]); -% p.ptb.stim_sprites(p.stim.tFile+2) = Screen('MakeTexture', p.ptb.w, pink_noise); - %%sprite_index = [pink_noise FixationCross trial(1) FixationCross pink_noise trial(2) NaN]; - - %get fixation crosses and onsets from p parameter - fix = round(p.ptb.CrossPositions(tt,:)); - - %StartEyelinkRecording(tt,phase,trial(1),fix(1),fix(2)); - - %GetSecs so that the onsets can be defined - onsets = p.trial.onsets + GetSecs; -% %pink_noise 1 -% -% Screen('DrawTexture', p.ptb.w,p.ptb.stim_sprites(p.stim.tFile+1)); -% Eyelink('Message', 'Pink Noise 1 Onset'); -% Screen('Flip',p.ptb.w,onsets(1),0); - - %fixation cross 1 - Screen('DrawText', p.ptb.w, double('+'),fix(1),fix(2), p.stim.white); -%Eyelink('Message', 'FX 1 Onset at %d %d',fix(1),fix(2)); - Screen('Flip',p.ptb.w,onsets(1),0); - - %face trial(1) - Screen('DrawTexture',p.ptb.w,p.ptb.stim_sprites(trial(1))); -% Eyelink('Message', 'Stim 1 Onset'); - Screen('Flip',p.ptb.w,onsets(2),0); - -%StopEyelinkRecording; - - %second face of the trial -%StartEyelinkRecording(tt,phase,trial(2),fix(3),fix(4)); -% %pink_noise 2 -% Screen('DrawTexture', p.ptb.w, p.ptb.stim_sprites(p.stim.tFile+2)); -% Eyelink('Message', 'Pink Noise 2 Onset'); -% Screen('Flip',p.ptb.w,onsets(4),0); - - %fixation cross 2 - Screen('DrawText', p.ptb.w, double('+'), fix(3),fix(4), p.stim.white); -%Eyelink('Message', 'FX Onset 2 at %d %d',fix(3),fix(4)); - Screen('Flip',p.ptb.w,onsets(3),0); - - %face trial(2) - Screen('DrawTexture', p.ptb.w, p.ptb.stim_sprites(trial(2))); -%Eyelink('Message', 'Stim 2 Onset'); - Screen('Flip',p.ptb.w,onsets(4),0); - while GetSecscross2onset->onset2shock->shock2offset - %these (duration.BLA) are average duration values: -% 1.5 0.5 0.5 - p.duration.stim = 1.5;%s - p.duration.fix = 0.85; - %p.duration.gray = .1; - if simulation_mode - p.duration.stim = .001;%s - p.duration.pink = .001; - p.duration.fix = .001; - %p.duration.gray = .001; - end - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - %create the randomized design - p.stim.cs_plus = csp_degree;%index of cs stimulus, this is the one paired to shock - %p.stim.cs_neg = csn; - -% -% event_onsets = 0.15; -% event_onsets = [event_onsets event_onsets(end)+p.duration.pink]; -% event_onsets = [event_onsets event_onsets(end)+p.duration.fix]; -% event_onsets = [event_onsets event_onsets(end)+p.duration.stim]; -% event_onsets = [event_onsets event_onsets(end)+p.duration.pink]; -% event_onsets = [event_onsets event_onsets(end)+p.duration.fix]; -% event_onsets = [event_onsets event_onsets(end)+p.duration.stim]; -% %event_onsets = [event_onsets event_onsets(end)+p.duration.gray]; - - event_onsets = 0.15; - event_onsets = [event_onsets event_onsets(end)+p.duration.fix]; - event_onsets = [event_onsets event_onsets(end)+p.duration.stim]; - event_onsets = [event_onsets event_onsets(end)+p.duration.fix]; - event_onsets = [event_onsets event_onsets(end)+p.duration.stim]; - %event_onsets = [event_onsets event_onsets(end)+p.duration.gray]; - - p.trial.onsets = event_onsets; -% p.out.rating = []; -% p.out.log = zeros(p.psi.numtrials*4,4).*NaN; - - - - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %priors for the PSI fitting structure PM - - %% Define prior, these are always the same so defining once is enough. - p.psi.prioraaRange = linspace(0,100,50); %values of aa to include in prior - %IS THIS RANGE OF BETA VALUES REASONABLE? - p.psi.priorBetaRange = linspace(-2,0,50); %values of log_10(beta) to include in prior - %Range of lapse rates for the marginalized estimation of lambda - %Prins(2013) uses 0:0.01:0.1; - p.psi.priorLambdaRange = 0:0.01:0.05; - %Range of guess rates (Prins: 0:0.03:0.3); - p.psi.priorGammaRange = 0:0.03:0.3; - % Stimulus values to select from (need not be equally spaced) - p.psi.stimRange = 0:11.25:100; - %Function to be fitted during procedure - p.psi.PFfit = @PAL_CumulativeNormal; %Shape to be assumed - - %Termination after n Trials - p.psi.numtrials = 50; - % percentage of obligatory x=0 trials - p.psi.p0 = .2; - - %set up procedure - PM = []; - face_shift = [0 180 0 180]; - circle_shift = [0 0 360 360]; - circle_id = [1 1 2 2]*p.stim.tFace/2; - tchain = 2; - ncircle=1; - - - - - - - - - - - - %Save the stuff - save(p.path.path_param,'p'); - % - - end - function [rating]=RatingSlider(rect,tSection,position,up,down,confirm,labels,message1,message2,numbersOn) - % - %Detect the bounding boxes of the labels. - for nlab = 1:2 - [nx, ny, bb(nlab,:)]=DrawFormattedText(p.ptb.w,labels{nlab}, 'center', 'center', p.stim.white,[],[],[],2); - Screen('FillRect',p.ptb.w,p.stim.bg); - end - bb = max(bb); - bb_size = bb(3)-bb(1);%vertical size of the bb. - % - DrawSkala; - ok = 1; - while ok == 1 - [secs, keyCode, deltaSecs] = KbStrokeWait; - - keyCode = find(keyCode); - if (keyCode == up) | (keyCode == down) - next = position + increment(keyCode); - if next < (tSection+1) & next > 0 - position = position + increment(keyCode); - rating = tSection - position + 1; - end - DrawSkala; - elseif keyCode == confirm - WaitSecs(0.1); - ok = 0; - Screen('FillRect',p.ptb.w,p.stim.bg); - Screen('Flip',p.ptb.w); - end - end - - function DrawSkala - rating = tSection - position + 1; - increment([up down]) = [1 -1];%delta - tick_x = linspace(rect(1),rect(1)+rect(3),tSection+1);%tick positions - tick_size = rect(3)./tSection; - ss = tick_size/5*0.9;%slider size. - % - for tick = 1:length(tick_x)%draw ticks - Screen('DrawLine', p.ptb.w, [255 0 0], tick_x(tick), rect(2), tick_x(tick), rect(2)+rect(4) , 3); - if tick <= tSection && numbersOn - Screen('TextSize', p.ptb.w,p.text.fontsize./2); - DrawFormattedText(p.ptb.w, mat2str(tick) , tick_x(tick)+ss/2, rect(2)+rect(4), p.stim.white); - Screen('TextSize', p.ptb.w,p.text.fontsize); - end - if tick == 1 - DrawFormattedText(p.ptb.w, labels{1},tick_x(tick)-bb_size*1.6,rect(2), p.stim.white); - elseif tick == tSection+1 - DrawFormattedText(p.ptb.w, labels{2},tick_x(tick)+bb_size*0.2,rect(2), p.stim.white); - end - end - %slider coordinates - slider = [ tick_x(position)+tick_size*0.1 rect(2) tick_x(position)+tick_size*0.9 rect(2)+rect(4)]; - %draw the slider - Screen('FillRect',p.ptb.w, p.stim.white, round(slider)); - Screen('TextSize', p.ptb.w,p.text.fontsize); - DrawFormattedText(p.ptb.w,message1, 'center', p.ptb.midpoint(2)*0.2, p.stim.white,[],[],[],2); - Screen('TextSize', p.ptb.w,p.text.fontsize./2); - DrawFormattedText(p.ptb.w,message2, 'center', p.ptb.midpoint(2)*0.4, p.stim.white,[],[],[],2); - Screen('TextSize', p.ptb.w,p.text.fontsize); - Screen('Flip',p.ptb.w); - end - end - - function shuffled = Shuffle(vector,N) - %takes first N from the SHUFFLED before outputting. This function - %could be used as a replacement for randsample - if nargin < 2;N = length(vector);end - [dummy, idx] = sort(rand([1 length(vector)])); - shuffled = vector(idx(1:N)); - shuffled = shuffled(:); - end - - function ShowInstruction(nInstruct) - - [text]=GetText(nInstruct); - ShowText(text); - %let subject read it and ask confirmation to proceed. - - KbStrokeWait; - - Screen('FillRect',p.ptb.w,p.stim.bg); - Screen('Flip',p.ptb.w); - - end - function ShowText(text) - - - Screen('FillRect',p.ptb.w,p.stim.bg); - %DrawFormattedText(p.ptb.w, text, p.text.start_x, 'center',p.stim.white,[],[],[],2,[]); - DrawFormattedText(p.ptb.w, text, 'center', 'center',p.stim.white,[],[],[],2,[]); - Screen('Flip',p.ptb.w); - - %show the messages at the experimenter screen - fprintf([repmat('=',1,50) '\n']); - fprintf('Subject''s monitor:\n'); - fprintf(text); - fprintf([repmat('=',1,50) '\n']); - - end - - - function [text]=GetText(nInstruct) - - if nInstruct == 0%Eyetracking calibration - - text = ['Um Deine Augenbewegungen zu messen, \n' ... - 'müssen wir jetzt den Eye-Tracker kalibrieren.\n' ... - 'Dazu zeigen wir Dir einige Punkte auf dem Bildschirm, \n' ... - 'bei denen Du Dich wie folgt verhältst:\n' ... - 'Bitte fixiere das Fixationskreuz und \n' ... - 'bleibe so lange darauf, wie es zu sehen ist.\n' ... - 'Bitte drücke jetzt den mittleren Knopf, \n' ... - 'um mit der Kalibrierung weiterzumachen.\n' ... - ]; - - elseif nInstruct == 1 - text = ['Du siehst nun nacheinander zwei Gesichter.\n'... - '\n'... - 'Danach wirst Du gefragt, ob die Gesichter unterschiedlich oder gleich waren.\n'... - '\n'... - 'Benutze dazu die Pfeiltasten (links, rechts) und die obere Taste zum Bestätigen.\n'... - '\n'... - 'Wenn du noch Fragen hast, kannst du jetzt den Versuchsleiter fragen.\n'... - '\n'... - 'Drücke ansonsten die mittlere Taste,\n'... - ' um das Experiment zu starten.\n' ... - ]; - elseif nInstruct == 3 - text = ['You will now see two faces after each other.\n'... - '\n'... - 'Please state, if they were different (left) or the same (right).\n'... - '\n'... - 'Use the arrow keys to move the marker and confirm with the UP button.\n'... - '\n'... - 'Please press UP\n'... - ' to start the experiment!\n' ... - ]; - elseif nInstruct == 2%end - text = 'Experiment beendet!\n'; - - elseif nInstruct==4%break - text = [sprintf('Du hast bereits %g von %g Durchgängen geschafft!\n',tt-1,p.psi.numtrials*tchain)... - 'Mache eine kurze Pause, aber halte Deinen Kopf in der gleichen Position!\n'... - 'Drücke anschließend die mittlere Taste, um weiterzumachen.\n']; - end - end - - function SetupLog(nc) - - - p.psi.log.globaltrial= NaN(nc,p.psi.numtrials); - p.psi.log.signal = NaN(nc,p.psi.numtrials); - p.psi.log.x = NaN(nc,p.psi.numtrials); - p.psi.log.refface = NaN(nc,p.psi.numtrials); - p.psi.log.testface = NaN(nc,p.psi.numtrials); - - p.psi.log.response = NaN(nc,p.psi.numtrials); - p.psi.log.alpha = NaN(nc,p.psi.numtrials); - p.psi.log.seAlpha = NaN(nc,p.psi.numtrials); - p.psi.log.beta = NaN(nc,p.psi.numtrials); - p.psi.log.seBeta = NaN(nc,p.psi.numtrials); - p.psi.log.gamma = NaN(nc,p.psi.numtrials); - p.psi.log.seGamma = NaN(nc,p.psi.numtrials); - p.psi.log.lambda = NaN(nc,p.psi.numtrials); - p.psi.log.seLambda = NaN(nc,p.psi.numtrials); - p.psi.log.xrounded = NaN(p.stim.tFace/tchain+1,p.psi.numtrials,nc); - p.psi.log.trial_counter = zeros(p.stim.tFace/tchain+1,nc); - - end - - function SetLog - - - p.psi.log.globaltrial(current_chain,cc(current_chain))= tt; - p.psi.log.signal(current_chain,cc(current_chain)) = signal; - p.psi.log.x(current_chain,cc(current_chain)) = PM{current_chain}.x(cc(current_chain))*direction; - p.psi.log.refface(current_chain,cc(current_chain)) = ref_face; - p.psi.log.testface(current_chain,cc(current_chain)) = test_face; - p.psi.log.response(current_chain,cc(current_chain)) = response; - p.psi.log.alpha(current_chain,cc(current_chain)) = PM{current_chain}.threshold(end); - p.psi.log.seAlpha(current_chain,cc(current_chain)) = PM{current_chain}.seThreshold(end); - p.psi.log.beta(current_chain,cc(current_chain)) = PM{current_chain}.slope(end); - p.psi.log.seBeta(current_chain,cc(current_chain)) = PM{current_chain}.seSlope(end); - p.psi.log.gamma(current_chain,cc(current_chain)) = PM{current_chain}.guess(end); - p.psi.log.seGamma(current_chain,cc(current_chain)) = PM{current_chain}.seGuess(end); - p.psi.log.lambda(current_chain,cc(current_chain)) = PM{current_chain}.lapse(end); - p.psi.log.seLambda(current_chain,cc(current_chain)) = PM{current_chain}.seLapse(end); - - - end -% function PlotProcedure -% plotproc=figure(1); -% % title(sprintf('Threshold Estimation for subject %02d',tchain),'FontSize',14) -% for sub=1:tchain; -% subplot(2,2,sub) -% t = 1:length(p.log.x(sub)); -% hold on; -% plot(t,abs(p.log.x(sub)),'bo-'); -% errorbar(t,p.log.alpha(sub),p.log.seAlpha(sub),'r--') -% plot(t(p.log.response(sub) == 1),p.log.x(sub)(p.log.response(sub) == 1),'ko', ... -% 'MarkerFaceColor','k'); -% plot(t(p.log.response(sub) == 0),p.log.x(sub)(p.log.response(sub) == 0),'ko', ... -% 'MarkerFaceColor','w'); -% -% set(gca,'FontSize',12); -% axis([0 max(t)+1 0 max(p.log{sub}.alpha)+max(p.log{sub}.seAlpha)+20]) -% xlabel('Trial'); -% ylabel('xCurrent (Deg)'); -% -% end -% annotation('textbox', [0 0.9 1 0.1], 'String',... -% (sprintf('Threshold Estimation for subject %02d',tchain)), ... -% 'EdgeColor', 'none', ... -% 'HorizontalAlignment', 'center','FontSize',14) -% legend('xCurrent','estimated Threshold','Response = 1','Response = 0','Location','northeast'); -% -% % end -% function Plot_Fit -% plotfit=figure(2); -% for sub=1:tchain; -% subplot(2,2,sub) -% t = 1:length(p.log{sub}.x); -% hold on; -% plot(t,abs(p.log{sub}.x),'bo-'); -% errorbar(t,p.log{1}.alpha,p.log{1}.seAlpha,'r--') -% plot(t(p.log{sub}.response == 1),p.log{sub}.x(p.log{sub}.response == 1),'ko', ... -% 'MarkerFaceColor','k'); -% plot(t(p.log{sub}.response == 0),p.log{sub}.x(p.log{sub}.response == 0),'ko', ... -% 'MarkerFaceColor','w'); -% -% set(gca,'FontSize',12); -% axis([0 max(t)+1 0 max(p.log{sub}.alpha)+max(p.log{sub}.seAlpha)+20]) -% xlabel('Trial'); -% ylabel('xCurrent (Deg)'); -% -% end - -function [t]=StartEyelinkRecording(tt,phase,trialface,fixx,fixy) - t = []; - - Eyelink('Message', 'Trial: %03d, Phase: %02d, Face: %d ,FX %d,%d', tt, phase, trialface, fixx,fixy); - % an integration message so that an image can be loaded as - % overlay background when performing Data Viewer analysis. - WaitSecs(0.01); - Eyelink('Message', '!V IMGLOAD CENTER %s %d %d', p.stim.files(trialface,:), p.ptb.midpoint(1), p.ptb.midpoint(2)); - % This supplies the title at the bottom of the eyetracker display - Eyelink('Command', 'record_status_message "Stim: %d, Phase: %d"',trialface, phase); - % - %Put the tracker offline and draw the stimuli. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - % clear tracker display and draw box at center - Eyelink('Command', 'clear_screen %d', 0); - %draw the image on the screen - Eyelink('ImageTransfer',p.stim.files24(trialface,:),p.ptb.imrect(1),p.ptb.imrect(2),p.ptb.imrect(3),p.ptb.imrect(4),p.ptb.imrect(1),p.ptb.imrect(2)); - - %Eyelink('Command', 'draw_cross %d %d',fix(1),fix(2)) - % - %drift correction - %EyelinkDoDriftCorrection(el,crosspositionx,crosspositiony,0,0); - %start recording following mode transition and a short pause. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('StartRecording'); - Screen('Textsize', p.ptb.w,p.text.fixationsize); - t = GetSecs; - Log(t,8,NaN); -end - -function [t]=StopEyelinkRecording - Eyelink('StopRecording'); - - t = GetSecs; - %this is the end of the trial scope. - WaitSecs(0.01); - Eyelink('Message', 'TRIAL_RESULT 0'); - % - WaitSecs(0.01); - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('Command', 'clear_screen %d', 0); - Screen('Textsize', p.ptb.w,p.text.fontsize); - Log(t,-8,NaN); -end - -function InitEyeLink - % - if EyelinkInit(0)%use 0 to init normaly - fprintf('=================\nEyelink initialized correctly...\n') - else - fprintf('=================\nThere is problem in Eyelink initialization\n') - keyboard; - end - % - WaitSecs(0.5); - [~, vs] = Eyelink('GetTrackerVersion'); - fprintf('=================\nRunning experiment on a ''%s'' tracker.\n', vs ); - - %load 24bits pictures for eyelink... - dummy = dir([p.path.stim24 '*.bmp']); - p.stim.files24 = [repmat([fileparts(p.path.stim24) filesep],length(dummy),1) vertcat(dummy(:).name)]; -% for i=1:32 -% filename = p.stim.files24(nStim,:); -% [im , ~, ~] = imread(filename); -% end -% - % - el = EyelinkInitDefaults(p.ptb.w); - %update the defaults of the eyelink tracker - el.backgroundcolour = p.stim.bg; - el.msgfontcolour = WhiteIndex(el.window); - el.imgtitlecolour = WhiteIndex(el.window); - el.targetbeep = 0; - el.calibrationtargetcolour = WhiteIndex(el.window); - el.calibrationtargetsize = 1.5; - el.calibrationtargetwidth = 0.5; - el.displayCalResults = 1; - el.eyeimgsize = 50; - el.waitformodereadytime = 25;%ms - el.msgfont = 'Times New Roman'; - el.cal_target_beep = [0 0 0];%[1250 0.6 0.05]; - %shut all sounds off - el.drift_correction_target_beep = [0 0 0]; - el.calibration_failed_beep = [0 0 0]; - el.calibration_success_beep = [0 0 0]; - el.drift_correction_failed_beep = [0 0 0]; - el.drift_correction_success_beep= [0 0 0]; - EyelinkUpdateDefaults(el); - %PsychEyelinkDispatchCallback(el) - - % open file. - res = Eyelink('Openfile', p.path.edf); - % - Eyelink('command', 'add_file_preamble_text ''Recorded by EyelinkToolbox FearGen2 Experiment'''); - Eyelink('command', 'screen_pixel_coords = %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - Eyelink('message', 'DISPLAY_COORDS %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - % set calibration type. - Eyelink('command', 'calibration_type = HV13'); - Eyelink('command', 'select_parser_configuration = 1'); - %what do we want to record - Eyelink('command', 'file_sample_data = LEFT,RIGHT,GAZE,HREF,AREA,GAZERES,STATUS,INPUT,HTARGET'); - Eyelink('command', 'file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON,INPUT'); - Eyelink('command', 'use_ellipse_fitter = no'); - % set sample rate in camera setup screen - Eyelink('command', 'sample_rate = %d',1000); - end -function StopEyelink(filename) - try - fprintf('Trying to stop the Eyelink system with StopEyelink\n'); - Eyelink('StopRecording'); - WaitSecs(0.5); - Eyelink('Closefile'); - display('receiving the EDF file...'); - Eyelink('ReceiveFile',filename,[p.path.subject '\eye\'],1); - display('...finished!') - % Shutdown Eyelink: - Eyelink('Shutdown'); - catch - display('StopEyeLink routine didn''t really run well'); - end - end -function CalibrateEL - fprintf('=================\n=================\nEntering Eyelink Calibration\n') - p.var.ExpPhase = 0; - ShowInstruction(0); - EyelinkDoTrackerSetup(el); - %Returns 'messageString' text associated with result of last calibration - [~, messageString] = Eyelink('CalMessage'); - Eyelink('Message','%s',messageString);% - WaitSecs(0.05); - fprintf('=================\n=================\nNow we are done with the calibration\n') -end - - -function Log(ptb_time, event_type, event_info) - %Phases: - %Pre-Experiment : 1 - %Post-Experiment : 2 -% %Instruction : 1 -% %Baseline : 2 -% %Conditioning : 3 -% %Test : 4 -% %Rating : 5 -% %Calibration : 0 - % - %event types are as follows: - % - %Scan Detection : 0 info: NaN; - %Cross Onset : 1 info: position - %Stimulus Onset/Offset: 2/-2 info: stim_id - %Cross Movement : 3 info: NaN; - %Stimulus Offset : -2 info: NaN; - %UCS Delivery : 4 info: NaN; - %Key Presses : 7 info: NaN; - %Tracker Onset/Offset : 8 info: NaN; - % - %Text on the screen : 5 info: Which Text? - %RatingScreen Onset : 6 info: NaN; - - p.var.event_count = p.var.event_count + 1; - p.out.log(p.var.event_count,:) = [ptb_time event_type event_info phase]; - % % p_out_log(p.out.event_counter,:) - %logstring([ 'Logged: ' mat2str(p_out_log(p.out.event_counter,:)) ' - Type: ' p.verbose.eventtype{abs(event_type)} ' - Phase: ' p.verbose.eventphase{CurrentExperimentalPhase}]) - %for i = 1:3;subplot(3,1,i);plot(p_out_log(1:p.out.event_counter ,i),'o-');drawnow;end - % - - end -function cleanup - - % Close window: - sca; - %set back the old resolution - if strcmp(p.hostname,'triostim1') - Screen('Resolution',p.ptb.screenNumber, p.ptb.oldres.width, p.ptb.oldres.height ); - %show the cursor - ShowCursor(p.ptb.screenNumber); - end - % -% %IOPort('ConfigureSerialPort', p.com.serial,' StopBackgroundRead'); -% %IOPort('Close',p.com.serial); -% commandwindow; -% ListenChar(0); -% KbQueueRelease(p_ptb_device); -end - -end diff --git a/exp_painThreshold_laptop.m b/exp_painThreshold_laptop.m deleted file mode 100644 index e41967e..0000000 --- a/exp_painThreshold_laptop.m +++ /dev/null @@ -1,403 +0,0 @@ -function [p]=PainThreshold(subject,INITLEVEL,varargin) - -clear mex global functions -cgshut; -if ~isempty(varargin) - debug = varargin{1}; -else - debug = 0; -end -global cogent; -% -p = []; -log_threshold =[]; -%0 -SetParams; -SetPTB; -SCRCheck; -GetThreshold; -save(p.path.filename,'p'); -%%now give the subject a final shock with the "tobeused level" and ask -%%whether it is bearable. -%factor = input('Enter the desired factor (for example 1.4). Start with the highest :).\n'); -%ConfirmIntensity(factor); -save(p.path.filename,'p'); -% -ShowInstruction(6); - -%move the file to its final location. -movefile(p.path.subject,p.path.finalsubject); -cleanup; - - - function GetThreshold - - %message to show on the rating screen. - message = 'War der Reiz schmerzhaft oder nicht?\nBewege den "Zeiger" mit der rechten und linken Pfeiltaste\n und bestätige deine Einschätzung mit der mit der oberen Pfeiltaste.'; - % - p.threshold.init.alphas = log(0.1):0.177/100:log(50); - p.threshold.init.prior = PAL_pdfNormal(p.threshold.init.alphas, log(3), log(2.5)); - p.threshold.init.stopcriterion = 'trials'; - p.threshold.init.stoprule = 12; - p.threshold.init.PFfit = @PAL_Gumbel; - p.threshold.init.beta = 3.5; - p.threshold.init.lambda = 0; - p.threshold.init.gamma = 0; - p.threshold.init.meanmode = 'mode'; - p.threshold.final.factor = [1.2 1.3 1.4]; - % - p.threshold.RF = PAL_AMRF_setupRF('priorAlphaRange', p.threshold.init.alphas, 'prior', p.threshold.init.prior,... - 'stopCriterion',p.threshold.init.stopcriterion,'stoprule',p.threshold.init.stoprule,'beta',p.threshold.init.beta,'gamma',p.threshold.init.gamma,... - 'lambda',p.threshold.init.lambda,'PF',p.threshold.init.PFfit,'meanmode',p.threshold.init.meanmode); - % - p.threshold.RF.xCurrent = log(INITLEVEL);%start shock; - % - response_mapping = [1 0]; - ShowInstruction(4); - % - counter = 0; - close all; - while ~p.threshold.RF.stop - % - counter = counter + 1; - fprintf([repmat('=',1,50) '\n']); - fprintf('SHOCK No: %d of %d.\n',counter,p.threshold.init.stoprule); - fprintf('!!! ADJUST THE SHOCK INTENSITY ON THE DIGITIMER !!!\n'); - fprintf(' The intensity is now: %g\n',exp(p.threshold.RF.xCurrent)); - fprintf(' Experimenter: Press any key to deliver a shock.\n'); - fprintf(' Or escape to quit prematurely.\n'); - fprintf([repmat('=',1,50) '\n']); - % - [secs, keyCode, deltaSecs] = KbStrokeWait; - if find(keyCode ) == p.keys.esc - p.threshold.RF.stop = 1; - else - ShowInstruction(5);%shock is coming message, stays ~2 sec... - %prepare for the shock - t = GetSecs + p.duration.shock; - while GetSecs < t; - Buzz; - end - %Ask for rating - [response] = RatingSlider(p.ptb.rect,2,Shuffle(1:2,1),p.keys.increase,p.keys.decrease,p.keys.confirm,{ 'nicht\nschmerzhaft' 'schmerzhaft'},message,0); - response = response_mapping(response); - % - response = logical(response); - amplitude = p.threshold.RF.xCurrent; - p.threshold.RF = PAL_AMRF_updateRF(p.threshold.RF, amplitude, response); - % - plot(p.threshold.RF.priorAlphaRange,p.threshold.RF.pdf,'r') - drawnow; -% % % RF = p.threshold.RF; -% % % figure(1);set(gcf,'position',[940 770 360 206]) -% % % x = 1:length(RF.x); -% % % plot(x,exp(RF.x),'o-'); -% % % hold on; -% % % plot(x(RF.response == 1),exp(RF.x(RF.response == 1)),'.-') -% % % drawnow -% % % figure(2);set(gcf,'position',[941 485 361 212]) -% % % plot(x,log(exp(RF.x)),'o-'); -% % % hold on; -% % % plot(x(RF.response == 1),log(exp(RF.x(RF.response == 1))),'.-') -% % % drawnow -% % % figure(3) -% % % set(gcf,'position',[940 294 362 115]) -% % % %plot(exp(alphas),RF.pdf,'r'); - end - end - log_threshold = p.threshold.RF.(p.threshold.init.meanmode); - p.threshold.final.estimated = exp(log_threshold); - - fprintf('\n\n\nRESULT:\n'); - fprintf('The estimated pain threshold : %g mA\n',p.threshold.final.estimated); - fprintf('Choose an intensity:\n'); - fprintf('Intensity to be used for factor x 1.2): %g mA\n',exp(log_threshold.*p.threshold.final.factor(1))); - fprintf('Intensity to be used for factor x 1.3): %g mA\n',exp(log_threshold.*p.threshold.final.factor(2))); - fprintf('Intensity to be used for factor x 1.4): %g mA\n',exp(log_threshold.*p.threshold.final.factor(3))); - fprintf('We will now ask whether this is bearable...\n'); - end - function ConfirmIntensity(factor) - % - if log_threshold > 0 - I = exp(log_threshold*factor); - else - I = exp(log_threshold*(1-factor)); - end - % - ShowInstruction(1); - % - fprintf([repmat('=',1,50) '\n']); - fprintf('TEST SHOCK:\n'); - fprintf('!!! ADJUST THE SHOCK INTENSITY ON THE DIGITIMER !!!\n'); - fprintf(' The intensity is now: %g mA\n',I); - fprintf(' Experimenter: Press any key to deliver a shock.\n'); - fprintf([repmat('=',1,50) '\n']); - % - [secs, keyCode, deltaSecs] = KbStrokeWait; - ShowInstruction(5);%shock is coming message... - t = GetSecs + p.duration.shock; - while GetSecs < t; - Buzz; - end - % - message = 'Bewege den "Zeiger" mit der rechten und linken Pfeiltaste\n und bestätige deine Einschätzung mit der mit der oberen Pfeiltaste.'; - [p.threshold.confirmation.response] = RatingSlider(p.ptb.rect,2,1,p.keys.increase,p.keys.decrease,p.keys.confirm,{ 'nicht\nerträglich' 'erträglich'},message,0); - if p.threshold.confirmation.response == 1 - fprintf('All is fine :)\n'); - fprintf('Subject confirmed the shock intensity...\n') - fprintf('INTENSITY TO BE USED FOR THE MAIN EXPERIMENT: %g mA\n',I); - p.threshold.final.tobeused = I; - return; - elseif p.threshold.confirmation.response == 2 - fprintf('Shit... :(, %g is too much for the subject\n',I); - fprintf('We will try a little milder intensity.\n'); - factor = factor - 0.05; - ConfirmIntensity(factor); - end - - - end - function SetParams - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %relative path to stim and experiments - %Path Business. - p.path.baselocation = 'C:\Users\onat\Documents\Experiments\'; - p.path.experiment = [p.path.baselocation 'PainThreshold\']; - % - p.name = subject; - timestamp = datestr(now,30); - p.path.subject = [p.path.experiment 'data\tmp\' p.name '_' timestamp '\']; - p.path.finalsubject = [p.path.experiment 'data\' p.name '_' timestamp ]; - mkdir(p.path.subject); - p.path.filename = [regexprep(p.path.subject,'\\','\\\') 'param.mat' ]; - %font size and background gray level - p.text.fontname = 'Times New Roman'; - p.text.fontsize = 30; - %where to place text on the screen; - p.text.start_x = 60; - p.textstart_y = 275; - % - p.stim.bg = [0.47 0.47 0.47]*255;%background color - p.stim.bg_rating = [0 0.47 0].*255; - p.stim.white = [255 255 255]; - p.stim.crossy = 30;%crosshair position - % - p.size_RatingScale = 200;%size of the rating scale in pixels. The actual size is 2x. - %All settings for laptop computer. - p.keys.confirm = KbName('up'); - p.keys.increase = KbName('right'); - p.keys.decrease = KbName('left'); - p.keys.space = KbName('space'); - p.keys.esc = KbName('esc'); - %parallel port - p.lpt.address = 888; - p.lpt.US = 255; - p.lpt.shut = 0; - p.lpt.stim = 1; - p.lpt.fixation = 2; - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %timing business - p.duration.shock = 0.1;%s;x - p.duration.shockpulse = 0.005;%ms; duration of each individual pulses - p.duration.intershockpulse = 0.01;%ms; and the time between each pulse - - % - %Save the stuff - save(p.path.filename,'p'); - end - - - function [rating]=RatingSlider(rect,tSection,position,up,down,confirm,labels,message,numbersOn) - % - %Detect the bounding boxes of the labels. - for nlab = 1:2 - [nx ny bb(nlab,:)]=DrawFormattedText(p.ptb.w,labels{nlab}, 'center', 'center', p.stim.white,[],[],[],2); - Screen('FillRect',p.ptb.w,p.stim.bg); - end - bb = max(bb); - bb_size = bb(3)-bb(1);%vertical size of the bb. - % - DrawSkala; - ok = 1; - while ok == 1 - [secs, keyCode, deltaSecs] = KbStrokeWait; - - keyCode = find(keyCode); - if (keyCode == up) | (keyCode == down) - next = position + increment(keyCode); - if next < (tSection+1) & next > 0 - position = position + increment(keyCode); - rating = tSection - position + 1; - end - DrawSkala; - elseif keyCode == confirm - WaitSecs(0.1); - ok = 0; - Screen('FillRect',p.ptb.w,p.stim.bg); - Screen('Flip',p.ptb.w); - end - end - - function DrawSkala - rating = tSection - position + 1; - increment([up down]) = [1 -1];%delta - tick_x = linspace(rect(1),rect(1)+rect(3),tSection+1);%tick positions - tick_size = rect(3)./tSection; - ss = tick_size/5*0.9;%slider size. - % - for tick = 1:length(tick_x)%draw ticks - Screen('DrawLine', p.ptb.w, [255 0 0], tick_x(tick), rect(2), tick_x(tick), rect(2)+rect(4) , 3); - if tick <= tSection && numbersOn - Screen('TextSize', p.ptb.w,p.text.fontsize./2); - DrawFormattedText(p.ptb.w, mat2str(tick) , tick_x(tick)+ss/2, rect(2)+rect(4), p.stim.white); - Screen('TextSize', p.ptb.w,p.text.fontsize); - end - if tick == 1 - DrawFormattedText(p.ptb.w, labels{1},tick_x(tick)-bb_size*1.2,rect(2), p.stim.white); - elseif tick == tSection+1 - DrawFormattedText(p.ptb.w, labels{2},tick_x(tick)+bb_size*0.2,rect(2), p.stim.white); - end - end - %slider coordinates - slider = [ tick_x(position)+tick_size*0.1 rect(2) tick_x(position)+tick_size*0.9 rect(2)+rect(4)]; - %draw the slider - Screen('FillRect',p.ptb.w, p.stim.white, round(slider)); - Screen('TextSize', p.ptb.w,p.text.fontsize./2); - DrawFormattedText(p.ptb.w,message, 'center', p.ptb.midpoint(2)*0.2, p.stim.white,[],[],[],2); - Screen('TextSize', p.ptb.w,p.text.fontsize); - Screen('Flip',p.ptb.w); - end - end - function ShowInstruction(nInstruct) - - [text]=GetText(nInstruct); - ShowText(text); - %let subject read it and ask confirmation to proceed. But we don't - %need that in the case of INSTRUCT = 5; - if nInstruct == 5 %this is for the Reiz kommnt - WaitSecs(0.5+rand(1)); - elseif nInstruct == 6 - WaitSecs(3); - else - KbStrokeWait; - end - Screen('FillRect',p.ptb.w,p.stim.bg); - Screen('Flip',p.ptb.w); - function ShowText(text) - - - Screen('FillRect',p.ptb.w,p.stim.bg); - %DrawFormattedText(p.ptb.w, text, p.text.start_x, 'center',p.stim.white,[],[],[],2,[]); - DrawFormattedText(p.ptb.w, text, 'center', 'center',p.stim.white,[],[],[],2,[]); - Screen('Flip',p.ptb.w); - - %show the messages at the experimenter screen - fprintf([repmat('=',1,50) '\n']); - fprintf('Subject''s monitor:\n'); - fprintf(text); - fprintf([repmat('=',1,50) '\n']); - - end - function [text]=GetText(nInstruct); - if nInstruct == 1%Baseline Phase - %=================================================================================================================% - text = ['Gib bitte an ob die Reizstärke des folgenden Schocks\nfür dich erträglich ist.\n'... - '\n'... - 'Drücke bitte die mittlere Taste um den Reiz zu bekommen.\n'... - ]; - - - elseif nInstruct == 4%shock calibration - text = ['Wir werden nun deine Schmerzschwelle bestimmen.\n'... - '\n'... - 'Dafür wirst du mehrere (~10) elektrische Reize bekommen.\n' ... - '\n'... - 'Bitte gib jeweils nach jedem Reiz an, ob er schmerzhaft war oder nicht.\n'... - '\n'... - 'Wenn du noch fragen hast, kannst du jetzt den Versuchsleiter fragen.\n'... - '\n'... - 'Drücke ansonsten die mittlere Taste,\n'... - ' um das Experiment fortzusetzen.\n' ... - ]; - elseif nInstruct == 5%just before the shock - text = ['Reiz kommt...\n']; - elseif nInstruct == 6%transition. - - text = ['Damit ist dieser Teil zu Ende.\n' ... - '\n'... - 'Wir machen nun mit der nächsten Phase weiter.\n'... - ]; - - else - text = {''}; - end - end - end - function SetPTB - %Open a graphics window using PTB - screens = Screen('Screens'); - screenNumber = max(screens); - %make everything transparent for debuggin purposes. - if debug - commandwindow; - PsychDebugWindowConfiguration; - end - Screen('Preference', 'SkipSyncTests', 1); - Screen('Preference', 'DefaultFontSize', p.text.fontsize); - Screen('Preference', 'DefaultFontName', p.text.fontname); - % - [p.ptb.w ] = Screen('OpenWindow', screenNumber, p.stim.bg); - [p.ptb.width, p.ptb.height] = Screen('WindowSize', screenNumber); - %find the mid position. - p.ptb.midpoint = [ p.ptb.width./2 p.ptb.height./2]; - %area of the slider - p.ptb.rect = [p.ptb.midpoint(1)*0.5 p.ptb.midpoint(2)*0.8 p.ptb.midpoint(1) p.ptb.midpoint(2)*0.2]; - %compute the cross position. - [nx ny bb] = DrawFormattedText(p.ptb.w,'+','center','center'); - Screen('FillRect',p.ptb.w,p.stim.bg); - p.ptb.cross_shift = [45 50];%upper and lower cross positions - p.ptb.CrossPosition_y = [ny-p.ptb.cross_shift(1) ny+p.ptb.cross_shift(2) ]; - p.ptb.CrossPosition_x = [bb(1) bb(1)]; - p.ptb.CrossPositionET_x = [p.ptb.midpoint(1) p.ptb.midpoint(1)]; - p.ptb.CrossPositionET_y = [p.ptb.midpoint(2)-p.ptb.cross_shift(2) p.ptb.midpoint(2)+p.ptb.cross_shift(2)]; - % - Priority(MaxPriority(p.ptb.w)); - %prepare parallel port communication. This relies on cogent i - %think. - config_io64; - outp64(p.lpt.address,0); - if( cogent.io.status ~= 0 ) - error('inp/outp installation failed'); - end - end - function shuffled = Shuffle(vector,N) - %takes first N from the SHUFFLED before outputting. This function - %could be used as a replacement for randsample - if nargin < 2;N = length(vector);end - [dummy, idx] = sort(rand([1 length(vector)])); - shuffled = vector(idx(1:N)); - shuffled = shuffled(:); - end - function Buzz - - outp64(p.lpt.address, p.lpt.US ); - WaitSecs(p.duration.shockpulse); - outp64(p.lpt.address, 0); - WaitSecs(p.duration.intershockpulse); - - end - function cleanup - % Close window: - sca; - commandwindow; - end - function SCRCheck - fprintf([repmat('!',1,50) '\n']); - fprintf([repmat('!',1,50) '\n']); - fprintf([repmat('!',1,50) '\n']); - fprintf('Did you TURN ON the SCR ????\n Press a key to continue...\n'); - KbStrokeWait; - end -end diff --git a/exp_plapil_PFfitting_YN.m b/exp_plapil_PFfitting_YN.m deleted file mode 100644 index 520d4ab..0000000 --- a/exp_plapil_PFfitting_YN.m +++ /dev/null @@ -1,1003 +0,0 @@ -function [p]=exp_plapil_PFfitting_YN(subject,phase,csp_degree) - -% Diskrimination Task estimating the Threshold alpha and Slope beta of an -% observer's underlying Psychometric Function (PF). -% Enter the subject Number as well as the CS+ Face in Degrees (where 00 is -% 1st face, and so) -simulation_mode = 0; -ncircle=1; - -ListenChar(2);%disable pressed keys to be spitted around -commandwindow; -%clear everything -clear mex global functions -cgshut; -global cogent; -%%%%%%%%%%%load the GETSECS mex files so call them at least once -GetSecs; -WaitSecs(0.001); - -el = []; -p = []; -SetParams; -SetPTB; - -InitEyeLink; -WaitSecs(2); -%calibrate if we are at the scanner computer. -if strcmp(p.hostname,'triostim1') || strcmp(p.hostname,'etpc'); - CalibrateEL; -end - -%save again the parameter file -save(p.path.path_param,'p'); - -% make a break every ....th Trial -breakpoint=50; - - -% counter for within chain trials (cc) and global trials (tt) -cc=zeros(1,tchain); -tt=0; -%trialID is counting every single face (2 per Trial_YN), need that for -%Eyelink -trialID=0; - - -for nc = 1:tchain -%set up procedure -PM{nc} = PAL_AMPM_setupPM('priorAlphaRange',p.psi.prioraaRange,'priorBetaRange',... - p.psi.priorBetaRange, 'priorLambdaRange', p.psi.priorLambdaRange,'priorGammaRange',... - p.psi.priorGammaRange,'numtrials',p.psi.numtrials, 'PF' , p.psi.PFfit, 'stimRange',p.psi.stimRange,... - 'marginalize', [3 4]); - -% -PM{nc}.reference_face = face_shift(nc); -PM{nc}.reference_circle = circle_shift(nc); -if p.psi.p0 ~= 0 - -shuffledummy=Shuffle(1:p.psi.numtrials); -p.psi.zerotrials(:,nc)=shuffledummy(1:ceil(p.psi.numtrials*p.psi.p0)); -end -% set up Log Variable -SetupLog(nc); -end - -ShowInstruction(1); - -OK = 1; -while OK - - current_chain = RandSample(1:tchain,[1 1]); - - - if PM{current_chain}.stop ~= 1 - tt=tt+1; - % enter in break loop - if (tt~=1 && mod(tt,breakpoint)==1 && simulation_mode==0); - save(p.path.path_param,'p'); - memory - ShowInstruction(4); - CalibrateEL; - end - cc(current_chain)=cc(current_chain)+1; - fprintf('Chain %4.2f , Trial %02d\n',current_chain,cc(current_chain)) - fprintf('Original PM.x: %4.2f \n',PM{current_chain}.x(cc(current_chain))) - % manually force x=0 trial, if it fits the zerotrial condition - if p.psi.p0 ~= 0 - if any(p.psi.zerotrials(:,current_chain)==cc(current_chain)) - fprintf('Forcing x=0 Trial...\n') - PM{current_chain}.xCurrent = 11.25; - PM{current_chain}.x(cc(current_chain)) = 11.25; - - end - end - - - %Present trial here at stimulus intensity PM.xCurrent and collect - %response - direction = RandSample([-1 1],[1 1]); - fprintf('PM.x is now %4.2f \n',direction*PM{current_chain}.x(cc(current_chain))) - test = PM{current_chain}.xCurrent * direction + PM{current_chain}.reference_face + csp_degree + PM{current_chain}.reference_circle; - dummy = test; - % the computed degree has to stay in the same circle: - % whenever it goes left from the 00 degrees (360 at foreign), - % there's a problem - % for chain 1 and 2, values below 0 have to be shifted 360 - % degrees, - % for chain 3 and 4, values below 360 have to be shifted 360 degrees - % e.g., -45 has to be 315 in chain 1; 315 has to be 675 in chain 3 - % was done using mod... adding (0 0 360 360) (this is the last part) - test = mod(test,360)+ PM{current_chain}.reference_circle; - - % the reference is one of the four faces - %(cs+ local, cs- local, cs+ foreign, cs- forein) - ref = PM{current_chain}.reference_face + csp_degree + PM{current_chain}.reference_circle; - ref = mod(ref,360)+ PM{current_chain}.reference_circle; - - % fprintf('Chain: %03d\nxCurrent: %6.2f\nDirection:%6.2f\n %6.2f -> %6.2f vs. %6.2f\n',current_chain,PM{current_chain}.xCurrent,direction,dummy,test,ref); - % start Trial - fprintf('Starting Trial %03d/%03d.\n',tt,tchain*p.psi.numtrials) - - [test_face, ref_face, signal,trialID] = Trial_YN(trialID,ref,test,circle_id(current_chain),tt); - - fprintf('Rating.\n') - Screen('Textsize', p.ptb.w,p.text.fontsize); - %Rating Slider - % - message1 = 'Waren die Muster unterschiedlich oder gleich?\n'; - message2 = 'Bewege den "Zeiger" mit der rechten und linken Pfeiltaste\n und bestätige deine Einschätzung mit der oberen Pfeiltaste.'; - if ~simulation_mode - [response_subj] = RatingSlider(p.ptb.rect,2,Shuffle(1:2,1),p.keys.increase,p.keys.decrease,p.keys.confirm,{ 'unterschiedlich' 'gleich'},message1,message2,0); - - % see if subject found the different pair of faces... - % buttonpress left (Yes) is response_subj=2, right alternative (No) outputs a 1. - % note that response=1 only means "yes", and not correct or anything - sdt=NaN; - if (response_subj == 2 && signal == 1) - response=1; - fprintf('...Hit. \n') - sdt=1; - elseif (response_subj==1 && signal == 1) - response=0; - fprintf('...Miss. \n') - sdt=3; - elseif (response_subj == 2 && signal==0) - response=1; - fprintf('...False Alarm. \n') - sdt=2; - elseif (response_subj == 1 && signal == 0) - response=0; - fprintf('...Correct Rejection. \n') - sdt=4; - else - fprintf('error in the answer algorithm! \n') - end - - else - true_a = 45; - true_s = 3; - true_g = 0.2; - true_l = 0.02; -% response = ObserverResponseFunction(p.psi.PFfit,true_a,1/true_s,true_g,true_l,PM{current_chain}.xCurrent); - response = round(rand(1)); - sdt = 1; - - - end - - - - % store everything in the Log - row = round(PM{current_chain}.xCurrent/p.stim.delta+1); - p.psi.log.trial_counter(row,current_chain) = p.psi.log.trial_counter(row,current_chain) + 1; - p.psi.log.xrounded(row,p.psi.log.trial_counter(row,current_chain),current_chain) = response; - - - %updating PM - PM{current_chain} = PAL_AMPM_updatePM(PM{current_chain},response); - fprintf('Estimated Threshold after trial %d: %g \n',tt,PM{current_chain}.threshold(end)) - SetLog; - %iteration control - dummy = cell2mat(PM); - OK = sum([dummy(:).stop]) ~= tchain; - end - - - %save Logfile here - - %save([p.path.path_param 'Log' num2str(subject) '.mat'],'p.psi.log'); - - %save again the parameter file - save(p.path.path_param,'p'); - -end -%end of Experiment, shown to subject -ShowInstruction(2); -%Print summary of results to screen -for chain=1:tchain -fprintf('Chain %g: Estimated Threshold (alpha): %4.2f \n',chain,PM{chain}.threshold(end)); -fprintf('Chain %g: Estimated Slope (beta): %4.2f \n',chain,PM{chain}.slope(end)); -end - -%get the eyelink file back to this computer -StopEyelink(p.path.edf); - - -%save([p.path.dropbox 'Log' num2str(subject) '.mat'],'p.psi.log') -% save PF Fit Plot -%feargenET_PFfitting_Fitplot(num2str(subject),p.log) - - -%clear the screen -%close everything down -cleanup; -%move the folder to appropriate location -movefile(p.path.subject,p.path.finalsubject); - - - - function [test_face,ref_face,signal,trialID] = Trial_YN(trialID,ref_stim,test_stim,last_face_of_circle,tt) - Screen('Textsize', p.ptb.w,p.text.fixsize); - % computes the trial FACES, using the test/ref information input - % values (in Deg) - - trial = [ref_stim test_stim]/p.stim.delta; - % correct face number within circle - trial = mod(round(trial),last_face_of_circle)+1; - ref_face = trial(1); - test_face = trial(2); - [trial,idx]= Shuffle(trial); - fprintf('Faces: %d %d \n',trial(1),trial(2)); - %compute if trial had different faces or not - %if trial(1)=trial(2), they were the same and subject has to - %answer with 'no' (right option, is 1), else means correct hit - - if trial(1)==trial(2) - signal = 0; - else - signal = 1; - end - - - trial_deg = [ref_stim test_stim]; - isref=double(trial==ref_face) ; - delta_ref = MinimumAngleQuartile([trial_deg(idx(1)) trial_deg(idx(2))],ref); - delta_csp = MinimumAngleQuartile([trial_deg(idx(1)) trial_deg(idx(2))],csp_degree); % ... - abs_FGangle = [trial_deg(idx(1)) trial_deg(idx(2))]; - - - %get fixation crosses and onsets from p parameter - fix = round(p.ptb.CrossPositions(tt,:)); - - - - trialID=trialID+1; - - - %GetSecs so that the onsets can be defined - - onsets = 0.25+GetSecs;%fix1 onset - onsets = [onsets onsets(end)+p.duration.fix+rand(1)*.25];%stim1 onset - onsets = [onsets onsets(end)+p.duration.stim];%stim1 offset - fixdelta=p.duration.fix+rand(1)*.25; - onsets = [onsets onsets(end)+1.5-fixdelta];%fix2 onset - onsets = [onsets onsets(end)+fixdelta];%stim2 onset - onsets = [onsets onsets(end)+p.duration.stim];%stim2 offset - - - - - %fixation cross 1 - FixCross = [fix(1)-1,fix(2)-20,fix(1)+1,fix(2)+20;fix(1)-20,fix(2)-1,fix(1)+20,fix(2)+1]; - Screen('FillRect', p.ptb.w, [255,255,255], FixCross'); - Eyelink('Message', 'FX Onset at %d %d',fix(1),fix(2)); - Screen('Flip',p.ptb.w,onsets(1),0); - StartEyelinkRecording(trialID,phase,cc(current_chain),tt,current_chain,isref(1),trial(1),delta_ref(1),delta_csp(1),abs_FGangle(1),fix(1),fix(2)); - - - %face trial(1) - Screen('DrawTexture',p.ptb.w,p.ptb.stim_sprites(trial(1))); - Screen('Flip',p.ptb.w,onsets(2),0); - - Eyelink('Message', 'Stim Onset'); - Eyelink('Message', 'SYNCTIME'); - while GetSecs < onsets(3) - end - Screen('Flip',p.ptb.w,onsets(3),0); - - StopEyelinkRecording; - %second face of the trial - trialID=trialID+1; - - - - %fixation cross 2 - FixCross = [fix(3)-1,fix(4)-20,fix(3)+1,fix(4)+20;fix(3)-20,fix(4)-1,fix(3)+20,fix(4)+1]; - Screen('FillRect', p.ptb.w, [255,255,255], FixCross'); - Eyelink('Message', 'FX Onset at %d %d',fix(3),fix(4)); - Screen('Flip',p.ptb.w,onsets(4),0); - StartEyelinkRecording(trialID,phase,cc(current_chain),tt,current_chain,isref(2),trial(2),delta_ref(2),delta_csp(2),abs_FGangle(2),fix(3),fix(4)); - - %face trial(2) - Screen('DrawTexture', p.ptb.w, p.ptb.stim_sprites(trial(2))); - Screen('Flip',p.ptb.w,onsets(5),0); - - Eyelink('Message', 'Stim Onset'); - Eyelink('Message', 'SYNCTIME'); - - while GetSecscross2onset->onset2shock->shock2offset - %these (duration.BLA) are average duration values: -% 1.5 0.5 0.5 - p.duration.stim = 1.0;%s - %p.duration.pink = 0.7;%0.7 - p.duration.fix = .85; - %p.duration.gray = 0; - if simulation_mode - p.duration.stim = .001;%s - p.duration.pink = .001; - p.duration.fix = .001; - %p.duration.gray = .001; - end - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - %create the randomized design - p.stim.cs_plus = csp_degree;%index of cs stimulus, this is the one paired to shock - %p.stim.cs_neg = csn; - - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %priors for the PSI fitting structure PM - - %% Define prior, these are always the same so defining once is enough. - p.psi.prioraaRange = linspace(1,170,50); %values of aa to include in prior - %IS THIS RANGE OF BETA VALUES REASONABLE? - p.psi.priorBetaRange = linspace(.1,10,50); %values of beta to include in prior - %Range of lapse rates for the marginalized estimation of lambda - %Prins(2013) uses 0:0.01:0.1; - p.psi.priorLambdaRange = 0:0.01:0.1; - %Range of guess rates (Prins: 0:0.03:0.3); - p.psi.priorGammaRange = 0:0.03:0.3; - % Stimulus values to select from (need not be equally spaced) - p.psi.stimRange = 0:11.25:169; - %Function to be fitted during procedure - p.psi.PFfit = @PAL_Weibull; %Shape to be assumed - - %Termination after n Trials - p.psi.numtrials = 100; - % percentage of obligatory x=0 trials - p.psi.p0 = .2; - - %set up procedure - PM = []; - face_shift = [0 180 0 180]; - circle_shift = [0 0 360 360]; - circle_id = [1 1]*p.stim.tFace; - %circle_id = [1 1 2 2]*p.stim.tFace/2 % for 2 circles; - tchain = 2; - - - %Save the stuff - save(p.path.path_param,'p'); - % - - end - function [rating]=RatingSlider(rect,tSection,position,up,down,confirm,labels,message1,message2,numbersOn) - % - %Detect the bounding boxes of the labels. - for nlab = 1:2 - [nx, ny, bb(nlab,:)]=DrawFormattedText(p.ptb.w,labels{nlab}, 'center', 'center', p.stim.white,[],[],[],2); - Screen('FillRect',p.ptb.w,p.stim.bg); - end - bb = max(bb); - bb_size = bb(3)-bb(1);%vertical size of the bb. - % - DrawSkala; - ok = 1; - while ok == 1 - [secs, keyCode, deltaSecs] = KbStrokeWait; - - keyCode = find(keyCode); - if (keyCode == up) | (keyCode == down) - next = position + increment(keyCode); - if next < (tSection+1) & next > 0 - position = position + increment(keyCode); - rating = tSection - position + 1; - end - DrawSkala; - elseif keyCode == confirm - WaitSecs(0.1); - ok = 0; - Screen('FillRect',p.ptb.w,p.stim.bg); - Screen('Flip',p.ptb.w); - end - end - - function DrawSkala - rating = tSection - position + 1; - increment([up down]) = [1 -1];%delta - tick_x = linspace(rect(1),rect(1)+rect(3),tSection+1);%tick positions - tick_size = rect(3)./tSection; - ss = tick_size/5*0.9;%slider size. - % - for tick = 1:length(tick_x)%draw ticks - Screen('DrawLine', p.ptb.w, [255 0 0], tick_x(tick), rect(2), tick_x(tick), rect(2)+rect(4) , 3); - if tick <= tSection && numbersOn - Screen('TextSize', p.ptb.w,p.text.fontsize./2); - DrawFormattedText(p.ptb.w, mat2str(tick) , tick_x(tick)+ss/2, rect(2)+rect(4), p.stim.white); - Screen('TextSize', p.ptb.w,p.text.fontsize); - end - if tick == 1 - DrawFormattedText(p.ptb.w, labels{1},tick_x(tick)-bb_size*1.6,rect(2), p.stim.white); - elseif tick == tSection+1 - DrawFormattedText(p.ptb.w, labels{2},tick_x(tick)+bb_size*0.2,rect(2), p.stim.white); - end - end - %slider coordinates - slider = [ tick_x(position)+tick_size*0.1 rect(2) tick_x(position)+tick_size*0.9 rect(2)+rect(4)]; - %draw the slider - Screen('FillRect',p.ptb.w, p.stim.white, round(slider)); - Screen('TextSize', p.ptb.w,p.text.fontsize); - DrawFormattedText(p.ptb.w,message1, 'center', p.ptb.midpoint(2)*0.2, p.stim.white,[],[],[],2); - Screen('TextSize', p.ptb.w,p.text.fontsize./2); - DrawFormattedText(p.ptb.w,message2, 'center', p.ptb.midpoint(2)*0.4, p.stim.white,[],[],[],2); - Screen('TextSize', p.ptb.w,p.text.fontsize); - Screen('Flip',p.ptb.w); - end - end - - function [shuffled,idx] = Shuffle(vector,N) - %takes first N from the SHUFFLED before outputting. This function - %could be used as a replacement for randsample - if nargin < 2;N = length(vector);end - [dummy, idx] = sort(rand([1 length(vector)])); - shuffled = vector(idx(1:N)); - shuffled = shuffled(:); - end - - function [a]=MinimumAngleQuartile(y,x) - %[a]=MinimumAngle(x,y); - % - %finds the minimum angle between two angles given in degrees, the answer is - %also in degrees. The clockwise distances from Y to X are considered as - %positive. Opposite angles are considered as positive 180. - - x = deg2rad(x); - y = deg2rad(y); - - a = atan2(sin(x-y), cos(x-y)); - - a = -round(((180/pi)*a)*4)/4; - - if any(abs(a) == 180); - a(abs(a) == 180) = 180; - end - end - - function ShowInstruction(nInstruct) - - [text]=GetText(nInstruct); - ShowText(text); - %let subject read it and ask confirmation to proceed. - - KbStrokeWait; - - Screen('FillRect',p.ptb.w,p.stim.bg); - Screen('Flip',p.ptb.w); - - end - function ShowText(text) - - - Screen('FillRect',p.ptb.w,p.stim.bg); - %DrawFormattedText(p.ptb.w, text, p.text.start_x, 'center',p.stim.white,[],[],[],2,[]); - DrawFormattedText(p.ptb.w, text, 'center', 'center',p.stim.white,[],[],[],2,[]); - Screen('Flip',p.ptb.w); - - %show the messages at the experimenter screen - fprintf([repmat('=',1,50) '\n']); - fprintf('Subject''s monitor:\n'); - fprintf(text); - fprintf([repmat('=',1,50) '\n']); - - end - - - function [text]=GetText(nInstruct) - - if nInstruct == 0%Eyetracking calibration - - text = ['Um Ihre Augenbewegungen zu messen, \n' ... - 'müssen wir jetzt den Eye-Tracker kalibrieren.\n' ... - 'Dazu zeigen wir Ihnen einige Punkte auf dem Bildschirm, \n' ... - 'bei denen Sie sich wie folgt verhalten:\n' ... - 'Bitte fixieren Sie das Fixationskreuz und \n' ... - 'bleiben Sie so lange darauf, wie es zu sehen ist.\n' ... - 'Bitte drücken Sie jetzt den mittleren Knopf, \n' ... - 'um mit der Kalibrierung weiterzumachen.\n' ... - ]; - - elseif nInstruct == 1 - text = ['Sie sehen nun nacheinander zwei Muster.\n'... - '\n'... - 'Danach werden Sie gefragt, ob die Muster unterschiedlich oder gleich waren.\n'... - '\n'... - 'Benutzen Sie dazu die Pfeiltasten (links, rechts) und die obere Taste zum Bestätigen.\n'... - '\n'... - 'Wenn Sie noch Fragen haben, können Sie jetzt die Versuchsleiterin fragen.\n'... - 'Wir können Sie jederzeit hören.\n'... - '\n'... - 'Drücken Sie ansonsten die mittlere Taste,\n'... - ' um das Experiment zu starten.\n' ... - ]; - elseif nInstruct == 3 - text = ['You will now see two patterns after each other.\n'... - '\n'... - 'Please state, if they were different (left) or the same (right).\n'... - '\n'... - 'Use the arrow keys to move the marker and confirm with the UP button.\n'... - '\n'... - 'Please press UP\n'... - ' to start the experiment!\n' ... - ]; - elseif nInstruct == 2%end - text = 'Experiment beendet!\n'; - - elseif nInstruct==4%break - text = [sprintf('Sie haben bereits %g von %g Durchgängen geschafft!\n',tt-1,p.psi.numtrials*tchain)... - 'Machen Sie eine kurze Pause, lehnen Sie sich gern einen Moment zurück\n'... - 'und schließen Sie die Augen, um diese zu entspannen.\n'... - 'Drücken Sie anschließend die mittlere Taste, um weiterzumachen.\n']; - end - end - - function SetupLog(nc) - - - p.psi.log.globaltrial= NaN(nc,p.psi.numtrials); - p.psi.log.signal = NaN(nc,p.psi.numtrials); - p.psi.log.x = NaN(nc,p.psi.numtrials); - p.psi.log.refface = NaN(nc,p.psi.numtrials); - p.psi.log.testface = NaN(nc,p.psi.numtrials); - - p.psi.log.response = NaN(nc,p.psi.numtrials); - p.psi.log.alpha = NaN(nc,p.psi.numtrials); - p.psi.log.seAlpha = NaN(nc,p.psi.numtrials); - p.psi.log.beta = NaN(nc,p.psi.numtrials); - p.psi.log.seBeta = NaN(nc,p.psi.numtrials); - p.psi.log.gamma = NaN(nc,p.psi.numtrials); - p.psi.log.seGamma = NaN(nc,p.psi.numtrials); - p.psi.log.lambda = NaN(nc,p.psi.numtrials); - p.psi.log.seLambda = NaN(nc,p.psi.numtrials); - p.psi.log.xrounded = NaN(p.stim.tFace/tchain+1,p.psi.numtrials,nc); - p.psi.log.sdt = NaN(nc,p.psi.numtrials); - p.psi.log.trial_counter = zeros(p.stim.tFace/tchain+1,nc); - - - end - - function SetLog - - - p.psi.log.globaltrial(current_chain,cc(current_chain))= tt; - p.psi.log.signal(current_chain,cc(current_chain)) = signal; - p.psi.log.x(current_chain,cc(current_chain)) = PM{current_chain}.x(cc(current_chain))*direction; - p.psi.log.refface(current_chain,cc(current_chain)) = ref_face; - p.psi.log.testface(current_chain,cc(current_chain)) = test_face; - p.psi.log.response(current_chain,cc(current_chain)) = response; - p.psi.log.alpha(current_chain,cc(current_chain)) = PM{current_chain}.threshold(end); - p.psi.log.seAlpha(current_chain,cc(current_chain)) = PM{current_chain}.seThreshold(end); - p.psi.log.beta(current_chain,cc(current_chain)) = PM{current_chain}.slope(end); - p.psi.log.seBeta(current_chain,cc(current_chain)) = PM{current_chain}.seSlope(end); - p.psi.log.gamma(current_chain,cc(current_chain)) = PM{current_chain}.guess(end); - p.psi.log.seGamma(current_chain,cc(current_chain)) = PM{current_chain}.seGuess(end); - p.psi.log.lambda(current_chain,cc(current_chain)) = PM{current_chain}.lapse(end); - p.psi.log.seLambda(current_chain,cc(current_chain)) = PM{current_chain}.seLapse(end); - p.psi.log.sdt(current_chain,cc(current_chain)) = sdt;%1=hit 2=FA 3=miss 4=CR - - - end -% function PlotProcedure -% plotproc=figure(1); -% % title(sprintf('Threshold Estimation for subject %02d',tchain),'FontSize',14) -% for sub=1:tchain; -% subplot(2,2,sub) -% t = 1:length(p.log.x(sub)); -% hold on; -% plot(t,abs(p.log.x(sub)),'bo-'); -% errorbar(t,p.log.alpha(sub),p.log.seAlpha(sub),'r--') -% plot(t(p.log.response(sub) == 1),p.log.x(sub)(p.log.response(sub) == 1),'ko', ... -% 'MarkerFaceColor','k'); -% plot(t(p.log.response(sub) == 0),p.log.x(sub)(p.log.response(sub) == 0),'ko', ... -% 'MarkerFaceColor','w'); -% -% set(gca,'FontSize',12); -% axis([0 max(t)+1 0 max(p.log{sub}.alpha)+max(p.log{sub}.seAlpha)+20]) -% xlabel('Trial'); -% ylabel('xCurrent (Deg)'); -% -% end -% annotation('textbox', [0 0.9 1 0.1], 'String',... -% (sprintf('Threshold Estimation for subject %02d',tchain)), ... -% 'EdgeColor', 'none', ... -% 'HorizontalAlignment', 'center','FontSize',14) -% legend('xCurrent','estimated Threshold','Response = 1','Response = 0','Location','northeast'); -% -% % end -% function Plot_Fit -% plotfit=figure(2); -% for sub=1:tchain; -% subplot(2,2,sub) -% t = 1:length(p.log{sub}.x); -% hold on; -% plot(t,abs(p.log{sub}.x),'bo-'); -% errorbar(t,p.log{1}.alpha,p.log{1}.seAlpha,'r--') -% plot(t(p.log{sub}.response == 1),p.log{sub}.x(p.log{sub}.response == 1),'ko', ... -% 'MarkerFaceColor','k'); -% plot(t(p.log{sub}.response == 0),p.log{sub}.x(p.log{sub}.response == 0),'ko', ... -% 'MarkerFaceColor','w'); -% -% set(gca,'FontSize',12); -% axis([0 max(t)+1 0 max(p.log{sub}.alpha)+max(p.log{sub}.seAlpha)+20]) -% xlabel('Trial'); -% ylabel('xCurrent (Deg)'); -% -% end - -function [t]=StartEyelinkRecording(trialID,phase,cc,tt,current_chain,isref,file,delta_ref,delta_csp,abs_FGangle,fixx,fixy) - - t = []; - - - Eyelink('Message', 'TRIALID:%04d, PHASE:%04d, CHAIN:%04d, CHAINTRIAL:%04d, TTRIAL:%04d, ISREF:%04d, FILE:%04d, DELTAREF:%04d, DELTACSP:%04d, FGDEG:%04d, FXX:%04d, FXY:%04d',trialID, phase,... - current_chain, cc, tt, isref, file, delta_ref*100, delta_csp*100, abs_FGangle*100,fixx,fixy); - % an integration message so that an image can be loaded as - % overlay background when performing Data Viewer analysis. - WaitSecs(0.01); - Eyelink('Message', '!V IMGLOAD CENTER %s %d %d', p.stim.files(file,:), p.ptb.midpoint(1), p.ptb.midpoint(2)); - % This supplies the title at the bottom of the eyetracker display - Eyelink('Command', 'record_status_message "Stim: %d, Phase: %d"',file, phase); - % - %Put the tracker offline and draw the stimuli. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - % clear tracker display and draw box at center - Eyelink('Command', 'clear_screen %d', 0); - %draw the image on the screen - Eyelink('ImageTransfer',p.stim.files24(file,:),p.ptb.imrect(1),p.ptb.imrect(2),p.ptb.imrect(3),p.ptb.imrect(4),p.ptb.imrect(1),p.ptb.imrect(2)); - Eyelink('Command', 'draw_cross %d %d 15',fixx,fixy); - % - %drift correction - %EyelinkDoDriftCorrection(el,crosspositionx,crosspositiony,0,0); - %start recording following mode transition and a short pause. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('StartRecording'); - - t = GetSecs; - Log(t,8,NaN); -end - -function [t]=StopEyelinkRecording - - Eyelink('Message', 'Stim Offset'); - Eyelink('Message', 'BLANK_SCREEN'); - Eyelink('StopRecording'); - t = GetSecs; - %this is the end of the trial scope. - WaitSecs(0.01); - Eyelink('Message', 'TRIAL_RESULT 0'); - % - WaitSecs(0.01); - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('Command', 'clear_screen %d', 0); - - Log(t,-8,NaN); -end - -function InitEyeLink - % - if EyelinkInit(0)%use 0 to init normaly - fprintf('=================\nEyelink initialized correctly...\n') - else - fprintf('=================\nThere is problem in Eyelink initialization\n') - keyboard; - end - % - WaitSecs(0.5); - [~, vs] = Eyelink('GetTrackerVersion'); - fprintf('=================\nRunning experiment on a ''%s'' tracker.\n', vs ); - - %load 24bits pictures for eyelink... - dummy = dir([p.path.stim24 '*.bmp']); - p.stim.files24 = [repmat([fileparts(p.path.stim24) filesep],length(dummy),1) vertcat(dummy(:).name)]; -% for i=1:32 -% filename = p.stim.files24(nStim,:); -% [im , ~, ~] = imread(filename); -% end -% - % - el = EyelinkInitDefaults(p.ptb.w); - %update the defaults of the eyelink tracker - el.backgroundcolour = p.stim.bg; - el.msgfontcolour = WhiteIndex(el.window); - el.imgtitlecolour = WhiteIndex(el.window); - el.targetbeep = 0; - el.calibrationtargetcolour = WhiteIndex(el.window); - el.calibrationtargetsize = 1.5; - el.calibrationtargetwidth = 0.5; - el.displayCalResults = 1; - el.eyeimgsize = 50; - el.waitformodereadytime = 25;%ms - el.msgfont = 'Times New Roman'; - el.cal_target_beep = [0 0 0];%[1250 0.6 0.05]; - %shut all sounds off - el.drift_correction_target_beep = [0 0 0]; - el.calibration_failed_beep = [0 0 0]; - el.calibration_success_beep = [0 0 0]; - el.drift_correction_failed_beep = [0 0 0]; - el.drift_correction_success_beep= [0 0 0]; - EyelinkUpdateDefaults(el); - %PsychEyelinkDispatchCallback(el) - - % open file. - res = Eyelink('Openfile', p.path.edf); - if res == -3 - fprintf('File cannot be created!!!!\n'); - return; - end - % - Eyelink('command', 'add_file_preamble_text ''Recorded by EyelinkToolbox FearCloud Experiment'''); - Eyelink('command', 'screen_pixel_coords = %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - Eyelink('message', 'DISPLAY_COORDS %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - % set calibration type. - Eyelink('command', 'calibration_type = HV13'); - Eyelink('command','auto_calibration_messages = YES'); - Eyelink('command', 'select_parser_configuration = 1'); - %what do we want to record - Eyelink('command', 'file_sample_data = LEFT,RIGHT,GAZE,HREF,AREA,GAZERES,STATUS,INPUT,HTARGET'); - Eyelink('command', 'file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON,INPUT'); - Eyelink('command', 'use_ellipse_fitter = no'); - % set sample rate in camera setup screen - Eyelink('command', 'sample_rate = %d',1000); - end -function StopEyelink(filename) - try - fprintf('Trying to stop the Eyelink system with StopEyelink\n'); - Eyelink('StopRecording'); - WaitSecs(0.5); - Eyelink('Closefile'); - display('receiving the EDF file...'); - Eyelink('ReceiveFile',filename,[p.path.subject '\eye\'],1); - display('...finished!') - % Shutdown Eyelink: - Eyelink('Shutdown'); - catch - display('StopEyeLink routine didn''t really run well'); - end - end -function CalibrateEL - fprintf('=================\n=================\nEntering Eyelink Calibration\n') - p.var.ExpPhase = 0; - ShowInstruction(0); - EyelinkDoTrackerSetup(el); - %Returns 'messageString' text associated with result of last calibration - [~, messageString] = Eyelink('CalMessage'); - Eyelink('Message','%s',messageString);% - WaitSecs(0.05); - fprintf('=================\n=================\nNow we are done with the calibration\n') -end - - - -function Log(ptb_time, event_type, event_info) - %Phases: - %Pre-Experiment : 1 - %Post-Experiment : 2 -% %Instruction : 1 -% %Baseline : 2 -% %Conditioning : 3 -% %Test : 4 -% %Rating : 5 -% %Calibration : 0 - % - %event types are as follows: - % - %Scan Detection : 0 info: NaN; - %Cross Onset : 1 info: position - %Stimulus Onset/Offset: 2/-2 info: stim_id - %Cross Movement : 3 info: NaN; - %Stimulus Offset : -2 info: NaN; - %UCS Delivery : 4 info: NaN; - %Key Presses : 7 info: NaN; - %Tracker Onset/Offset : 8 info: NaN; - % - %Text on the screen : 5 info: Which Text? - %RatingScreen Onset : 6 info: NaN; - - p.var.event_count = p.var.event_count + 1; - p.out.log(p.var.event_count,:) = [ptb_time event_type event_info phase]; - % % p_out_log(p.out.event_counter,:) - %logstring([ 'Logged: ' mat2str(p_out_log(p.out.event_counter,:)) ' - Type: ' p.verbose.eventtype{abs(event_type)} ' - Phase: ' p.verbose.eventphase{CurrentExperimentalPhase}]) - %for i = 1:3;subplot(3,1,i);plot(p_out_log(1:p.out.event_counter ,i),'o-');drawnow;end - % - - end -function cleanup - - % Close window: - sca; - %set back the old resolution - if strcmp(p.hostname,'triostim1') - Screen('Resolution',p.ptb.screenNumber, p.ptb.oldres.width, p.ptb.oldres.height ); - %show the cursor - ShowCursor(p.ptb.screenNumber); - end - % -% %IOPort('ConfigureSerialPort', p.com.serial,' StopBackgroundRead'); -% %IOPort('Close',p.com.serial); -% commandwindow; -% ListenChar(0); -% KbQueueRelease(p_ptb_device); -end - -end diff --git a/exp_remi3_fmri.m b/exp_remi3_fmri.m deleted file mode 100644 index 8859e85..0000000 --- a/exp_remi3_fmri.m +++ /dev/null @@ -1,675 +0,0 @@ -function [p] = remi3_fmri(subject,run,group) - -if nargin == 0 - subject = 96; run = 1; group = 1; -end - -if group == 1 - name = 'NaCl'; -elseif group == 2 - name = 'Remi50'; -elseif goup == 3 - name = 'Remi100'; -end -fprintf('Sub%02d\nRun%d\nGroup: %s\n',subject,run,name); - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%% Put in your experiment choices here -debug = 1; % Use this function to have a transparent screen -p_mri_on = 0; % If on, waits for pulses and useses BrainVision Recorder marking BEFORE it marks CED. Otherwise, it only uses CED marking and sets BVR to 0 -p_slave_on = 0; % If on, waits for pulse from master and starts presentation at the same time. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Initialize Experiment Environment -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -ListenChar(2); % Disable pressed keys to printed out -commandwindow; -%clear everything without using 'clear all' -clear mex global functions - -%%%%%%%%%%%%%%%%%%%%%%%%%%% Load the GETSECS mex files so call them at -%%%%%%%%%%%%%%%%%%%%%%%%%%% least oncec -GetSecs; -WaitSecs(0.001); - -SetParameters; - -if strcmp(p.hostname,'triostim1') - debug = 0; -end - -SetPTB; - - -%%%%%%%%%%%%%%%%%%%%%%%%%%% Initialize all variables -nTrial = 0; -stimName = []; -itiDuration = []; -CueDuration = []; -TimeCrossOn = []; -TimeCueOn = []; -TimeHeatOn = []; -TimeStarOn = []; -TimeBlankOn = []; -TimeBreathOn = []; -p_stim_white = p.stim.white; -p_stim_red = p.stim.red; -p_stim_backgr = p.stim.backgr; -p_stim_sizeCross = p.stim.sizeCross; -p_stim_widthCross = p.stim.widthCross; -p_monitor_nx = p.monitor.Xaxis; % pixel x-axis -p_monitor_ny = p.monitor.Yaxis; % pixel y-axis -p_com_lpt_CEDaddress = p.com.lpt.CEDaddress; -p_com_lpt_CEDduration = p.com.lpt.CEDduration; -p_com_lpt_scannerPulseOnset = p.com.lpt.scannerPulseOnset; -p_com_lpt_ITIOnset = p.com.lpt.ITIOnset; -% p_com_lpt_CueOnset = p.com.lpt.CueOnset; -p_com_lpt_HeatOnset = p.com.lpt.HeatOnset; -p_com_lpt_VASOnset = p.com.lpt.VASOnset; -p_presentation_itiDuration = p.presentation.itiDuration; -p_presentation_CueDuration = p.presentation.CueDuration; -p_presentation_stimDuration = p.presentation.stimDuration; -p_presentation_blankDuration = p.presentation.blankDuration; -p_presentation_stimSequence = p.presentation.stimSequence; -p_presentation_TrialList = p.presentation.trialList; -p_presentation_scaleDuration = p.presentation.scaleDuration; -p_keys_trigger = p.keys.trigger; -p_keys_nextStep = p.keys.nextStep; -p_mri_tr = p.mri.tr; -p_ptb_w = p.ptb.w; -p_ptb_midpoint = p.ptb.midpoint; -p_ptb_midpoint_y = p.ptb.midpoint(2); -p_ptb_rect = p.ptb.rect; -p_ptb_startY = p.ptb.startY; -p_text_linespace = p.text.linespace; -p_ptb_lineheight = p.ptb.lineheight; - -% save again the parameter file -save(p.path.save ,'p'); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% Run Experiment -% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -putLog(GetSecs, 'Experiment Start'); -fprintf(['=================\n=================\nStart thermode protocol ' num2str(p_presentation_stimSequence) '!!!!\n']); - -% Show Instructions; -ShowInstruction; - -% Wait for Dummy Scans -firstScannerPulseTime = WaitPulse(p.keys.trigger,p.mri.dummyScan); -commandwindow; -p.log.mriExpStartTime = firstScannerPulseTime(end); -putLog(p.log.mriExpStartTime, 'FirstMRPulse_ExpStart'); - -% Actual stimulus presentation -runExperiment; - -% Show SessionEnd -ShowEndSessionText; - -cleanup; -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% End of Experiment -% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - -%% Set all parameters relevant for the whole experiment and the specific subject - function SetParameters - p.mri.on = p_mri_on; - p.mri.dummyScan = 5; - p.mri.tr = 2.65; - p.slave = p_slave_on; - p.subinfo.subID = subject; - p.subinfo.group = group; % nacl 1 remi50 2 remi100 3 - p.subinfo.groupname = name; % nacl 1 remi50 2 remi100 3 - p.subinfo.run = run; - - %%%%%%%%%%%%%%%%%%%%%%%%%%% create log structure - p.log.mriExpStartTime = 0; % Initialize as zero - p.log.events = {{},{},{},{}}; % event count, real time, experiment duration, event string - p.log.ratings1 = []; % event count, real time, experiment duration, event string - p.log.ratings2 = []; - p.log.eventCount = 0; - p.log.rating1EventCount = 0; - p.log.rating2EventCount = 0; - p.log.onratingEventCount = 0; - p.log.moodEventCount = 0; - p.log.scaleDefaultVAS1 = []; - p.log.scaleDefaultVAS2 = []; - p.log.PainOnset = []; - p.log.PainOnsetScan = []; - p.log.MoodRating = []; - p.log.Rating1 = []; - p.log.Rating2 = []; - - %%%%%%%%%%%%%%%%%%%%%%%%%%% relative paths to stim and experiments - [~, hostname] = system('hostname'); - p.hostname = deblank(hostname); - p.hostaddress = java.net.InetAddress.getLocalHost ; - p.hostIPaddress = char( p.hostaddress.getHostAddress); - if strcmp(p.hostname,'triostim1') - p.path.experiment = 'C:\USER\tinnermann\remi3\Paradigma_MRT\'; - p.monitor.Xaxis = 1024; % stim PC resolution - p.monitor.Yaxis = 768; % stim PC resolution - else - p.path.experiment = 'C:\Users\tinnermann\Documents\remi3\Paradigma_MRT\'; - p.monitor.Xaxis = 1920; % stim PC resolution - p.monitor.Yaxis = 1200; % stim PC resolution - end - % - p.subID = sprintf('sub%02d',subject); - p.timestamp = datestr(now,30); - - p.path.subject = [p.path.experiment '/logs/' p.subID '/']; - - p.path.save = [p.path.subject p.subID '_run' num2str(p.subinfo.run) '_' p.timestamp ]; - %create folder hierarchy - mkdir(p.path.subject); - - %%%%%%%%%%%%%%%%%%%%%%%%%%% font size, background gray level, monitor settings - p.text.fontname = 'Arial'; - p.text.fontsize = 20; %30; %18; - p.text.linespace = 10; - p.stim.white = [255 255 255]; - p.stim.red = [255 0 0]; - p.stim.backgr = [70 70 70]; - p.stim.widthCross = 3; - p.stim.sizeCross = 20; - - if strcmp(p.hostname,'triostim1') % curdes button box single diamond (HID NAR 12345) - p.keys.confirm = KbName('3#'); % green button - p.keys.right = KbName('4$'); % red button - p.keys.left = KbName('2@'); % yellow button - p.keys.esc = KbName('esc'); - p.keys.nextStep = KbName('space'); - p.keys.trigger = KbName('5%'); - else - %All settings for laptop computer. - KbName('UnifyKeyNames'); - p.keys.confirm = KbName('Return'); - p.keys.right = KbName('RightArrow'); - p.keys.left = KbName('LeftArrow'); - p.keys.esc = KbName('Escape'); - p.keys.nextStep = KbName('space'); - p.keys.trigger = KbName('5'); - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%% Parallel port settings - % Codes for different events - % device Thermode: 4 - % Spike-channel 4 : 32 - % Spike-channel 5 : 64 - % Spike-channel 6 : 128 - - if strcmp(p.hostname,'triostim1') - p.com.lpt.scannerPulseOnset = 224; % start of each run -> 32+64+128 (all 3 channels) - p.com.lpt.HeatOnset = 36; % Cue (spike channel 4) - p.com.lpt.VASOnset = 64; % Heat trigger for thermode plus spike channel 5 - p.com.lpt.ITIOnset = 128; % VAS/Mood scale on (Spike-channel 6) -% p.com.lpt.ITIOnset = 192; % white fixation cross on channel 5 and 6 - else - p.com.lpt.scannerPulseOnset = 0; % start of each run -> 32+64+128 (all 3 channels) - p.com.lpt.CueOnset = 0; % Cue (spike channel 4) - p.com.lpt.HeatOnset = 255; % Heat trigger for thermode - p.com.lpt.VASOnset = 0; % VAS/Mood scale on (Spike-channel 6) - p.com.lpt.ITIOnset = 0; % white fixation cross - end - p.com.lpt.CEDaddress = 888; - p.com.lpt.CEDduration = 0.005; - - %%%%%%%%%%%%%%%%%%%%%%%%%%% Stimulus sequence and startle timings - p.presentation.stimDuration = 17; - p.presentation.blankDuration = 0.5; - iti = [19 20 21 22 22 23 24 25]; - trialLists = load([p.path.experiment 'trial_seq.mat']); - trialLists = trialLists.trial_seq; - sequence = load([p.path.experiment 'rand_seq.mat']); - sequence = sequence.rand_seq; - p.presentation.stimSequence = sequence(run,subject); - p.presentation.trialList = trialLists(:,p.presentation.stimSequence); - p.presentation.tTrial = length(p.presentation.trialList); %number of trials - p.presentation.itiDuration = iti(randperm(length(iti))); - p.presentation.CueDuration = 4; - p.presentation.scaleDuration = 8; - p.presentation.scaleBackColor = p.stim.backgr; - p.presentation.BreathRem = 2; - p.presentation.starTime = 0.6; - p.presentation.lastITI = 4; - - clearvars trialLists - - %%%%%%%%%%%%%%%%%%%%%%%%%%% Save the parameters for this subject - save(p.path.save ,'p'); - end - -%% Set Up the PTB with parameters and initialize drivers - function SetPTB - screens = Screen('Screens'); % Find the number of the screen to be opened - p.ptb.screenNumber = max(screens); % The maximum is the second monitor - if debug - commandwindow; - PsychDebugWindowConfiguration; % Make everything transparent for debugging purposes. - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%% Default parameters - Screen('Preference', 'SkipSyncTests', 0); - Screen('Preference', 'DefaultFontSize', p.text.fontsize); - Screen('Preference', 'DefaultFontName', p.text.fontname); - %Screen('Preference', 'TextAntiAliasing',2); % Enable textantialiasing high quality - Screen('Preference', 'VisualDebuglevel', 0); % 0 disable all visual alerts - %Screen('Preference', 'SkipSyncTests', 0); - %Screen('Preference', 'SuppressAllWarnings', 0); - if debug == 0; - HideCursor(p.ptb.screenNumber); % Hide the cursor - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%% Open a graphics window using PTB - p.ptb.w = Screen('OpenWindow', p.ptb.screenNumber, p.stim.backgr); - % Screen('TextStyle', p.ptb.w, 1); % Make Text Bold - Screen('Flip',p.ptb.w); % Make the bg - p.ptb.slack = Screen('GetFlipInterval',p.ptb.w)./2; - % [p.ptb.width, p.ptb.height] = Screen('WindowSize', p.ptb.screenNumber); - p.ptb.rect = [0 0 p.monitor.Xaxis p.monitor.Yaxis]; - p.ptb.width = p.monitor.Xaxis; - p.ptb.height = p.monitor.Yaxis; - p.ptb.midpoint = [p.ptb.width./2 p.ptb.height./2]; % Find the mid position on the screen. - - p.ptb.startY = p.monitor.Yaxis/4; - p.ptb.lineheight = p.text.fontsize + p.text.linespace; - - p.ptb.whiteFix1 = [p.ptb.midpoint(1)-p.stim.sizeCross p.ptb.startY-p.stim.widthCross p.ptb.midpoint(1)+p.stim.sizeCross p.ptb.startY+p.stim.widthCross]; - p.ptb.whiteFix2 = [p.ptb.midpoint(1)-p.stim.widthCross p.ptb.startY-p.stim.sizeCross p.ptb.midpoint(1)+p.stim.widthCross p.ptb.startY+p.stim.sizeCross]; - % p.ptb.imrect = [ p_ptb_midpoint(1)-p.stim.width/2 p_ptb_midpoint(2)-p.stim.height/2 p.stim.width p.stim.height]; - - p.ptb.priorityLevel=MaxPriority('GetSecs','KbCheck','KbWait'); - Priority(MaxPriority(p.ptb.w)); - p.ptb.device = []; - - %%%%%%%%%%%%%%%%%%%%%%%%%%% Parallel port communication. - config_io; - outp(p.com.lpt.CEDaddress,0); - - end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Functions collection -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - function [secs]=WaitPulse(keycode,n) - %[secs]=WaitPulse(keycode,n) - % - % This function waits for the Nth upcoming pulse. If N=1, it will wait for - % the very next pulse to arrive. 1 MEANS NEXT PULSE. So if you wish to wait - % for 6 full dummy scans, you should use N = 7 to be sure that at least 6 - % full acquisitions are finished. - % - % The function avoids KbCheck, KbWait functions, but relies on the OS - % level event queues, which are much less likely to skip short events. A - % nice discussion on the topic can be found here: - % http://ftp.tuebingen.mpg.de/pub/pub_dahl/stmdev10_D/Matlab6/Toolboxes/Psychtoolbox/PsychDocumentation/KbQueue.html - - %KbQueueFlush;KbQueueStop;KbQueueRelease;WaitSecs(1); - fprintf('Will wait for %i dummy pulses...\n',n); - if n ~= 0 - secs = nan(1,n); - pulse = 0; - dummy = []; - while pulse < n - dummy = KbTriggerWait(keycode,p.ptb.device); - pulse = pulse + 1; - secs(pulse+1) = dummy; - fprintf('Waiting for dummy scan %d\n',pulse); - putLog(dummy,num2str(pulse)); - end - else - secs = GetSecs; - end - end - -%% Start the actual experiment - function runExperiment - for nTrial = 1:p.presentation.tTrial; % Enter the presentation loop - stimName = p_presentation_TrialList(nTrial); - itiDuration = p_presentation_itiDuration(nTrial); - CueDuration = p_presentation_CueDuration; - - if nTrial == 1 % Turn on the fixation cross for the first trial. These have to be done before the main for loop. - Screen('FillRect', p_ptb_w, p_stim_white, p.ptb.whiteFix1); - Screen('FillRect', p_ptb_w, p_stim_white, p.ptb.whiteFix2); - TimeCrossOn = Screen('Flip',p_ptb_w); % gets timing of event for putLog - putMark(p_com_lpt_ITIOnset); % Mark Fixation Cross Onset - putLog(TimeCrossOn, 'FirstITIOnset'); % Log the cross onset... - fprintf('=================\n=================\nFirst ITI, waiting for 5 seconds\n=================\n=================\n'); - while GetSecs < TimeCrossOn + 5 end - end - - fprintf('%d of %d, Stim: %d, CueDuration: %d, itiDuration: %d \n',nTrial,p.presentation.tTrial, stimName(1), CueDuration, itiDuration); - - p.log.scaleDefaultVAS1(nTrial,1) = randi([30,71]); - p.log.scaleDefaultVAS2(nTrial,1) = randi([30,71]); - p.log.scaleDefaultMood(nTrial,1) = randi([2,6]); - - Trial(itiDuration); - - end - - fprintf('=================\n=================\nWait for last scanner pulse of experiment!...\n'); - - mriEnd = KbTriggerWait(p_keys_trigger,p.ptb.device); - putLog(mriEnd, 'mriTrigger'); - putLog(GetSecs, 'ExpEnd'); - end - -%% Present affective Picture - function Trial(itiDuration) %Trial(stimID,stimName,stimStrlOnset,itiDuration,itiStrlOnset,jitter) - - %cue - if p_presentation_stimSequence == 2 && nTrial == 2 || p_presentation_stimSequence == 2 && nTrial == 7 ||... - p_presentation_stimSequence == 4 && nTrial == 1 || p_presentation_stimSequence == 4 && nTrial == 6 - DrawFormattedText(p_ptb_w, 'Im nächsten Durchgang bewerten Sie bitte', 'center',p_ptb_startY-100, p_stim_white); - DrawFormattedText(p_ptb_w, 'die Schmerzhaftigkeit WÄHREND des Hitzereizes!', 'center',p_ptb_startY-70, p_stim_white); - end - - Screen('FillRect', p_ptb_w, p_stim_red, p.ptb.whiteFix1); - Screen('FillRect', p_ptb_w, p_stim_red, p.ptb.whiteFix2); - TimeCueOn = Screen('Flip',p_ptb_w); - putLog(TimeCueOn, 'CueOnset'); - p.log.reactionTime(nTrial) = getRT(p_presentation_CueDuration,TimeCueOn); % check reaction time during cue - if nTrial > 1 - if isnan(p.log.reactionTime(end)) && isnan(p.log.reactionTime(end-1)) - warning(sprintf('\n***********\n***********\nNo RT for 2 Trials!\nPlease check participant!!!\n***********\n***********\n')); - end - end - - %Pain - %online rating scale - if p_presentation_stimSequence == 2 && nTrial == 2 || p_presentation_stimSequence == 2 && nTrial == 7 ||... - p_presentation_stimSequence == 4 && nTrial == 1 || p_presentation_stimSequence == 4 && nTrial == 6 - TimeHeatOn = GetSecs; - putMark(p_com_lpt_HeatOnset); - fprintf('Heat on\n'); - p.log.PainOnset(nTrial) = TimeHeatOn - p.log.mriExpStartTime; - p.log.PainOnsetScan(nTrial) = (TimeHeatOn - p.log.mriExpStartTime)/p_mri_tr; - putLog(TimeHeatOn, 'HeatOnset'); - [p.onrating.conRating,p.onrating.conTime,p.onrating.response] = onlineScale(p_ptb_w,p_ptb_rect,... - p_presentation_stimDuration,p_stim_backgr,p_ptb_startY,p.keys,p.presentation.starTime); % - putOnRatingLog(nTrial); - - else % only showing cross during pain - Screen('FillRect', p_ptb_w, p_stim_red, p.ptb.whiteFix1); % no treatment condition - Screen('FillRect', p_ptb_w, p_stim_red, p.ptb.whiteFix2); - TimeHeatOn = Screen('Flip',p_ptb_w); - putMark(p_com_lpt_HeatOnset); - putLog(TimeHeatOn, 'HeatOnset'); - p.log.PainOnset(nTrial) = TimeHeatOn - p.log.mriExpStartTime; - p.log.PainOnsetScan(nTrial) = (TimeHeatOn - p.log.mriExpStartTime)/p_mri_tr; - fprintf('Heat on\n'); - while GetSecs < TimeHeatOn + (p_presentation_stimDuration/2.5) end % = WaitSecs(p_presentation_stimDuration); - %Show star for rating - Screen('TextSize',p_ptb_w,p.text.fontsize+40); - Screen('FillRect', p_ptb_w, p_stim_red, p.ptb.whiteFix1); % no treatment condition - Screen('FillRect', p_ptb_w, p_stim_red, p.ptb.whiteFix2); - Screen('DrawText', p_ptb_w,'*',p_ptb_midpoint(1)-12,p.ptb.startY-60,p_stim_white); - TimeStarOn = Screen('Flip',p_ptb_w); - putLog(TimeStarOn, 'StarOnset'); - fprintf('Star on\n'); - while GetSecs < TimeStarOn + p.presentation.starTime end - Screen('FillRect', p_ptb_w, p_stim_red, p.ptb.whiteFix1); % no treatment condition - Screen('FillRect', p_ptb_w, p_stim_red, p.ptb.whiteFix2); - TimeHeatOn = Screen('Flip',p_ptb_w); - - while GetSecs < TimeStarOn + (p_presentation_stimDuration - (p_presentation_stimDuration/2.5)) end % = WaitSecs(p_presentation_stimDuration); - end - - %blank screen - TimeBlankOn = Screen('Flip',p_ptb_w); - while GetSecs < TimeBlankOn + p_presentation_blankDuration end % = WaitSecs(p_presentation_blankDuration); - putLog(TimeBlankOn, 'BlankOnset'); - - %VAS T2 - putLog(GetSecs, 'VAS1Onset'); - putMark(p_com_lpt_VASOnset); - fprintf('VAS_T2 on\n'); - - [p.rating1.finalRating,p.rating1.reactionTime,p.rating1.response] = vasScaleT2(p_ptb_w,p_ptb_rect,... - p_presentation_scaleDuration,p.log.scaleDefaultVAS1(nTrial,1),p_stim_backgr,p_ptb_startY,p.keys); % - putRating1Log(nTrial); - p.log.Rating1(nTrial) = p.rating1.finalRating; - - %blank screen - TimeBlankOn = Screen('Flip',p_ptb_w); - while GetSecs < TimeBlankOn + p_presentation_blankDuration end % = WaitSecs(p_presentation_blankDuration); - putLog(TimeBlankOn, 'BlankOnset'); - - %VAS T3 - putLog(GetSecs, 'VAS2Onset'); - putMark(p_com_lpt_VASOnset); - fprintf('VAS_T3 on\n'); - - [p.rating2.finalRating,p.rating2.reactionTime,p.rating2.response] = vasScaleT3(p_ptb_w,p_ptb_rect,... - p_presentation_scaleDuration-2,p.log.scaleDefaultVAS2(nTrial,1),p_stim_backgr,p_ptb_startY,p.keys,p.rating1.finalRating); % - putRating2Log(nTrial); - p.log.Rating2(nTrial) = p.rating2.finalRating; - - %blank screen - TimeBlankOn = Screen('Flip',p_ptb_w); - while GetSecs < TimeBlankOn + p_presentation_blankDuration end % = WaitSecs(p_presentation_blankDuration); - putLog(TimeBlankOn, 'BlankOnset'); - - %Mood - putLog(GetSecs, 'MoodOnset'); - fprintf('Mood on\n'); - - [p.mood.finalRating,p.mood.reactionTime,p.mood.response] = moodScale(p_ptb_w,p_ptb_rect,... - p_presentation_scaleDuration-4,p.log.scaleDefaultMood(nTrial,1),p_stim_backgr,p_ptb_startY,p.keys); %p.log.scaleDefaultVAS(nTrial,1) - putMoodLog(nTrial); - p.log.MoodRating(nTrial) = p.mood.finalRating; - if nTrial > 1 - if p.log.MoodRating(end)+2 <= p.log.MoodRating(end-1) - warning(sprintf('\n***********\n***********\nParticipant rated 2 points less!\nPlease check participant!!!\n***********\n***********\n')); - end - end - - %Breath - Screen('TextSize',p_ptb_w,p.text.fontsize); - p_monitor_ny = p.monitor.Yaxis/4; - [p_monitor_nx, p_monitor_ny, textbounds]=DrawFormattedText(p_ptb_w, 'Bitte atmen Sie ruhig und gleichmäßig', 'center', p_monitor_ny, p_stim_white); - [p_monitor_nx, p_monitor_ny, textbounds]=DrawFormattedText(p_ptb_w, 'durch die Nase.', 'center', p_monitor_ny+p_ptb_lineheight, p_stim_white); - - fprintf('Breath Reminder\n'); - TimeBreathOn = Screen('Flip',p_ptb_w); - putLog(TimeBreathOn, 'BreathOnset'); - while GetSecs < TimeBreathOn + p.presentation.BreathRem end - - %ITI - p.presentation.durVAS(nTrial) = p.mood.reactionTime+p.rating1.reactionTime+p.rating2.reactionTime+(2*p_presentation_blankDuration); - p.presentation.itiDurationReal(nTrial) = (itiDuration + p.presentation.lastITI) - p.presentation.durVAS(nTrial); - -% if p.presentation.itiDurationReal(nTrial) > 0 - Screen('FillRect', p_ptb_w, p_stim_white, p.ptb.whiteFix1); - Screen('FillRect', p_ptb_w, p_stim_white, p.ptb.whiteFix2); - TimeCrossOn = Screen('Flip',p_ptb_w); - putMark(p_com_lpt_ITIOnset); - putLog(TimeCrossOn, 'ITIOnset'); - fprintf(['Remaining ITI duration: ' num2str(p.presentation.itiDurationReal(nTrial)) '\n']); - while GetSecs < (TimeCrossOn + p.presentation.itiDurationReal(nTrial)) end -% else -% Screen('FillRect', p_ptb_w, p_stim_white, p.ptb.whiteFix1); -% Screen('FillRect', p_ptb_w, p_stim_white, p.ptb.whiteFix2); -% TimeCrossOn = Screen('Flip',p_ptb_w); -% putLog(TimeCrossOn, 'ITIOnset'); -% putMark(p_com_lpt_ITIOnset); -% while GetSecs < TimeCrossOn + 5 end -% % fprintf('adding seconds to ITI to show breathing reminder\n'); -% % p.presentation.itiDurationReal(nTrial) = p.presentation.itiDurationReal(nTrial) + abs(p.presentation.itiDurationReal(nTrial) - p.presentation.BreathRem); -% end -% - save(p.path.save ,'p'); - end - -%% Instruction Text - function ShowInstruction - if run == 1 - p_monitor_ny = p.monitor.Yaxis/8; - [p_monitor_nx, p_monitor_ny, textbounds]=DrawFormattedText(p_ptb_w, 'Gleich beginnt das Experiment.', 'center', p_monitor_ny, p_stim_white); - [p_monitor_nx, p_monitor_ny, textbounds]=DrawFormattedText(p_ptb_w, 'Bleiben Sie die ganze Zeit so ruhig wie möglich liegen!', 'center', p_monitor_ny+p_ptb_lineheight, p_stim_white); - [p_monitor_nx, p_monitor_ny, textbounds]=DrawFormattedText(p_ptb_w, 'Haben Sie noch Fragen?', 'center', p_monitor_ny+p_ptb_lineheight, p_stim_white); - [p_monitor_nx, p_monitor_ny, textbounds]=DrawFormattedText(p_ptb_w, 'Sonst geht es jetz los!', 'center', p_monitor_ny+p_ptb_lineheight, p_stim_white); - else - [p_monitor_nx, p_monitor_ny, textbounds]=DrawFormattedText(p_ptb_w, 'Es geht gleich los...', 'center', p.ptb.startY, p_stim_white); - end - - introTextTime = Screen('Flip',p_ptb_w); - putLog(introTextTime,'IntroTextOn'); - WaitSecs(1); - - while 1 - [keyIsDown, ~, keyCode] = KbCheck(); % Start waiting 1/2 TR before JitterOnset for next pulse (this avoids collecting Pulses before). - if keyIsDown - if find(keyCode) == p_keys_nextStep; - break; - end - end - end - - StartWaitTime = Screen('Flip',p_ptb_w); - putLog(StartWaitTime, 'WaitForExpStartOnset'); - - fprintf('=================\n=================\nAsk if subject is alright\nThen tell MTA to start scanner!!!!!!!!...\n'); - fprintf('=================\n=================\nWill wait %d volumes for dummy...\n',p.mri.dummyScan); - end - -%% End session Text - function ShowEndSessionText - Screen('TextSize',p_ptb_w,p.text.fontsize); - if run == 8 - [p_monitor_nx, p_monitor_ny, textbounds]=DrawFormattedText(p_ptb_w, 'Das Experiment ist beendet.', 'center', p.ptb.start, p_stim_white); - [p_monitor_nx, p_monitor_ny, textbounds]=DrawFormattedText(p_ptb_w, 'Vielen Dank!', 'center', p_monitor_ny+p_ptb_lineheight, p_stim_white); - else - [p_monitor_nx, p_monitor_ny, textbounds]=DrawFormattedText(p_ptb_w, 'Ende des Durchgangs.', 'center', p.ptb.startY, p_stim_white); - [p_monitor_nx, p_monitor_ny, textbounds]=DrawFormattedText(p_ptb_w, 'Es geht gleich weiter!', 'center', p_monitor_ny+p_ptb_lineheight, p_stim_white); - end - - endTextTime = Screen('Flip',p_ptb_w); - putLog(endTextTime,'EndTextOn'); - - WaitSecs(1); - - while 1 - [keyIsDown, ~, keyCode] = KbCheck(); % Start waiting 1/2 TR before JitterOnset for next pulse (this avoids collecting Pulses before). - if keyIsDown - if find(keyCode) == p_keys_nextStep; - break; - end - end - end - end - -%% get reaction time - function reactionTime = getRT(durCue,startTime) - response = 0; - numberOfSecondsRemaining = durCue; - while numberOfSecondsRemaining > 0 - - if response == 0 - - [ keyIsDown, secs, keyCode ] = KbCheck; % this checks the keyboard very, very briefly. - if keyIsDown % only if a key was pressed we check which key it was - response = 0; % predefine variable for confirmation button 'space' - if keyCode(p.keys.confirm) - response = 1; - reactionTime = secs - startTime; - disp(['Reaction Time: ' num2str(reactionTime)]); - flip_confKey = GetSecs; - SecondsRemaining = durCue-(flip_confKey-startTime); - WaitSecs(SecondsRemaining); - break; - end - end - end - numberOfSecondsElapsed = (GetSecs - startTime); - numberOfSecondsRemaining = durCue - numberOfSecondsElapsed; - end - - if response == 0 - warning(sprintf('\n***********\n***********\nNo Response!\nPlease check participant!!!\n***********\n***********\n')); - reactionTime = NaN; - end - - end -%% Set Marker for CED and BrainVision Recorder - function putMark(port) - % Send pulse to CED for SCR, thermode, digitimer - % [handle, errmsg] = IOPort('OpenSerialport',num2str(port)); - outp(p_com_lpt_CEDaddress,port); - WaitSecs(p_com_lpt_CEDduration); - outp(p_com_lpt_CEDaddress,0); - % IOPort('CloseAll'); - end - -%% Log all events - function putLog(ptb_time, event_info) - p.log.eventCount = p.log.eventCount + 1; - p.log.events(p.log.eventCount,1) = {p.log.eventCount}; - p.log.events(p.log.eventCount,2) = {ptb_time}; - p.log.events(p.log.eventCount,3) = {ptb_time-p.log.mriExpStartTime}; - p.log.events(p.log.eventCount,4) = {event_info}; - end - function putOnRatingLog(currentTrial) - p.log.onratingEventCount = p.log.onratingEventCount + 1; - p.log.onratings.conTrial(p.log.onratingEventCount,1) = {currentTrial}; - p.log.onratings.conRating(:,p.log.onratingEventCount) = {p.onrating.conRating}; - p.log.onratings.conTime(:,p.log.onratingEventCount) = {p.onrating.conTime}; - p.log.onratings.conRes(p.log.onratingEventCount,1) = {p.onrating.response}; - end - function putRating1Log(currentTrial) - p.log.rating1EventCount = p.log.rating1EventCount + 1; - p.log.ratings1(p.log.rating1EventCount,1) = currentTrial; - p.log.ratings1(p.log.rating1EventCount,2) = p.rating1.finalRating; - p.log.ratings1(p.log.rating1EventCount,3) = p.rating1.response; - p.log.ratings1(p.log.rating1EventCount,4) = p.rating1.reactionTime; - end - - function putRating2Log(currentTrial) - p.log.rating2EventCount = p.log.rating2EventCount + 1; - p.log.ratings2(p.log.rating2EventCount,1) = currentTrial; - p.log.ratings2(p.log.rating2EventCount,2) = p.rating2.finalRating; - p.log.ratings2(p.log.rating2EventCount,3) = p.rating2.response; - p.log.ratings2(p.log.rating2EventCount,4) = p.rating2.reactionTime; - end - - function putMoodLog(currentTrial) - p.log.moodEventCount = p.log.moodEventCount + 1; - p.log.mood(p.log.moodEventCount,1) = currentTrial; - p.log.mood(p.log.moodEventCount,2) = p.mood.finalRating; - p.log.mood(p.log.moodEventCount,3) = p.mood.response; - p.log.mood(p.log.moodEventCount,4) = p.mood.reactionTime; - end - -%% After experiment is over clean everything and close drivers - function cleanup - sca; % Close window: - commandwindow; - ListenChar(0); % Use keys again - %KbQueueRelease(p_ptb_device); - save(p.path.save ,'p'); - if run == 4 - diary off; - end - end - -end - - - - - diff --git a/exp_treatgen.m b/exp_treatgen.m deleted file mode 100644 index 1961123..0000000 --- a/exp_treatgen.m +++ /dev/null @@ -1,1658 +0,0 @@ -function [p]=exp_treatgen(subject,run,csp,tonic,middletemp,lowtemp) -%[p]=FearGen_eyelab(subject,phase,csp,PainThreshold) -% -%Used for fearamy project, based on the FearGen_eyelab code. It increments -%it by adding scanner pulse communications. -% -% -mrt = 0; -debug = 0;%debug mode -laptop = 0; -arduino = 1; -%replace parallel port function with a dummy function -if ismac - % outp = @(x,y) fprintf('[%i %i]\n',x,y); -end -if nargin ~= 6 - fprintf('Wrong number of inputs\n'); - keyboard; -end - -csn = mod( csp + 8/2-1, 8)+1; -commandwindow; -%clear everything -clear mex global functions -if ~ismac - cgshut; - global cogent; -end -%%%%%%%%%%%load the GETSECS mex files so call them at least once -GetSecs; -WaitSecs(0.001); -% -el = 0;%[]; -p = []; -s = []; -SetParams; -echo on -diary(p.path.diary) -if arduino - SetArduino; -end -SetPTB; -% -%init all the variables -t = []; -nTrial = 0; -%% -p.var.event_count = 0; -%% -if el - InitEyeLink; -end -WaitSecs(2); -KbQueueStop(p.ptb.device); -KbQueueRelease(p.ptb.device); -%save again the parameter file -fprintf('saving parameter file. \n'); -save(p.path.path_param,'p'); -if run == 0 - p.var.ExpPhase = run;%set this after the calibration; - ShowInstruction(1,1); - ApplyAndRate; - ShowInstruction(2,1); - TENSdemo; - ShowInstruction(3,1); - PresentStimuli; - ShowInstruction(20,0,2); -elseif run == 5 - p.var.ExpPhase = run; - AskDetectionSelectable; - ShowInstruction(21,0,2); -else - % - if el - CalibrateEL; - end - p.var.ExpPhase = run;%set this after the calibration; - if run ==1 - - ShowInstruction(4,1); - ApplyAndRate; - for ninstr = 400:406 - ShowInstruction(ninstr,1); - end - else - ShowInstruction(44,1); - ApplyAndRate; - end - PresentStimuli; - Summary; - WaitSecs(2); - ShowInstruction(21,0,2); -end - -%get the eyelink file back to this computer -if el - StopEyelink(p.path.edf); -end -%trim the log file and save -p.out.log = p.out.log(sum(isnan(p.out.log),2) ~= size(p.out.log,2),:); -%shift the time so that the first timestamp is equal to zero -p.out.log(:,1) = p.out.log(:,1) - p.out.log(1); -p.out.log = p.out.log;%copy it to the output variable. -save(p.path.path_param,'p'); -diary off -% -%move the file to its final location. -try - copyfile(p.path.subject,p.path.finalsubject); -catch - movefile(p.path.subject,p.path.finalsubject); -end -%close everything down -% try -% addpath('/USER/onat/Code/globalfunctions/ssh2_v2_m1_r6/ssh2_v2_m1_r6/') -% p.path.tarname = [p.path.finalsubject(1:end-1) '.tar']; -% tar(p.path.tarname,p.path.finalsubject); -% [a b c] = fileparts( p.path.tarname); -% cd(a) -% scp_simple_put('sanportal','onat','',[b c]); -% fprintf('Copying to neuronass succesfull...\n'); -% catch -% fprintf('Copying to neuronass failed...\n'); -% end -cleanup; - - function AskDetectionSelectable - %asks subjects to select the face that was associated with a shocks - positions = circshift(1:8,[1 PsychRandSample(1:8,[1 1])]);%position of the marker - p.var.ExpPhase = 4; - ShowInstruction(8,1); - %% - increment([p.keys.increase p.keys.decrease]) = [1 -1];%key to increment mapping - %% - ok = 1; - while ok - DrawCircle; - Screen('FrameOval', p.ptb.w, [255 255 255], p.stim.circle_rect(positions(1),:), 2);%draw the marker circle somewhere random initially. - Screen('Flip',p.ptb.w); - [~, keyCode, ~] = KbStrokeWait(p.ptb.device);%observe key presses - keyCode = find(keyCode); - if length(keyCode) == 1%this loop avoids crashes to accidential presses of meta keys - if (keyCode == p.keys.increase) || (keyCode == p.keys.decrease) - positions = circshift(positions,[0 increment(keyCode)]); - elseif keyCode == p.keys.confirm - WaitSecs(0.1); - ok = 0; - end - end - end - %% - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.imrect ); - Screen('Flip',p.ptb.w); - p.out.selectedface = p.stim.circle_order(positions(1)); - end - function DrawCircle - for npos = 1:p.stim.tFace - Screen('DrawTexture', p.ptb.w, p.ptb.stim_sprites(p.stim.circle_file_id(npos)),[],p.stim.circle_rect(npos,:)); - %Screen('DrawText', p.ptb.w, sprintf('%i_%i_%i',p.stim.circle_order(npos),p.stim.circle_file_id(npos),npos),mean(p.stim.circle_rect(npos,[1 3])) ,mean(p.stim.circle_rect(npos,[2 4]))); - end - end - function [myrect]=angle2rect(A) - factor = 1.9;%factor resize the images - [x y] = pol2cart(A./180*pi,280);%randomly shift the circle - left = x+p.ptb.midpoint(1)-p.stim.width/2/factor; - top = y+p.ptb.midpoint(2)-p.stim.height/2/factor; - right = left+p.stim.width/factor; - bottom = top+p.stim.height/factor; - myrect = [left top right bottom]; - end - function AskDetection - % - p.var.ExpPhase = 3; - ShowInstruction(801,1); - %% show a fixation cross - fix = [p.ptb.CrossPosition_x p.ptb.CrossPosition_y(1)];%show the fixation cross at the lip position to ease the subsequent drift correction. - FixCross = [fix(1)-1,fix(2)-p.ptb.fc_size,fix(1)+1,fix(2)+p.ptb.fc_size;fix(1)-p.ptb.fc_size,fix(2)-1,fix(1)+p.ptb.fc_size,fix(2)+1]; - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.imrect ); %always create a gray background - Screen('FillRect', p.ptb.w, [255,255,255], FixCross');%draw the prestimus cross atop - - Screen('DrawingFinished',p.ptb.w,0); - Screen('Flip',p.ptb.w); - StartEyelinkRecording(1,0,p.var.ExpPhase,0,0,0,fix,0); - WaitSecs(1.5); - %% - DrawCircle; - %Stimulus onset - Screen('Flip',p.ptb.w); - Eyelink('Message', 'Stim Onset'); - Eyelink('Message', 'SYNCTIME'); - %% - WaitSecs(30); - Screen('Flip',p.ptb.w); - Eyelink('Message', 'Stim Offset'); - Eyelink('Message', 'BLANK_SCREEN'); - StopEyelinkRecording; - end - - function PresentStimuli - if arduino - serialcom(s,'T',p.presentation.pain.tonic(1)); - end - %Enter the presentation loop and wait for the first pulse to - %arrive. - %wait for the dummy scans - % [secs] = WaitPulse(p.keys.pulse,p.mrt.dummy_scan);%will log it - % KbQueueStop(p.ptb.device); - % WaitSecs(.05); - % KbQueueCreate(p.ptb.device); - % KbQueueStart(p.ptb.device);%this means that from now on we are going to log pulses. - %If the scanner by mistake had been started prior to this point - %those pulses would have been not logged. - %log the pulse timings. - % TimeEndStim = secs(end)- p.ptb.slack;%take the first valid pulse as the end of the last stimulus. - for nTrial = 1:p.presentation.tTrial; - - %Get the variables that Trial function needs. - stim_id = p.presentation.stim_id(nTrial); - fix = p.presentation.CrossPosition(nTrial,:); %dummy:[656 280 664 320; 640 296 680 304] - ISI = p.presentation.tonicpain(nTrial); - ucs = p.presentation.ucs(nTrial); - dist = p.presentation.dist(nTrial); - if ucs - tempC = p.presentation.pain.low(nTrial); - else - tempC = p.presentation.pain.middle(nTrial); - end - % - %OnsetTime = TimeEndStim + ISI-p.duration.stim - p.ptb.slack; - fprintf('\nTrial %d of %d, Stim: %d, Temp: %5.2f, UCS: %d. ',nTrial,p.presentation.tTrial,stim_id,tempC,ucs); - - %Start with the trial, here is time-wise sensitive must be - %optimal - [TimeEndStim] = Trial(nTrial, ISI, tempC, stim_id, ucs, dist, fix); - %fprintf('OffsetTime: %05.8gs, Difference of %05.8gs\n',TimeEndStim,TimeEndStim-OnsetTime-p.duration.stim); - % - %dump itfa - [keycode, secs] = KbQueueDump;%this contains both the pulses and keypresses. - %log everything but "pulse keys" as pulses, not as keypresses. - if mrt == 1 - pulses = (keycode == p.keys.pulse); - if any(~pulses);%log keys presses if only there is one - Log(secs(~pulses),7,keycode(~pulses)); - end - if any(pulses);%log pulses if only there is one - Log(secs(pulses),0,keycode(pulses)); - end - end - %check if temperatures need to be adapted - adaptTemp(nTrial,ucs); - end - %wait 6 seconds for the BOLD signal to come back to the baseline... - KbQueueStop(p.ptb.device); - KbQueueRelease(p.ptb.device); - if mrt ==1 - if p.var.ExpPhase > 0 - WaitPulse(p.keys.pulse,p.mrt.dummy_scan);% - fprintf('OK!! Stop the Scanner\n'); - end - end - %dump the final events - [keycode, secs] = KbQueueDump;%this contains both the pulses and keypresses. - %log everything but "pulse keys" as pulses, not as keypresses. - - if mrt ==1 - pulses = (keycode == p.keys.pulse); - if any(~pulses);%log keys presses if only there is one - Log(secs(~pulses),7,keycode(~pulses)); - end - if any(pulses);%log pulses if only there is one - Log(secs(pulses),0,keycode(pulses)); - end - end - %stop the queue - KbQueueStop(p.ptb.device); - KbQueueRelease(p.ptb.device); - % if mrt == 1 - % WaitSecs(10); - % end - end - function rating = RatePain(nTrial,tonictemp); - time2rate = p.duration.rate; - if nTrial == 0; - time2rate = p.duration.rate +10; - end - OnSetTime = GetSecs + .1; - RateOn = GetSecs + min(p.presentation.tonicpain); - EndTrial = OnSetTime + 5 + p.duration.rate; - if nTrial < 2 - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.rect); %always create a gray background - Screen('FillRect', p.ptb.w, p.stim.white, p.ptb.centralFixCross');%draw the prestimus cross atop TimeCrossOn = Screen('Flip',p.ptb.w,Fix1On,0); - Screen('DrawingFinished',p.ptb.w,0); - TimeCrossOn = Screen('Flip',p.ptb.w,0); - MarkCED( p.com.lpt.address, p.com.lpt.FixOnset); - Log(TimeCrossOn,2,p.ptb.centralFixCross);%cross onset. - end - while GetSecs < RateOn;end - rateinit = randi(p.rating.initrange); - MarkCED( p.com.lpt.address, p.com.lpt.RateP); - [currentRating.finalRating,currentRating.RT,currentRating.response] = vasScale(p.ptb.w,p.ptb.rect,time2rate,rateinit,... - p.stim.bg,p.ptb.startY,p.keys,'pain'); - RateOff = Screen('Flip',p.ptb.w); - Log(RateOff,2,p.ptb.centralFixCross); - MarkCED(p.com.lpt.address, p.com.lpt.FixOnset); - PutRatingLog(nTrial,currentRating,tonictemp,rateinit,'pain') - while GetSecs < EndTrial;end - rating = currentRating.finalRating; - end - function ApplyAndRate - ShowInstruction(11,1); - ok = 0; - while ok == 0 - rampdur = abs(p.presentation.pain.tonic(1) - p.presentation.pain.base)./p.presentation.pain.ror; - p.log.ARcount = p.log.ARcount + 1; - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.rect); %always create a gray background - Screen('FillRect', p.ptb.w, p.stim.white, p.ptb.centralFixCross');%draw the prestimus cross atop - Screen('DrawingFinished',p.ptb.w,0); - TimeCrossOn = Screen('Flip',p.ptb.w,0); - MarkCED( p.com.lpt.address, p.com.lpt.FixOnset); - Log(TimeCrossOn,2,p.ptb.centralFixCross);%cross onset. - k = 0; - while k ~= KbName('v'); - pause(0.1); - fprintf('Is the thermode set? Press v to confirm that you will now press Pre-test and START at the thermode.') - [~, k] = KbStrokeWait(p.ptb.device); - k = find(k); - end - fprintf('.. Continuing!\n') - WaitSecs(.5); - starttime = GetSecs; - Log(starttime,7,k); - ShowInstruction(9,0,rampdur+1) % Temp rising... - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.rect); %always create a gray background - Screen('FillRect', p.ptb.w, p.stim.white, p.ptb.centralFixCross');%draw the prestimus cross atop - DrawFormattedText(p.ptb.w,'Rating folgt in einigen Sekunden.', 'center', p.ptb.midpoint(2)./1.2,p.stim.white); - Screen('DrawingFinished',p.ptb.w,0); - TimeCrossOn = Screen('Flip',p.ptb.w,0); - Log(TimeCrossOn,2,p.ptb.centralFixCross);%cross onset. - WaitSecs(10); - rating = RatePain(0,p.presentation.pain.tonic(1)); - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.rect); %always create a gray background - Screen('FillRect', p.ptb.w, p.stim.white, p.ptb.centralFixCross');%draw the prestimus cross atop TimeCrossOn = Screen('Flip',p.ptb.w,Fix1On,0); - Screen('DrawingFinished',p.ptb.w,0); - TimeCrossOn = Screen('Flip',p.ptb.w,0); - MarkCED( p.com.lpt.address, p.com.lpt.FixOnset); - Log(TimeCrossOn,2,p.ptb.centralFixCross);%cross onset. - putAR = [tonic rating]; - p.log.AR = [p.log.AR; putAR]; - k = 0; - while ~ or(k == KbName('v'),k == KbName('c')); - pause(0.1); - fprintf('Do you want to change the temp? Press c to correct (then STOP), or v to continue...\n') - [~, k] = KbStrokeWait(p.ptb.device); - k = find(k); - end - if k == KbName('v') - ok = 1; - fprintf('Continuing.\n') - elseif k == KbName('c') - ShowInstruction(12,1); - x = input('.\nEnter the next tonic pain temperature we will try.\n'); - delta = x - p.presentation.pain.tonic(1); - p.presentation.pain.tonic(1:end) = x; - p.presentation.pain.middle = p.presentation.pain.middle + delta; - p.presentation.pain.low = p.presentation.pain.low + delta; - fprintf('Temps are now:\n'); - fprintf('Tonic: %5.2f C\n',p.presentation.pain.tonic(1)); - fprintf('Middle: %5.2f C\n',p.presentation.pain.middle(1)); - fprintf('Low: %5.2f C.\n',p.presentation.pain.low(1)); - if arduino - serialcom(s,'T',p.presentation.pain.tonic(1)); - end - end - end - end - function Summary - fprintf('=================\n') - fprintf('Rating results:\n') - fprintf('single ratings for middle temp: %s\n',num2str(p.log.ratings.relief(logical(~p.presentation.ucs),3)')); - fprintf('Mean rating for middle temp: %5.2f\n',nanmean(p.log.ratings.relief(logical(~p.presentation.ucs),3)')); - fprintf('single ratings for UCS: %s\n',num2str(p.log.ratings.relief(logical(p.presentation.ucs),3)')); - fprintf('Mean rating for UCS: %5.2f\n',nanmean(p.log.ratings.relief(logical(p.presentation.ucs),3))); - fprintf('=================\nYour final temperatures were:\n') - fprintf('Your final temperatures were: tonic: %5.2f\n',p.presentation.pain.tonic(end)) - fprintf(' middle: %5.2f\n',p.presentation.pain.middle(end)) - fprintf(' low: %5.2f\n',p.presentation.pain.low(end)) - - end - function [TimeEndStim] = Trial(nTrial, ISI, tempC, stim_id, ucs, dist, fix) - tonic = p.presentation.pain.tonic(nTrial); - if p.presentation.ratepain(nTrial) - RatePain(nTrial,tonic); - end - rampdur = abs((tempC - p.presentation.pain.tonic(nTrial)))/p.presentation.pain.ror; - FixCross = [fix(1)-p.ptb.fc_width,fix(2)-p.ptb.fc_size,fix(1)+p.ptb.fc_width,fix(2)+p.ptb.fc_size;... - fix(1)-p.ptb.fc_size,fix(2)-p.ptb.fc_width,fix(1)+p.ptb.fc_size,fix(2)+p.ptb.fc_width]; %this is the fixcross before the face, not the central one - %get all the times - jitterF = rand(1).*.3; %jitter Fix - jitterR = rand(1).*.3; %jitter Ramp - OnsetTime = GetSecs + .05; %allow to compute and draw and so on - Fix1On = OnsetTime; - Fix2On = OnsetTime + ISI; - FaceOn = OnsetTime + ISI + p.duration.fix + jitterF; - FaceOff = OnsetTime + ISI + p.duration.fix + jitterF + p.duration.face; - Ramp1On = OnsetTime + ISI + p.duration.fix + jitterF + p.duration.face + jitterR; - Plateau = OnsetTime + ISI + p.duration.fix + jitterF + p.duration.face + jitterR + rampdur; - RateTOn = OnsetTime + ISI + p.duration.fix + jitterF + p.duration.face + jitterR + rampdur + p.duration.treatment - 2*rampdur; %dur.treatment - 2*rampdur is total plateau duration - RateTOff = OnsetTime + ISI + p.duration.fix + jitterF + p.duration.face + jitterR + rampdur + p.duration.treatment - 2*rampdur + p.duration.rate; - Ramp2On = OnsetTime + ISI + p.duration.fix + jitterF + p.duration.face + jitterR + p.duration.treatment; % not needed actually, because this just automatically happens after rating. - TimeEndStim = OnsetTime + ISI + p.duration.fix + jitterF + p.duration.face + jitterR + p.duration.treatment + p.duration.rate + p.duration.poststim - jitterF - jitterR; - %% Baseline, tonic pain, inkl. white fixcross in the middle - if nTrial ==1 - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.rect); %always create a gray background - Screen('FillRect', p.ptb.w, p.stim.white, p.ptb.centralFixCross');%draw the prestimus cross atop TimeCrossOn = Screen('Flip',p.ptb.w,Fix1On,0); - Screen('DrawingFinished',p.ptb.w,0); - TimeCrossOn = Screen('Flip',p.ptb.w,Fix1On,0); - MarkCED( p.com.lpt.address, p.com.lpt.FixOnset); - Log(TimeCrossOn,2,p.ptb.centralFixCross);%cross onset. - end - %% Show 2nd Fixcross, before Face - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.rect); %always create a gray background - Screen('FillRect', p.ptb.w, p.stim.white, FixCross');%draw the prestimus cross atop - Screen('DrawingFinished',p.ptb.w,0); - TimeCrossOn = Screen('Flip',p.ptb.w,Fix2On,0); - MarkCED( p.com.lpt.address, p.com.lpt.FixJump); - Log(TimeCrossOn,15,FixCross') - %% Draw the stimulus to the buffer - if stim_id ~=0 - Screen('DrawTexture', p.ptb.w, p.ptb.stim_sprites(stim_id)); - end - %% Face Stimulus Onset - TimeFaceOnset = Screen('Flip',p.ptb.w,FaceOn,0);%asap and dont clear - %send eyelink and ced a marker asap - Log(TimeFaceOnset,13,stim_id) - MarkCED(p.com.lpt.address, p.com.lpt.FaceOnset );%this actually didn't really work nicely. - fprintf('Face No %g is on.\n',stim_id) - %% Face Stim Off, Pain Cross on - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.rect); %always create a gray background - Screen('FillRect', p.ptb.w, p.stim.white,p.ptb.centralFixCross');%draw the central cross - Screen('DrawingFinished',p.ptb.w,0); - TimeFaceOffset = Screen('Flip',p.ptb.w,FaceOff,0);%asap and dont clear - Log(TimeFaceOffset,14,stim_id);%log the stimulus offset - Log(GetSecs,3,stim_id); - %% ramp to treatment temp - while GetSecs < Ramp1On;end - if arduino - serialcom(s,'START'); - end - Log(Ramp1On, 4, p.presentation.pain.ror); % ramp up - MarkCED(p.com.lpt.address, p.com.lpt.Ramp); - if ucs - MarkCED(p.com.lpt.address, p.com.lpt.ucs); - end - fprintf('Ramping to %5.2f C in %.02f s.\n',tempC,rampdur) - if arduino - serialcom(s,'SET',tempC); - end - while GetSecs < Plateau - end - % MarkCED(p.com.lpt.address,p.com.lpt.Plateau); - Log(Plateau, 5, tempC); % begin of stim plateau - if ucs == 1 - fprintf('This is a UCS trial!'); - end - countedDown = 1; - while GetSecs < RateTOn - [countedDown]=CountDown(GetSecs-Plateau,countedDown,'.'); - end - %% Flip to Rating - Log(RateTOn,11,NaN);%VAS Treatment onset. - rateinit = randi(p.rating.initrange); - MarkCED(p.com.lpt.address,p.com.lpt.RateR) - [currentRating.finalRating,currentRating.RT,currentRating.response] = vasScale(p.ptb.w,p.ptb.rect,p.duration.rate,rateinit,... - p.stim.bg,p.ptb.startY,p.keys,'relief'); - RateOff = Screen('Flip',p.ptb.w); - Log(RateOff,12,NaN);%VAS Treatment offset. - fprintf('Ramping back to baseline %5.2f C in %.02f s.',tonic,rampdur) - if arduino - serialcom(s,'SET',p.presentation.pain.tonic(nTrial)); - end - % MarkCED(p.com.lpt.address, p.com.lpt.Ramp2) - Log(GetSecs, 6, p.presentation.pain.ror) % ramp back to baseline - fprintf('Took subject %5.2f seconds to respond. \n',currentRating.RT); - PutRatingLog(nTrial,currentRating,tempC,rateinit,'relief'); - %% back to white cross (whenever ready) - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.rect); %always create a gray background - Screen('FillRect', p.ptb.w, p.stim.white, p.ptb.centralFixCross');%draw the prestimus cross atop TimeCrossOn = Screen('Flip',p.ptb.w,Fix1On,0); - Screen('DrawingFinished',p.ptb.w,0); - TimeCrossOn = Screen('Flip',p.ptb.w); - MarkCED( p.com.lpt.address, p.com.lpt.FixOnset); - Log(TimeCrossOn,2,p.ptb.centralFixCross');%cross onset. - while GetSecs < TimeEndStim %otherwise the trial just ends - end - if nTrial == p.presentation.tTrial - RatePain(nTrial,tonic); - end - end - function TENSdemo - basetemp = p.presentation.pain.tonic(1); - middletemp = p.presentation.pain.middle(1); - lowtemp = p.presentation.pain.low(1); - demotemps = [middletemp lowtemp middletemp lowtemp]; - rampdurs = abs((basetemp-demotemps))./p.presentation.pain.ror; - textstring ={'TENS aktiv' 'TENS aktiv' 'TENS aktiv' 'TENS aktiv'}; - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.rect); %always create a gray background - Screen('FillRect', p.ptb.w, p.stim.white, p.ptb.centralFixCross');%draw the prestimus cross atop - Screen('DrawingFinished',p.ptb.w,0); - Screen('Flip',p.ptb.w); - for dc = 1:length(demotemps) - text = textstring{dc}; - StartTrial = GetSecs; - fixon = StartTrial + .1; - tagon = StartTrial + .1 + 5; - rampon = StartTrial + .1 + 5 + 1 + rand(1)*.25; - plateauon = rampon + rampdurs(dc); - rateon = rampon + p.duration.treatment; - rateoff = rampon + p.duration.treatment + p.duration.rate; - - %white cross - if dc == 1 - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.rect); %always create a gray background - Screen('FillRect', p.ptb.w, p.stim.white, p.ptb.centralFixCross');%draw the prestimus cross atop - Screen('DrawingFinished',p.ptb.w,0); - FlipTime = Screen('Flip',p.ptb.w,fixon,0); - Log(FlipTime,2,p.ptb.centralFixCross); - end - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.rect); %always create a gray background - Screen('FillRect', p.ptb.w, p.stim.white, p.ptb.centralFixCross');%draw the prestimus cross atop - DrawFormattedText(p.ptb.w, text, 'center', p.ptb.midpoint(2)./1.2,p.stim.white); - Screen('DrawingFinished',p.ptb.w,0); - FlipTime = Screen('Flip',p.ptb.w,tagon,0); - Log(FlipTime,3,p.ptb.centralFixCross); - while GetSecs < rampon; end - if arduino - serialcom(s,'START'); - serialcom(s,'SET',demotemps(dc)); - end - Log(GetSecs,4,p.presentation.pain.ror); - Log(plateauon,5,demotemps(dc)); - while GetSecs < rateon; end - Log(GetSecs,11,NaN); - rateinit = randi(p.rating.initrange); - [currentRating.finalRating,currentRating.RT,currentRating.response] = vasScale(p.ptb.w,p.ptb.rect,p.duration.rate,rateinit,... - p.stim.bg,p.ptb.startY,p.keys,'relief'); - Log(GetSecs,12,NaN); - PutRatingLog(dc,currentRating,demotemps(dc),rateinit,'TENSdemo'); - fprintf(textstring{dc}) - fprintf(' condition with Temp of %g was rated as VAS = %g \n',demotemps(dc),currentRating.finalRating) - Log(GetSecs,6,p.presentation.pain.ror); - if arduino - serialcom(s,'SET',basetemp); - end - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.rect); %always create a gray background - Screen('FillRect', p.ptb.w, p.stim.white, p.ptb.centralFixCross');%draw the prestimus cross atop - Screen('DrawingFinished',p.ptb.w,0); - FlipTime = Screen('Flip',p.ptb.w,fixon,0); - Log(FlipTime,2,p.ptb.centralFixCross); - while GetSecs < rateoff;end % if subject rated faster than allowed, we add this to ISI. - end - k = 0; - while ~ or(k == KbName('v'),k == KbName('c')); - pause(0.1); - fprintf('Mean VAS: CS- (%5.2f C) = %g, CS+ (%5.2f C) = %g...\n',demotemps(1),nanmean(p.log.ratings.tensdemo([1 3],3)),demotemps(2),nanmean(p.log.ratings.tensdemo([2 4],3))) - fprintf('Are you OK with these ratings? Press c to correct, or v to continue...\n') - [~, k] = KbStrokeWait(p.ptb.device); - k = find(k); - end - if k == KbName('c') - x1 = input(sprintf('Please enter the corrected CS- temperature (medium, before %5.2f).\n',demotemps(1))); - x2 = input(sprintf('Please enter the corrected CS+ temperature (lower, before %5.2f).\n',demotemps(2))); - p.presentation.pain.middle = repmat(x1,[p.presentation.tTrial 1]); - p.presentation.pain.low = repmat(x2,[p.presentation.tTrial 1]); - fprintf('Corrected temperatures to middle = %g and low = %g. \n',p.presentation.pain.middle(1),p.presentation.pain.low(1)) - elseif k == KbName('v') - fprintf('Temperatures were okay. Continuing. \n') - end - end - function PutRatingLog(currentTrial,currentRating,tempC,initVAS,type) - if strcmp(type,'pain') - if currentTrial == 0 - p.log.ratings.initialPain = currentRating.finalRating; - else - p.log.ratingEventCount = p.log.ratingEventCount + 1; - p.log.ratings.pain(currentTrial,1) = tempC; - p.log.ratings.pain(currentTrial,2) = currentTrial; - p.log.ratings.pain(currentTrial,3) = currentRating.finalRating; - p.log.ratings.pain(currentTrial,4) = currentRating.response; - p.log.ratings.pain(currentTrial,5) = currentRating.RT; - p.log.ratings.pain(currentTrial,6) = initVAS; - end - elseif strcmp(type,'relief') - p.log.ratingEventCount = p.log.ratingEventCount + 1; - p.log.ratings.relief(currentTrial,1) = tempC; - p.log.ratings.relief(currentTrial,2) = currentTrial; - p.log.ratings.relief(currentTrial,3) = currentRating.finalRating; - p.log.ratings.relief(currentTrial,4) = currentRating.response; - p.log.ratings.relief(currentTrial,5) = currentRating.RT; - p.log.ratings.relief(currentTrial,6) = initVAS; - elseif strcmp(type,'TENSdemo') - p.log.ratingEventCount = p.log.ratingEventCount + 1; - if currentTrial == 0 - p.log.ratings.tensDEMOinitialPain = currentRating.finalRating; - else - p.log.ratings.tensdemo(currentTrial,1) = tempC; - p.log.ratings.tensdemo(currentTrial,2) = currentTrial; - p.log.ratings.tensdemo(currentTrial,3) = currentRating.finalRating; - p.log.ratings.tensdemo(currentTrial,4) = currentRating.response; - p.log.ratings.tensdemo(currentTrial,5) = currentRating.RT; - p.log.ratings.tensdemo(currentTrial,6) = initVAS; - end - end - end - function adaptTemp(nTrial,ucs) - adaptt = 0; - adaptb = 0; - if p.stim.phase ~=0 - if (p.presentation.pain.baseadapt == 1)&&(nTrial >= 3)&& (nTrial ~= p.presentation.tTrial); - basemed = median(p.log.ratings.pain(nTrial-2:nTrial,3)); - if (90 > basemed)&&(80 <= basemed) - p.presentation.pain.tonic(nTrial+1:end) = p.presentation.pain.tonic(nTrial) - p.presentation.pain.adaptstep; - fprintf('Median VAS was %g (not near 70). Decreased baseline Temp from %5.2f to %5.2f.\n',basemed,p.presentation.pain.tonic(nTrial),p.presentation.pain.tonic(nTrial+1)) - adaptb = -1; - elseif (basemed >= 90) - p.presentation.pain.tonic(nTrial+1:end) = p.presentation.pain.tonic(nTrial) - p.presentation.pain.adaptstep*2; - fprintf('This was really too hot, subject rated %g. Decreased baseline Temp from %5.2f to %5.2f.\n',basemed,p.presentation.pain.tonic(nTrial),p.presentation.pain.tonic(nTrial+1)) - adaptb = -2; - elseif basemed < 60 - p.presentation.pain.tonic(nTrial+1:end) = p.presentation.pain.tonic(nTrial) + p.presentation.pain.adaptstep; - fprintf('Median VAS was %g (not near 70). Increased baseline Temp from %5.2f to %5.2f.\n',basemed,p.presentation.pain.tonic(nTrial),p.presentation.pain.tonic(nTrial+1)) - adaptb = 1; - end - end - if (p.presentation.pain.treatadapt == 1)&&ucs % ucs only happens twice... probably better to adapt it very flexibly(?) - treatmed = p.log.ratings.relief(nTrial,3); - - if (treatmed >= 40) - p.presentation.pain.low(nTrial+1:end) = p.presentation.pain.low(nTrial) - p.presentation.pain.adaptstep; - fprintf('UCS was rated as %g (not near 30). Decreased UCS treatment Temp from %5.2f to %5.2f.\n',treatmed,p.presentation.pain.low(nTrial),p.presentation.pain.low(nTrial+1)) - adaptt = -1; - elseif treatmed < 20 - p.presentation.pain.low(nTrial+1:end) = p.presentation.pain.low(nTrial) + p.presentation.pain.adaptstep; - fprintf('UCS was rated as %g (not near 30). Increased UCS treatment Temp from %5.2f to %5.2f.\n',treatmed,p.presentation.pain.low(nTrial),p.presentation.pain.low(nTrial+1)) - adaptt = 1; - end - elseif ~ucs - if (p.presentation.pain.treatadapt == 1)&&(sum(p.presentation.ucs(1:nTrial)==0) >= 3) && (nTrial ~= p.presentation.tTrial); %nTrial > 3 because we want the last three ratings to go to median - - dummy = p.log.ratings.relief(~p.presentation.ucs(1:nTrial),3); - treatmed = median(dummy(end-2:end)); - if (treatmed >= 60) - p.presentation.pain.middle(nTrial+1:end) = p.presentation.pain.middle(nTrial) - p.presentation.pain.adaptstep; - fprintf('Median VAS was %g (not near 50). Decreased treatment Temp from %5.2f to %5.2f.\n',treatmed,p.presentation.pain.middle(nTrial),p.presentation.pain.middle(nTrial+1)) - adaptt = -1; - elseif treatmed < 40 - p.presentation.pain.middle(nTrial+1:end) = p.presentation.pain.middle(nTrial) + p.presentation.pain.adaptstep; - fprintf('Median VAS was %g (not near 50). Increased treatment Temp from %5.2f to %5.2f.\n',treatmed,p.presentation.pain.middle(nTrial),p.presentation.pain.middle(nTrial+1)) - adaptt = 1; - if p.presentation.pain.middle(nTrial+1) == p.presentation.pain.tonic(nTrial+1) - p.presentation.pain.middle(nTrial+1:end) = p.presentation.pain.tonic(nTrial+1)-.5; - fprintf('Reached baseline temp limit. Treatment temp set back to %5.2f.\n',p.presentation.pain.middle(nTrial+1)) - end - end - end - end - %check if temps are still different from each others - if nTrial ~= p.presentation.tTrial; - if p.presentation.pain.low(nTrial+1) == p.presentation.pain.middle(nTrial+1); - p.presentation.pain.low(nTrial+1:end) = p.presentation.pain.middle(nTrial+1)-p.presentation.pain.adaptstep; - warning('Needed to put UCS temp down, because middle temp was the same.\n') - end - if any([adaptb adaptt]) - fprintf('Temps are now:\nBase: %5.2f\nMiddle: %5.2f\nLow: %5.2f\n',p.presentation.pain.tonic(nTrial+1),p.presentation.pain.middle(nTrial+1),p.presentation.pain.low(nTrial+1)) - end - end - p.presentation.pain.adapt(nTrial,:) = [adaptb adaptt]; - end - end - function SetParams - %mrt business - p.mrt.dummy_scan = 7;%this will wait until the 6th image is acquired. - p.mrt.LastScans = 5;%number of scans after the offset of the last stimulus - p.mrt.tr = 1;%in seconds. - %will count the number of events to be logged - p.var.event_count = 0; - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %% relative path to stim and experiments - %Path Business. - [~, hostname] = system('hostname'); - p.hostname = deblank(hostname); - if strcmp(p.hostname,'triostim1') - p.path.baselocation = 'C:\USER\onat\Experiments\fearamy'; - elseif strcmp(p.hostname,'isn3464a9d59588') % Lea's HP - p.path.baselocation = 'C:\Users\Lea\Documents\Experiments\'; - end - - p.path.experiment = [p.path.baselocation 'Treatgen\']; - p.path.stim = [p.path.experiment 'Stimuli\']; - p.path.stim24 = [p.path.stim '24bit' filesep]; - p.path.stim_cut = [p.path.stim 'cut' filesep]; - % - p.subID = sprintf('sub%03d',subject); - timestamp = datestr(now,30); - p.path.subject = [p.path.experiment 'data\tmp' filesep p.subID '_' timestamp filesep ]; - p.path.finalsubject = [p.path.experiment 'data' filesep p.subID '_' 'p0' num2str(run) filesep]; - p.path.path_edf = [p.path.subject 'eye' filesep]; - p.path.edf = sprintf([p.subID 'p%02d.edf' ],run); - p.path.path_param = [p.path.subject 'stimulation' filesep 'data.mat']; - %create folder hierarchy - mkdir(p.path.subject); - % mkdir(p.path.finalsubject); - mkdir([p.path.subject 'scr']); - mkdir([p.path.subject 'eye']); - mkdir([p.path.subject 'stimulation']); - mkdir([p.path.subject 'midlevel']); - mkdir([p.path.subject 'diary']); - p.path.diary = [p.path.subject '\diary\diary.txt']; - %% %%%%%%%%%%%%%%%%%%%%%%%%% - %get stim files - [p.stim.files p.stim.label] = FileMatrix([p.path.stim '*.bmp']); - [p.stim.files_cut p.stim.label] = FileMatrix([p.path.stim_cut '*.png']); - p.stim.tFile = size(p.stim.files,1);%number of different files (including the UCS symbol) - p.stim.tFace = 8;%number of faces. - % - display([mat2str(p.stim.tFile) ' found in the destination.']); - %set the background gray according to the background of the stimuli - for i = 1:p.stim.tFace; - im = imread(p.stim.files(i,:)); - bg(i) = im(1,1,1); - end - %is all the captured bg values the same? - if sum(diff(bg))==0; - %if so take it as the bg color - p.stim.bg = double([bg(1) bg(1) bg(1)]); - else - fprintf('background luminance was not successfully detected...\n') - keyboard; - end - %bg of the rating screen. - p.stim.bg_rating = p.stim.bg; - p.stim.white = [255 255 255]; - %% font size and background gray level - p.text.fontname = 'Arial'; - p.text.fontsize = 18;%30; - p.text.fixsize = 60; - %rating business - p.rating.division = 101;%number of divisions for the rating slider - p.rating.initrange = [30 70]; - p.rating.repetition = 1;%how many times a given face has to be repeated... - %% get the actual stim size (assumes all the same) - info = imfinfo(p.stim.files(1,:)); - p.stim.width = info.Width; - p.stim.height = info.Height; - %% keys to be used during the experiment - %1, 6 ==> Right - %2, 7 ==> Left - %3, 8 ==> Down - %4, 9 ==> Up (confirm) - %5 ==> Pulse from the scanner - if strcmp(p.hostname,'triostim1') - p.keys.confirm = KbName('4$'); - p.keys.increase = KbName('1!'); - p.keys.decrease = KbName('3#'); - p.keys.pulse = KbName('5%'); - p.keys.el_calib = KbName('v'); - p.keys.el_valid = KbName('c'); - p.keys.esc = KbName('esc'); - p.keys.enter = KbName('return'); - elseif strcmp(p.hostname,'isn3464a9d59588') % Lea's HP - %All settings for laptop computer. - p.keys.confirm = KbName('space'); - p.keys.increase = KbName('right'); - p.keys.decrease = KbName('left'); - p.keys.space = KbName('space'); - p.keys.esc = KbName('esc'); - p.keys.null = KbName('0)'); - p.keys.one = KbName('1!'); - p.keys.v = KbName('v'); - p.keys.c = KbName('c'); - end - %% %%%%%%%%%%%%%%%%%%%%%%%%% - %Communication business - %parallel port - p.com.lpt.address = 888; - %codes for different events - p.com.lpt.FixOnset = 2; - p.com.lpt.FaceOnset = 4; - p.com.lpt.Ramp = 8; - p.com.lpt.RateP = 16; - p.com.lpt.RateR = 32; - p.com.lpt.ucs = 64; - p.com.lpt.FixJump = 128; - - - % - %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %timing business - %these are the intervals of importance - %time2fixationcross->cross2onset->onset2shock->shock2offset - %these (duration.BLA) are average duration values: - p.duration.fix = .85; % this is minimum, gets a jittered addition - p.duration.face = 1.5; % face stimulus - p.duration.poststim = 1; - p.duration.treatment = 6; % treatment plateau - p.duration.rate = 5; % how long can subject rate maximally - p.duration.keep_recording = 0.25;%this is the time we will keep recording (eye data) after stim offset. - - %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %stimulus sequence - if run == 0 - seq.cond_id = nan(10,1); - seq.tTrial = 10; - seq.tonicpain = Shuffle([5 6 7 6 5 6 7 6 6 5]); - seq.ratepain = [1 zeros(1,seq.tTrial-1)]; - seq.stim_id = [0 Shuffle(1:8)' csp]; - seq.ucs = [zeros(1,9) 1]; - seq.dist = MinimumAngle((seq.stim_id-1)*45,(csp-1)*45); %actually, there is no csp yet. so it could also be nans. - seq.dist(1) = 3000; %nulltrial - p.presentation = seq; - p.presentation.tTrial = 10; - elseif run == 1 - load([p.path.stim 'stimlist/cond_rr50.mat']); - seqid = subject+((run-1)*50); - p.presentation = seq(seqid,csp); - p.presentation.seqid = seqid; - elseif run == 10 % this could be any dummy seq, e.g. conditioning - seq.cond_id = Shuffle([1 1 1 1 2 2 2 2 3 3 3]); - seq.tTrial = length(seq.cond_id); - seq.ucs = seq.cond_id == 9; - seq.tonicpain = randi([5 7],[1 11]); - seq.ratepain = zeros(1,11); seq.ratepain(1) = 1; - seq.stim_id(seq.cond_id ==1) = csp; - seq.stim_id(seq.cond_id ==2) = csn; - seq.stim_id(seq.cond_id ==3) = csp; - seq.ucs = seq.cond_id ==3; - seq.dist = MinimumAngle((seq.stim_id-1)*45,(csp-1)*45); %actually, there is no csp yet. so it could also be nans. - seq.dist(seq.cond_id == 3) = 500; %ucs - p.presentation = seq; - else - load([p.path.stim 'stimlist\seq06x8_rr50.mat']); - seqid = subject+((run-2)*50); - p.presentation = seq(seqid,csp); - p.presentation.seqid = seqid; - end - - p.presentation.pain.base = 25; %thermode constant - p.presentation.pain.tonic = repmat(tonic,[p.presentation.tTrial 1]); - p.presentation.pain.middle = repmat(middletemp,[p.presentation.tTrial 1]); - p.presentation.pain.low = repmat(lowtemp,[p.presentation.tTrial 1]); - p.presentation.pain.ror = 5; - p.presentation.pain.adaptstep = .5; - p.presentation.pain.baseadapt = 0; % do you want to adapt baseline temp online? - p.presentation.pain.treatadapt = 0; % do you want to adapt treatment temps online? - p.presentation.pain.adapt = zeros(p.presentation.tTrial,2); % first column is baseline, second treatment, logs when it was adapted - % codes will be: - % 1 - increase - % -1 - decrease - % -2 - baseline was too hurtful - % 0 - no action taken - if ~ismember(run,1:4) - p.presentation.CrossPosition = FixationCrossPool; - end - clear seq - %% create the randomized design - p.stim.cs_plus = csp; %index of cs stimulus, this is the one with enhanced treatment - p.stim.cs_minus = csn; %this is only needed for beginning phase, where we condition people - %Record which Phase are we going to run in this run. - p.stim.phase = run; - - p.log.ARcount = 0; - p.log.AR = []; - p.log.ratingEventCount = 0; - p.log.ratings.pain = nan(p.presentation.tTrial,6); - p.log.ratings.relief = nan(p.presentation.tTrial,6); - p.log.ratings.tensdemo = nan(4,6); - p.out.log = zeros(1000000,4).*NaN; - p.out.response = zeros(p.presentation.tTrial,1); - %% - p.var.current_bg = p.stim.bg;%current background to be used. - %Save the stuff - save(p.path.path_param,'p'); - % - function [FM labels] = FileMatrix(path) - %Takes a path with file extension associated to regexp (e.g. - %C:\blabl\bla\*.bmp) returns the file matrix - dummy = dir(path); - FM = [repmat([fileparts(path) filesep],length(dummy),1) vertcat(dummy(:).name)]; - labels = {dummy(:).name}; - end - end - function SetArduino - s = serial('COM5','BaudRate',19200); - fopen(s); - WaitSecs(1); - serialcom(s,'T',p.presentation.pain.tonic(1)); - serialcom(s,'ROR',p.presentation.pain.ror); - WaitSecs(.5); - serialcom(s,'DIAG'); - WaitSecs(1); - end - function SetPTB - %KbName('UnifyKeyNames'); - %Sets the parameters related to the PTB toolbox. Including - %fontsizes, font names. - %Default parameters - Screen('Preference', 'SkipSyncTests', 1); - Screen('Preference', 'DefaultFontSize', p.text.fontsize); - Screen('Preference', 'DefaultFontName', p.text.fontname); - Screen('Preference', 'TextAntiAliasing',2);%enable textantialiasing high quality - Screen('Preference', 'VisualDebuglevel', 0); - Screen('Preference', 'SkipSyncTests', 1); - Screen('Preference', 'SuppressAllWarnings', 1); - %%Find the number of the screen to be opened - screens = Screen('Screens'); - p.ptb.screenNumber = max(screens);%the maximum is the second monitor - if laptop - p.ptb.screenNumber = 1; - end - %Make everything transparent for debugging purposes. - if debug - commandwindow; - PsychDebugWindowConfiguration; - end - %set the resolution correctly - res = Screen('resolution',p.ptb.screenNumber); - HideCursor(p.ptb.screenNumber); - %spit out the resolution - fprintf('Resolution of the screen is %dx%d...\n',res.width,res.height); - - %Open a graphics window using PTB - [p.ptb.w p.ptb.rect] = Screen('OpenWindow', p.ptb.screenNumber, p.var.current_bg); - %Screen('BlendFunction', p.ptb.w, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - Screen('Flip',p.ptb.w);%make the bg - p.ptb.slack = Screen('GetFlipInterval',p.ptb.w)./2; - [p.ptb.width, p.ptb.height] = Screen('WindowSize', p.ptb.screenNumber); - - %find the mid position on the screen. - p.ptb.midpoint = [ p.ptb.width./2 p.ptb.height./2]; - %NOTE about RECT: - %RectLeft=1, RectTop=2, RectRight=3, RectBottom=4. - p.ptb.imrect = [ p.ptb.midpoint(1)-p.stim.width/2 p.ptb.midpoint(2)-p.stim.height/2 p.ptb.midpoint(1)-p.stim.width/2+p.stim.width p.ptb.midpoint(2)-p.stim.height/2+p.stim.height]; - p.ptb.cross_shift = [180 -120]./2.5;%incremental upper and lower cross positions - p.ptb.CrossPosition_x = p.ptb.midpoint(1);%bb(1);%always the same - p.ptb.CrossPosition_y = p.ptb.midpoint(2)+p.ptb.cross_shift;%bb(1);%always the same - %cross position for the eyetracker screen. - p.ptb.CrossPositionET_x = [p.ptb.midpoint(1) p.ptb.midpoint(1)]; - p.ptb.CrossPositionET_y = [p.ptb.midpoint(2)-p.ptb.cross_shift(2) p.ptb.midpoint(2)+p.ptb.cross_shift(2)]; - p.ptb.fc_size = 20; - p.ptb.fc_width = 4; - p.ptb.fc_color = [130 50 0]; - p.ptb.startY = p.ptb.midpoint(2); - fix = [p.ptb.midpoint(1) p.ptb.startY]; % yaxis is 1/4 of total yaxis - p.ptb.centralFixCross = [fix(1)-p.ptb.fc_width,fix(2)-p.ptb.fc_size,fix(1)+p.ptb.fc_width,fix(2)+p.ptb.fc_size;fix(1)-p.ptb.fc_size,fix(2)-p.ptb.fc_width,fix(1)+p.ptb.fc_size,fix(2)+p.ptb.fc_width]; - - p.stim.white = [255 255 255]; % - %% - %priorityLevel=MaxPriority(['GetSecs'],['KbCheck'],['KbWait'],['GetClicks']); - Priority(MaxPriority(p.ptb.w)); - %this is necessary for the Eyelink calibration - %InitializePsychSound(0) - %sound('Open') - % Beeper(1000) - LoadPsychHID - %%%%%%%%%%%%%%%%%%%%%%%%%%%Prepare the keypress queue listening. - p.ptb.device = []; - %get all the required keys in a vector - p.ptb.keysOfInterest = [];for i = fields(p.keys)';p.ptb.keysOfInterest = [p.ptb.keysOfInterest p.keys.(i{1})];end - fprintf('Key listening will be restricted to %d\n',p.ptb.keysOfInterest) - RestrictKeysForKbCheck(p.ptb.keysOfInterest); - - p.ptb.keysOfInterest=zeros(1,256); - p.ptb.keysOfInterest(p.keys.confirm) = 1; - %create a queue sensitive to only relevant keys. - % KbQueueCreate(p.ptb.device,p.ptb.keysOfInterest);%default device. - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %prepare parallel port communication. This relies on cogent i - %think. We could do it with PTB as well. - if ~ismac - config_io; - outp(p.com.lpt.address,0); - if( cogent.io.status ~= 0 ) - error('inp/outp installation failed'); - end - end - - %CORRECT - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %test whether CED receives the triggers correctly... - k = 0; - while ~(k == 25 | k == 86 ); - pause(0.1); - outp(p.com.lpt.address,1);%256 means all channels. - % outp(p.com.lpt.address,256);%256 means all channels. - fprintf('Is everything set?\n\n') - fprintf('Digitimer still off?\n\n') - fprintf('Did the trigger test work?\n\nPress c to send it again, v to continue...\n') - [~, k] = KbStrokeWait(p.ptb.device); - k = find(k); - end - fprintf('Continuing...\n'); - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %load the pictures to the memory. - p.ptb.stim_sprites = CreateStimSprites(p.stim.files);% - p.ptb.stim_sprites_cut = CreateStimSprites(p.stim.files_cut);% - %% take care of the circle presentation - %order of faces on the circle that will be shown at the end. - if run > 1 - circle_order = Shuffle(unique(p.presentation.dist(p.presentation.dist < 500)));% - circle_order(end+1)=circle_order(1); - while any(abs(diff(circle_order)) < 50);%check that neighbors will not be neighbors in the next order. - circle_order = Shuffle(unique(p.presentation.dist(p.presentation.dist < 500))); - circle_order(end+1) = circle_order(1);%to be successful the check has to consider the circularity. - end - p.stim.circle_order = circle_order(1:end-1);%conditions in distances from CSP, 0 = CS+, randomized - p.stim.circle_angles = sort(p.stim.circle_order);%this is just angles with steps of 45 - %transform the angles to rects - for nc = 1:p.stim.tFace - p.stim.circle_rect(nc,:) = angle2rect(p.stim.circle_angles(nc)); - p.stim.circle_file_id(nc) = unique(p.presentation.stim_id(p.presentation.dist == p.stim.circle_order(nc)));%the file that corresponds to different conditions - end - %one to one mappings: - %now we have: circle_order ==> file_id - %circle_angles ==> circle_rect - end - - %% - function [out]=CreateStimSprites(files) - %loads all the stims to video memory - for nStim = 1:p.stim.tFile - filename = files(nStim,:); - [im , ~, ~] = imread(filename); - out(nStim) = Screen('MakeTexture', p.ptb.w, im ); - end - end - end - function [finalRating,reactionTime,response] = vasScale(window,windowRect,durRating,defaultRating,backgroundColor,StartY,keys,type) - - %% key settings - KbName('UnifyKeyNames'); - lessKey = keys.decrease; % yellow button - moreKey = keys.increase; % red button - confirmKey = keys.confirm; % green button - escapeKey = keys.esc; - - if isempty(window); error('Please provide window pointer for likertScale!'); end - if isempty(windowRect); error('Please provide window rect for likertScale!'); end - if isempty(durRating); error('Duration length of rating has to be specified!'); end - - %% Default values - inactive = 0; %should the irrelevant part of the scale be inactivated? - nRatingSteps = p.rating.division; - scaleWidth = 700; - textSize = 20; - lineWidth = 4; - scaleColor = [255 255 255]; - % if strcmp(type,'pain') - % activeColor = [255 0 0]; - % elseif strcmp(type,'relief') - % activeColor = [0 0 255]; - % else - % activeColor = [255 255 255]; - % end - activeColor = p.ptb.fc_color; - if isempty(defaultRating); defaultRating = round(nRatingSteps/2); end - if isempty(backgroundColor); backgroundColor = 0; end - - if inactive == 1 - defaultRating = ceil(nRatingSteps/2); - end - - % if length(ratingLabels) ~= nRatingSteps - % error('Rating steps and label numbers do not match') - % end - - %% Calculate rects - activeAddon_width = 1.5; - activeAddon_height = 20; - [xCenter, yCenter] = RectCenter(windowRect); - yCenter = StartY; - axesRect = [xCenter - scaleWidth/2; yCenter - lineWidth/2; xCenter + scaleWidth/2; yCenter + lineWidth/2]; - leftRect = [xCenter - scaleWidth/2; yCenter - lineWidth/2; xCenter; yCenter + lineWidth/2]; - rightRect = [xCenter; yCenter - lineWidth/2; xCenter + scaleWidth/2; yCenter + lineWidth/2]; - lowLabelRect = [axesRect(1),yCenter-20,axesRect(1)+6,yCenter+20]; - highLabelRect = [axesRect(3)-6,yCenter-20,axesRect(3),yCenter+20]; - ticPositions = linspace(xCenter - scaleWidth/2,xCenter + scaleWidth/2-lineWidth,nRatingSteps); - % ticRects = [ticPositions;ones(1,nRatingSteps)*yCenter;ticPositions + lineWidth;ones(1,nRatingSteps)*yCenter+tickHeight]; - activeTicRects = [ticPositions-activeAddon_width;ones(1,nRatingSteps)*yCenter-activeAddon_height;ticPositions + lineWidth+activeAddon_width;ones(1,nRatingSteps)*yCenter+activeAddon_height]; - %define text rects - if strcmp(type,'relief') - stringArray={ 'keine','Linderung','maximale','Linderung'}; - elseif strcmp(type,'pain') - stringArray={ 'kein','Schmerz','maximaler','Schmerz'}; - end - for i = 1:length(stringArray) - [~, ~, textBox] = DrawFormattedText(window,char(stringArray(i)),0,0,backgroundColor); - textWidths(i)=textBox(3)-textBox(1); - end - % keyboard - inactivecol = [130 130 130]; - - Screen('TextSize',window,textSize); - Screen('TextColor',window,[255 255 255]); - Screen('TextFont', window, 'Arial'); - currentRating = defaultRating; - finalRating = currentRating; - reactionTime = 0; - response = 0; - first_flip = 1; - startTime = GetSecs; - numberOfSecondsRemaining = durRating; - nrbuttonpresses = 0; - - %%%%%%%%%%%%%%%%%%%%%%% loop while there is time %%%%%%%%%%%%%%%%%%%%% - % tic; % control if timing is as long as durRating - while numberOfSecondsRemaining > 0 - Screen('FillRect',window,backgroundColor); - Screen('FillRect',window,scaleColor,axesRect); %draw white axis - Screen('FillRect',window,scaleColor,lowLabelRect); - Screen('FillRect',window,scaleColor,highLabelRect); - Screen('FillRect',window,activeColor,activeTicRects(:,currentRating)); - if strcmp(type,'pain') %we still differentiate between pain and relief so that they know whether it is pain NOW or relief experienced BEFORE - DrawFormattedText(window, 'Bitte bewerten Sie den momentanen Schmerz.', 'center',yCenter-100, scaleColor); - Screen('DrawText',window,'kein',axesRect(1)-textWidths(1)/2,yCenter+25,scaleColor); - Screen('DrawText',window,'Schmerz',axesRect(1)-textWidths(2)/2,yCenter+45,scaleColor); - Screen('DrawText',window,'maximaler',axesRect(3)-textWidths(3)/2,yCenter+25,scaleColor); - Screen('DrawText',window,'Schmerz',axesRect(3)-textWidths(4)/2,yCenter+45,scaleColor); - elseif strcmp(type,'relief') - DrawFormattedText(window, 'Bitte bewerten Sie die Wirksamkeit der Behandlung.', 'center',yCenter-100, scaleColor); - Screen('DrawText',window,'keine',axesRect(1)-textWidths(1)/2,yCenter+25,scaleColor); - Screen('DrawText',window,'Linderung',axesRect(1)-textWidths(2)/2,yCenter+45,scaleColor); - Screen('DrawText',window,'maximale',axesRect(3)-textWidths(3)/2,yCenter+25,scaleColor); - Screen('DrawText',window,'Linderung',axesRect(3)-textWidths(4)/2,yCenter+45,scaleColor); - end - - % Remove this line if a continuous key press should result in a continuous change of the scale - % while KbCheck; end - - if response == 0 - % set time 0 (for reaction time) - if first_flip == 1 - secs0 = Screen('Flip', window); % output Flip -> starttime rating - first_flip = 0; - % after 1st flip -> just flips without setting secs0 to null - else - Screen('Flip', window); - end - - [ keyIsDown, secs, keyCode ] = KbCheck; % this checks the keyboard very, very briefly. - Log(secs,7,keyCode); - if keyIsDown % only if a key was pressed we check which key it was - response = 0; % predefine variable for confirmation button 'space' - nrbuttonpresses = nrbuttonpresses + 1; - if keyCode(moreKey) % if it was the key we named key1 at the top then... - currentRating = currentRating + 1; - finalRating = currentRating; - response = 0; - if currentRating > nRatingSteps - currentRating = nRatingSteps; - end - elseif keyCode(lessKey) - currentRating = currentRating - 1; - finalRating = currentRating; - response = 0; - if currentRating < 1 - currentRating = 1; - end - elseif keyCode(confirmKey) - finalRating = currentRating-1; - disp(['VAS Rating: ' num2str(finalRating)]); - response = 1; - reactionTime = secs - secs0; - break; - end - end - end - - numberOfSecondsElapsed = (GetSecs - startTime); - numberOfSecondsRemaining = durRating - numberOfSecondsElapsed; - end - if nrbuttonpresses ~= 0 && response == 0 - finalRating = currentRating - 1; - reactionTime = durRating; - disp(['VAS Rating: ' num2str(finalRating)]); - fprintf('***********No Confirmation!***********\n'); - end - if nrbuttonpresses == 0 - finalRating = NaN; %NaN is NaN, no recoding necessary - reactionTime = durRating; - disp(['VAS Rating: ' num2str(finalRating)]); - warning(sprintf('\n***********No Response! Please check participant!***********\n')); - end - % toc - end - function ShowInstruction(nInstruct,waitforkeypress,varargin) - %ShowInstruction(nInstruct,waitforkeypress) - %if waitforkeypress is 1, ==> subject presses a button to proceed - %if waitforkeypress is 0, ==> text is shown for VARARGIN seconds. - - - [text]= GetText(nInstruct); - ShowText(text); - if waitforkeypress %and blank the screen as soon as the key is pressed - KbStrokeWait(p.ptb.device); - else - WaitSecs(varargin{1}); - end - Screen('FillRect',p.ptb.w,p.var.current_bg); - t = Screen('Flip',p.ptb.w); - - function ShowText(text) - - Screen('FillRect',p.ptb.w,p.var.current_bg); - DrawFormattedText(p.ptb.w, text, 'center', 'center',p.stim.white,[],[],[],2,[]); - t=Screen('Flip',p.ptb.w); - Log(t,-1,nInstruct); - %show the messages at the experimenter screen - fprintf('=========================================================\n'); - fprintf('Text shown to the subject:\n'); - fprintf(text); - fprintf('=========================================================\n'); - - end - end - function [text]=GetText(nInstruct) - if nInstruct == 0%Eyetracking calibration - text = ['Wir kalibrieren jetzt den Eye-Tracker.\n\n' ... - 'Bitte fixieren Sie die nun folgenden weißen Kreise und \n' ... - 'bleiben so lange darauf, wie sie zu sehen sind.\n\n' ... - 'Nach der Kalibrierung dürfen Sie Ihren Kopf nicht mehr bewegen.\n'... - 'Sollten Sie Ihre Position noch verändern müssen, tun Sie dies jetzt.\n'... - 'Die beste Position ist meist die bequemste.\n\n'... - 'Bitte drücken Sie jetzt die Leertaste, \n' ... - 'um mit der Kalibrierung weiterzumachen.\n' ... - ]; - elseif nInstruct == 1%first Instr. of the training phase. - text = ['Willkommen zum Experiment.\n' ... - '\n'... - 'Wir werden Ihnen nun als Erstes demonstrieren,\n'... - 'wie sich die Schmerzreize während des Experiments anfühlen werden. \n'... - 'Sie stellen gleich eine für Sie individuell angepasste konstante Temperatur ein, \n'... - 'um einen durchgängigen, aushaltbaren Schmerz zu erzeugen.\n'... - '\n'... - 'Drücken Sie die Leertaste um fortzufahren.\n' ... - ]; - elseif nInstruct == 11 - text = ['Sie erhalten nun die für Sie kalibrierte Temperatur.\n' ... - 'Nach einigen Sekunden werden Sie gebeten, diese auf einer Schmerzskala zu bewerten.\n' ... - 'Sie haben dazu 5 Sekunden Zeit.\n' ... - '\n' ... - 'Drücken Sie die Leertaste um zu starten.\n' ... - ]; - elseif nInstruct == 12 - text = ['Wir wiederholen den Vorgang noch einmal.\n' ... - 'Bitte geben Sie auf der Skala an, wie schmerzhaft Sie die gleich applizierte Temperatur empfinden.\n' ... - '\n' ... - 'Drücken Sie die Leertaste um zu starten.\n' ... - ]; - elseif nInstruct == 2%second Instr. of the training phase. - text = ['Sie erhalten nun vier TENS Behandlungsdurchgänge, um Ihnen die Wirksamkeit zu demonstrieren.\n' ... - 'Hierbei bewerten Sie nun in jedem Durchgang,\n' ... - 'wie gut der Schmerz durch diese Behandlung gelindert wird,\n' ... - 'd.h. als wie wirksam die Behandlung empfinden.\n' ... - 'Sie haben dazu wie immer 5 Sekunden Zeit, um zu antworten.\n' ... - 'Es ist sehr wichtig, dass Sie Ihr Rating innerhalb dieser Zeit abgeben und bestätigen.\n' ... - '\n'... - 'Drücken Sie die Leertaste um die Demonstration zu starten.\n' ... - ]; - elseif nInstruct == 3 - text = ['Als nächstes werden wir Ihnen demonstrieren,\n' ... - 'wie die verschiedenen Durchgänge im Hauptexperiment funktionieren.\n' ... - 'Ganz zu Beginn bewerten Sie einmalig auf der Schmerzskala,\n' ... - 'wie schmerzhaft die angebrachte Temperatur für Sie ist.\n' ... - 'Anschließend folgt der erste Behandlungsdurchgang.\n' ... - 'Bitte schauen Sie generell immer auf die Fixationskreuze, die Ihre Position hin und wieder ändern.\n' ... - '\n' ... - 'In jedem Durchgang wird Ihnen ein Gesicht präsentiert, das Sie aufmerksam betrachten sollen. \n' ... - 'Direkt nach dem Gesicht folgt die TENS Behandlung,\n'... - 'für die Sie anschließend wieder die Schmerzlinderung auf der gewohnten Skala bewerten.\n' ... - 'Es ist sehr wichtig, dass Sie Ihr Rating ganz intuitiv,\n' ... - 'aber innerhalb der gewohnten 5 Sekunden abgeben und bestätigen.\n' ... - '\n' ... - 'Beim ersten Durchgang erscheint kein Gesicht, dies ist beabsichtigt, wundern Sie sich also nicht.'... - '\n' ... - 'Drücken Sie die Leertaste um die Demonstration zu starten.\n' ... - ]; - elseif nInstruct == 299%short instruction before localizer - text = ['Die Kalibrierung war erfolgreich.\n'... - 'Es startet nun eine kurze Vormessung (~2 min), während der Sie nichts tun müssen.\n\n'... - ]; - elseif nInstruct == 4 %Instr. for the very first phase. - text = ['Willkommen zum Hauptteil des Experiments.\n' ... - 'Auch in diesem Teil des Experiments erhalten Sie einen durchgängigen Schmerzreiz, \n'... - 'der in jedem Durchgang durch eine TENS Behandlung gelindert wird.\n' ... - 'Wie zuvor geübt bewerten Sie hin und wieder den Schmerzreiz, sowie in jedem Durchgang die Schmerzlinderung.\n' ... - '\n' ... - 'Wir verwenden ab jetzt unterschiedliche TENS-Frequenzen, von denen eine spürbar besser ist als der Rest.\n' ... - '\n'... - 'Genau wie im vorherigen Durchgang sehen Sie vor jedem Behandlungsdurchgang ein Gesicht.\n'... - 'Dieses sollen Sie aufmerksam betrachten.\n'... - 'Nur EINS der Gesichter wird mit der besseren TENS Behandlung gepaart.\n'... - 'Sie werden also bemerken, dass unterschiedliche Gesichter unterschiedlich gute Behandlungen ankündigen.\n'... - '\n'... - 'Beim ersten Durchgang jeden Blocks erscheint kein Gesicht, dies ist beabsichtigt, wundern Sie sich also nicht.'... - '\n'... - 'Drücken Sie die Leertaste um fortzufahren.\n' ... - ]; - elseif nInstruct == 400% - text = ['Wir sind jetzt kurz vor Beginn des Experiments.\n'... - 'Wenn Sie noch Fragen haben, wenden Sie sich jetzt an die Versuchleiterin. \n'... - 'Ansonsten möchten wir Sie nun noch an die wichtigsten Punkte erinnern.\n\n'... - 'Drücken Sie jeweils die Leertaste um fortzufahren.\n' ... - ]; - elseif nInstruct == 44%short Instr. for following phases - text = ['Es folgt nun der nächste Durchgang.\n'... - 'Wenn Sie noch Fragen haben, wenden Sie sich jetzt an die Versuchleiterin. \n'... - '\n\n'... - 'Drücken Sie die Leertaste um zu starten.\n' ... - ]; - elseif nInstruct == 401%third Instr. of the training phase. - text = ['1. Blicken Sie immer auf die Fixationskreuze.\n'... - ]; - elseif nInstruct == 402%third Instr. of the training phase. - text = ['2. Bewerten Sie die Schmerzwahrnehmung immer wenn Sie danach gefragt werden.\n'... - ]; - elseif nInstruct == 403%third Instr. of the training phase. - text = ['3. Bewerten Sie die Linderung in jedem Durchgang (bei Erscheinen der Skala).\n'... - ]; - elseif nInstruct == 404%third Instr. of the training phase. - text = ['4. Eins der Gesichter wird mit der besseren TENS Frequenz gepaart.\n'... - ]; - elseif nInstruct == 405%third Instr. of the training phase. - text = ['5. Es ist allein Ihre Wahrnehmung gefragt, es gibt kein richtig oder falsch.\n'... - ]; - elseif nInstruct == 406%third Instr. of the training phase. - text = ['Drücken Sie jetzt die Leertaste, das Experiment startet dann in wenigen Sekunden.\n' ... - ]; - elseif nInstruct == 20 - text = ['Demo beendet. Vielen Dank! \n']; - - elseif nInstruct == 21 - text = ['Durchgang beendet. Vielen Dank! \n']; - - elseif nInstruct == 8;%AskDetectionSelectable - text = ['Sie sehen nun noch einmal eine Übersicht der verschiedenen Gesichter.\n'... - 'Bitte geben Sie an, welches der Gesichter Ihrer Meinung nach\n mit der optimalen TENS Behandlung gepaart wurde.\n\n'... - 'Nutzen Sie die linke und rechte Taste, um die Markierung\n zum richtigen Gesicht zu navigieren,\n'... - 'und drücken Sie die Leertaste zum Bestätigen.\n\n'... - 'Bitte zum Starten die Leertaste drücken.\n'... - ]; - elseif nInstruct == 801;%AskDetectionSelectable - text = ['Sie sehen nun eine Übersicht der verschiedenen Gesichter.\n'... - 'Bitte schauen Sie sich die Gesichter aufmerksam an.\n'... - 'Bitte drücken Sie zum Start die Leertaste und\n' ... - 'fixieren Sie das anschließend erscheinende Fixationskreuz.\n'... - ]; - elseif nInstruct == 9; % Rising Temp - text = ['Temperatur wird angepasst... \n']; - elseif nInstruct == 14 - text = ['Danke. Den aktiven Teil des Experiment haben Sie nun geschafft.\n'... - 'Es folgt nun noch eine strukturelle Messung, die ca. 7 Minuten dauert.\n'... - 'Sie können dabei ruhig die Augen schließen und sich entspannen.\n']; - else - text = {''}; - end - end - function [t]=StopEyelinkRecording - Eyelink('StopRecording'); - t = GetSecs; - %this is the end of the trial scope. - WaitSecs(0.01); - Eyelink('Message', 'TRIAL_RESULT 0'); - % - WaitSecs(0.01); - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('Command', 'clear_screen %d', 0); - Screen('Textsize', p.ptb.w,p.text.fontsize); - Log(t,8,NaN); - end - function [t]=StartEyelinkRecording(nTrial,nStim,phase,dist,oddball,ucs,fix,block_id) - t = []; - if isnan(dist) - dist=3000; - end - nStim = double(nStim); - Eyelink('Message', 'TRIALID: %04d, PHASE: %04d, FILE: %04d, DELTACSP: %04d, ODDBALL: %04d, UCS: %04d, FIXX: %04d, FIXY %04d, MBLOCK %04d', nTrial, phase, nStim, dist, double(oddball), double(ucs),fix(1),fix(2),block_id); - Eyelink('Message', 'FX Onset at %d %d',fix(1),fix(2)); - % an integration message so that an image can be loaded as - % overlay background when performing Data Viewer analysis. - WaitSecs(0.01); - %return - if nStim~=0 - Eyelink('Message', '!V IMGLOAD CENTER %s %d %d', p.stim.files(nStim,:), p.ptb.midpoint(1), p.ptb.midpoint(2)); - end - % This supplies the title at the bottom of the eyetracker display - Eyelink('Command', 'record_status_message "Stim: %02d, Phase: %d"', nStim, phase); - % - %Put the tracker offline and draw the stimuli. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - % clear tracker display and draw box at center - Eyelink('Command', 'clear_screen %d', 0); - %draw the image on the screen but also the two crosses - if (nStim <= 16 && nStim>0) - Eyelink('ImageTransfer',p.stim.files24(nStim,:),p.ptb.imrect(1),p.ptb.imrect(2),p.stim.width,p.stim.height,p.ptb.imrect(1),p.ptb.imrect(2),0); - end - Eyelink('Command', 'draw_cross %d %d 15',fix(1),fix(2)); - Eyelink('Command', 'draw_cross %d %d 15',fix(1),fix(2)+diff(p.ptb.cross_shift)); - - % - %drift correction - %EyelinkDoDriftCorrection(el,crosspositionx,crosspositiony,0,0); - %start recording following mode transition and a short pause. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('StartRecording'); - t = GetSecs; - Log(t,2,NaN); - end - function [shuffled idx] = Shuffle(vector,N) - %takes first N from the SHUFFLED before outputting. This function - %could be used as a replacement for randsample - if nargin < 2;N = length(vector);end - [~, idx] = sort(rand([1 length(vector)])); - shuffled = vector(idx(1:N)); - shuffled = shuffled(:); - end - function [cross_positions]=FixationCrossPool - radius = 290; %in px (around 14 degrees (37 px/deg)) - center = [960 600]; - - %setting up fixation cross pool vector of size - % totaltrials x 4 (face_1_x face_1_y face_2_x face_2_y) - cross_directions = round(rand(p.presentation.tTrial,1))*180; - dummy = cross_directions + rand(p.presentation.tTrial,1)*30-15; - cross_positions = [cosd(dummy(:,1))*radius+center(1) sind(dummy(:,1))*radius+center(2)]; - % cross_positions = [cosd(dummy(:,1))*radius+center(1) sind(dummy(:,1))*radius+center(2)... - % cosd(dummy(:,2))*radius+center(1) sind(dummy(:,2))*radius+center(2)]; - end - function [a]=MinimumAngle(y,x); - %[a]=MinimumAngle(x,y); - % - %finds the minimum angle between two angles given in degrees, the answer is - %also in degrees. The clockwise distances from Y to X are considered as - %positive. Opposite angles are considered as positive 180. - - x = deg2rad(x); - y = deg2rad(y); - - a = atan2(sin(x-y), cos(x-y)); - - a = -round(rad2deg(a)); - - if any(abs(a) == 180); - a(abs(a) == 180) = 180; - end - end - function MarkCED(socket,port) - %send pulse to SCR# - outp(socket,port); - WaitSecs(0.01); - outp(socket,0); - end - function [countedDown]=CountDown(secs, countedDown, countString) - if secs>countedDown - fprintf('%s', countString); - countedDown=ceil(secs); - end - end - function InitEyeLink - % - if EyelinkInit(0)%use 0 to init normaly - fprintf('=================\nEyelink initialized correctly...\n') - else - fprintf('=================\nThere is problem in Eyelink initialization\n') - keyboard; - end - % - WaitSecs(0.5); - [~, vs] = Eyelink('GetTrackerVersion'); - fprintf('=================\nRunning experiment on a ''%s'' tracker.\n', vs ); - - %load 24bits pictures for eyelink... - dummy = dir([p.path.stim24 '*.bmp']); - p.stim.files24 = [repmat([fileparts(p.path.stim24) filesep],length(dummy),1) vertcat(dummy(:).name)]; - % - el = EyelinkInitDefaults(p.ptb.w); - %update the defaults of the eyelink tracker - el.backgroundcolour = p.stim.bg; - el.msgfontcolour = WhiteIndex(el.window); - el.imgtitlecolour = WhiteIndex(el.window); - el.targetbeep = 0; - el.calibrationtargetcolour = WhiteIndex(el.window); - el.calibrationtargetsize = 1.5; - el.calibrationtargetwidth = 0.5; - el.displayCalResults = 1; - el.eyeimgsize = 50; - el.waitformodereadytime = 25;%ms - el.msgfont = 'Times New Roman'; - el.cal_target_beep = [0 0 0];%[1250 0.6 0.05]; - %shut all sounds off - el.drift_correction_target_beep = [0 0 0]; - el.calibration_failed_beep = [0 0 0]; - el.calibration_success_beep = [0 0 0]; - el.drift_correction_failed_beep = [0 0 0]; - el.drift_correction_success_beep= [0 0 0]; - EyelinkUpdateDefaults(el); - PsychEyelinkDispatchCallback(el); - - % open file. - res = Eyelink('Openfile', p.path.edf); - % - Eyelink('command', 'add_file_preamble_text ''Recorded by EyelinkToolbox FearAmy Experiment (Selim Onat)'''); - Eyelink('command', 'screen_pixel_coords = %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - Eyelink('message', 'DISPLAY_COORDS %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - % set calibration type. - Eyelink('command','auto_calibration_messages = YES'); - Eyelink('command', 'calibration_type = HV13'); - Eyelink('command', 'select_parser_configuration = 1'); - %what do we want to record - Eyelink('command', 'file_sample_data = LEFT,RIGHT,GAZE,HREF,AREA,GAZERES,STATUS,INPUT,HTARGET'); - Eyelink('command', 'file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON,INPUT'); - Eyelink('command', 'use_ellipse_fitter = no'); - % set sample rate in camera setup screen - Eyelink('command', 'sample_rate = %d',1000); - end - function StopEyelink(filename) - try - fprintf('Trying to stop the Eyelink system with StopEyelink\n'); - Eyelink('StopRecording'); - Log(t,8,NaN); - WaitSecs(0.5); - Eyelink('Closefile'); - display('receiving the EDF file...'); - Eyelink('ReceiveFile',filename,p.path.path_edf,1); - display('...finished!') - % Shutdown Eyelink: - Eyelink('Shutdown'); - catch - display('StopEyeLink routine didn''t really run well'); - end - end - function cleanup - % Close window: - sca; - %set back the old resolution - if strcmp(p.hostname,'triostim1') - % Screen('Resolution',p.ptb.screenNumber, p.ptb.oldres.width, p.ptb.oldres.height ); - %show the cursor - ShowCursor(p.ptb.screenNumber); - end - % - commandwindow; - KbQueueStop(p.ptb.device); - KbQueueRelease(p.ptb.device); - if arduino - fclose(s); - end - end - function CalibrateEL - fprintf('=================\n=================\nEntering Eyelink Calibration\n') - p.var.ExpPhase = 0; - ShowInstruction(0,1); - EyelinkDoTrackerSetup(el); - %Returns 'messageString' text associated with result of last calibration - [~, messageString] = Eyelink('CalMessage'); - Eyelink('Message','%s',messageString);% - WaitSecs(0.05); - fprintf('=================\n=================\nNow we are done with the calibration\n') - end - function Log(ptb_time, event_type, event_info) - %Phases: - %Instruction : 0 - %Test : 1 - %Rating : 5 - %Calibration : 0 - % - %event types are as follows: - % %Pulse Detection : 0 info: NaN; - % %Tracker Onset : 1 - % %Cross (tonic) Onset : 2 info: position - % %Cross (pain) Onset : 3 info: position - % %Ramp down Onset : 4 info: ror - % %Treatment Plateau : 5 info: temp - % %Ramp back onset : 6 info: ror; - % %Key Presses : 7 info: NaN; - % %Tracker Offset : 8 info: NaN; - % %Rate pain Onset : 9 info: NaN; - % %Rate pain Offset : 10 info: NaN; - % %Rate treat Onset : 11 info: NaN; - % %Rate treat Offset : 12 info: NaN; - % %Face Onset : 13 info: stim_id; - % %Face Offset : 14 info: stim_id; - % %FaceStim Fixcross : 15 info: position - % %dummy fixflip : 22 info: NaN; - %Text on the screen : -1 info: Which Text? - %VAS Onset : -2 info: NaN; - for iii = 1:length(ptb_time) - p.var.event_count = p.var.event_count + 1; - p.out.log(p.var.event_count,:) = [ptb_time(iii) event_type event_info(iii) p.var.ExpPhase]; - end - % plot(p.out.log(1:p.var.event_count,1) - p.out.log(1,1),p.out.log(1:p.var.event_count,2),'o','markersize',10); - % ylim([-2 8]); - % set(gca,'ytick',[-2:8],'yticklabel',{'Rating On','Text','Pulse','Tracker+','Cross+','Stim+','CrossMov','UCS','Stim-','Key+','Tracker-'}); - % grid on - % drawnow; - - end - function [secs]=WaitPulse(keycode,n) - %[secs]=WaitPulse(keycode,n) - % - % This function waits for the Nth upcoming pulse. If N=1, it will wait for - % the very next pulse to arrive. 1 MEANS NEXT PULSE. So if you wish to wait - % for 6 full dummy scans, you should use N = 7 to be sure that at least 6 - % full acquisitions are finished. - % - % The function avoids KbCheck, KbWait functions, but relies on the OS - % level event queues, which are much less likely to skip short events. A - % nice discussion on the topic can be found here: - % http://ftp.tuebingen.mpg.de/pub/pub_dahl/stmdev10_D/Matlab6/Toolboxes/Psychtoolbox/PsychDocumentation/KbQueue.html - - %KbQueueFlush;KbQueueStop;KbQueueRelease;WaitSecs(1); - fprintf('Will wait for %i dummy pulses...\n',n); - if n ~= 0 - secs = nan(1,n); - pulse = 0; - dummy = []; - while pulse < n - dummy = KbTriggerWait(keycode,p.ptb.device); - pulse = pulse + 1; - secs(pulse+1) = dummy; - Log(dummy,0,NaN); - end - else - secs = GetSecs; - end - end - function [keycode, secs] = KbQueueDump; - %[keycode, secs] = KbQueueDump - % Will dump all the events accumulated in the queue. - - keycode = []; - secs = []; - pressed = []; - %fprintf('there are %03d events\n',KbEventAvail(p.ptb.device)); - while KbEventAvail(p.ptb.device) - [evt, n] = KbEventGet(p.ptb.device); - n = n + 1; - keycode(n) = evt.Keycode; - pressed(n) = evt.Pressed; - secs(n) = evt.Time; - % fprintf('Event is: %d\n',keycode(n)); - end - i = pressed == 1; - keycode(~i) = []; - secs(~i) = []; - %fprintf('there are %03d events found...\n',length(keycode)); - end -end diff --git a/exp_treatgen_PMF.m b/exp_treatgen_PMF.m deleted file mode 100644 index a212aeb..0000000 --- a/exp_treatgen_PMF.m +++ /dev/null @@ -1,1049 +0,0 @@ -function [p]=exp_treatgen_PMF(subject,phase,csp) - -% Same/different discrimination task estimating the perceptual threshold alpha of an -% observer's underlying Psychometric Function (PF), using the method of constant stimuli. -% Input: -% subject = subject number -% phase = phase number, will only name the logfile folder -% csp = CS+ Face as ID (i.e. 1 to 8) -% -% Note: Two "chains" are run intertwinedly, i.e. trials for CS+ are mixed -% with trials for CS-. Chain 1 refers to CS+, Chain 2 to CS-. -% -% adapted by LK in 10/2016 for use on any computer - -EyelinkWanted = 0; %is Eyelink wanted? -fixjump = 0; %fixation cross starts at eyes and jumps to mouth - %(see variable fix_start). - -% make a break every ....th Trial -breakpoint = 40; - -ListenChar(2);%disable unwanted keypresses -commandwindow; -%clear everything -clear mex global functions -cgshut; -global cogent; -%%%%%%%%%%%load the GETSECS mex files so call them at least once -GetSecs; -WaitSecs(0.001); - -el = []; -p = []; -SetParams; -SetPTB; - -if EyelinkWanted - InitEyeLink; - WaitSecs(2); - ShowInstruction(1); - CalibrateEL; -else - WaitSecs(2); - ShowInstruction(11); -end - -SetupLog; -%save the parameter file once now -save(p.path.path_param,'p'); -if EyelinkWanted - ShowInstruction(3); -end -% counter for within chain trials (cc) and global trials (tt) -cc = zeros(1,tchain); -tt = 0; -%trialID is counting every single face (2 per Trial_YN), need that for -%Eyelink -trialID = 0; - -STOP = 0; -while ~STOP - chains = find(cc1 - current_chain = randsample(chains,[1 1]); - end - if tt~=tchain*p.psi.presentation.numtrials_chain - tt=tt+1; - % enter in break loop - if (tt~=1 && mod(tt,breakpoint)==1); - save(p.path.path_param,'p'); - ShowInstruction(4); - %calibrate if Eyelink - if EyelinkWanted - CalibrateEL; - end - end - cc(current_chain)=cc(current_chain)+1; - % Chain 1 is CS+, Chain 2 is CS-. - fprintf('Chain %4.2f, Chain trial %03d/%03d...',current_chain,cc(current_chain),p.psi.presentation.numtrials_chain) - %Present trial here at stimulus intensity x and collect response - fprintf('Intensity x is now %4.2f \n',x(cc(current_chain),current_chain)) - test = x(cc(current_chain),current_chain) + csn_shift(current_chain) + p.stim.cs_plus; - dummy = test; - test = mod(test,360); - % the reference is csp or csn - ref = csn_shift(current_chain) + p.stim.cs_plus; - ref = mod(ref,360); - % start Trial - fprintf('Starting Trial %03d/%03d.\n',tt,tchain*p.psi.presentation.numtrials_chain) - [test_face, ref_face, signal,trialID] = Trial_YN(trialID,ref,test,p.stim.tFace,tt); - % ask subject for answer - fprintf('Rating.\n') - Screen('Textsize', p.ptb.w,p.text.fontsize); - % put Rating there - message1 = 'Waren die Gesichter unterschiedlich oder gleich?\n'; - message2 = 'Bewegen Sie den "Zeiger" mit der rechten und linken Pfeiltaste\n und bestätigen Sie Ihre Einschätzung mit der oberen Pfeiltaste.'; - - rect = [p.ptb.width*0.2 p.ptb.midpoint(2) p.ptb.width*0.6 100]; - [response_subj] = RatingSlider(rect,2,Shuffle(1:2,1),p.keys.increase,p.keys.decrease,p.keys.confirm,{ 'unterschiedlich' 'gleich'},message1,message2,0); - % see if subject found the different pair of faces... - % buttonpress left (Yes) is response_subj=2, right alternative - % (No) outputs a 1, this will be transformed here. - % note that response == 1 only means "yes", but not necessarily - % "correct" - sdt = NaN; - if (response_subj == 2 && signal == 1) - response = 1; - fprintf('...Hit. \n') - sdt=1; - elseif (response_subj==1 && signal == 1) - response = 0; - fprintf('...Miss. \n') - sdt=3; - elseif (response_subj == 2 && signal==0) - response = 1; - fprintf('...False Alarm. \n') - sdt=2; - elseif (response_subj == 1 && signal == 0) - response = 0; - fprintf('...Correct Rejection. \n') - sdt=4; - else - warning('error in the answer algorithm! \n') - end - - % store everything in the Log - row = find(unique(x)==x(cc(current_chain),current_chain)); - p.psi.log.trial_counter(row,current_chain) = p.psi.log.trial_counter(row,current_chain) + 1; - p.psi.log.xrounded(row,p.psi.log.trial_counter(row,current_chain),current_chain) = response; - SetLog; - %iteration control - STOP = sum(cc >= p.psi.presentation.numtrials_chain) == tchain; - end - %final save of parameter-/logfile - save(p.path.path_param,'p'); -end - -%end of Experiment, show text to subject -ShowInstruction(2); -%get the eyelink file back to this computer -if EyelinkWanted - StopEyelink(p.path.edf); -end - -%close everything down -cleanup; -%move the folder to appropriate location -movefile(p.path.subject,p.path.finalsubject); - - function [test_face,ref_face,signal,trialID] = Trial_YN(trialID,ref_stim,test_stim,last_face_of_circle,tt) - Screen('Textsize', p.ptb.w,p.text.fixsize); - % computes the trial FACES, using the test/ref information input - % values (in Deg) - - trial = [ref_stim test_stim]/p.stim.delta; - % correct face number within circle - trial = mod(round(trial),last_face_of_circle)+1; - ref_face = trial(1); - test_face = trial(2); - [trial,idx]= Shuffle(trial); - fprintf('Faces: %d %d \n',trial(1),trial(2)); - %compute if trial had different faces or not - %if trial(1)=trial(2), they were the same and subject has to - %answer with 'no' (right option, is 1), else means correct hit - - if trial(1)==trial(2) - signal = 0; - else - signal = 1; - end - - - trial_deg = [ref_stim test_stim]; - isref = double(trial==ref_face) ; - delta_ref = MinimumAngleQuartile([trial_deg(idx(1)) trial_deg(idx(2))],ref); - delta_csp = MinimumAngleQuartile([trial_deg(idx(1)) trial_deg(idx(2))],p.stim.cs_plus); % ... - abs_FGangle = [trial_deg(idx(1)) trial_deg(idx(2))]; - - trialID=trialID+1; - - %get fixation crosses and onsets from p parameter - - - %GetSecs so that the onsets can be defined - if fixjump ==1 - onsets = 0.25+GetSecs; %fix1 onset - onsets = [onsets onsets(end)+p.duration.fix+rand(1)*.25];%stim1 onset - onsets = [onsets onsets(end)+p.duration.crossmoves]; %fix jump - onsets = [onsets onsets(end)+p.duration.crossmoves]; %stim offset - fixdelta = p.duration.fix+rand(1)*.25; - onsets = [onsets onsets(end)+p.duration.isi-fixdelta]; %fix2 onset - onsets = [onsets onsets(end)+fixdelta]; %stim2 onset - onsets = [onsets onsets(end)+p.duration.crossmoves]; %fix jump - onsets = [onsets onsets(end)+p.duration.crossmoves]; %stim offset - else - onsets = 0.25+GetSecs;%fix1 onset - onsets = [onsets onsets(end)+p.duration.fix+rand(1)*.25];%stim1 onset - onsets = [onsets onsets(end)+p.duration.stim];%stim1 offset - fixdelta = p.duration.fix+rand(1)*.25; - onsets = [onsets onsets(end)+p.duration.isi-fixdelta];%fix2 onset - onsets = [onsets onsets(end)+fixdelta];%stim2 onset - onsets = [onsets onsets(end)+p.duration.stim];%stim2 offset - end - - if fixjump ==1 - fix_i = p.psi.presentation.fix_start(cc(current_chain),current_chain); - fix = round([p.ptb.CrossPosition_x p.ptb.CrossPosition_y(fix_i)]); - FixCross = [fix(1)-1,fix(2)-p.ptb.fc_size,fix(1)+1,fix(2)+p.ptb.fc_size;fix(1)-p.ptb.fc_size,fix(2)-1,fix(1)+p.ptb.fc_size,fix(2)+1]; - %fixation cross 1 - %FixCross = [fix(1,1)-1,fix(1,2)-p.ptb.fc_size,fix(1,1)+1,fix(1,2)+p.ptb.fc_size;fix(1,1)-p.ptb.fc_size,fix(1,2)-1,fix(1,1)+p.ptb.fc_size,fix(1,2)+1]; - Screen('FillRect', p.ptb.w, [255,255,255], FixCross'); - if EyelinkWanted - Eyelink('Message', 'FX Onset at %d %d',fix(1),fix(2)); - end - Screen('Flip',p.ptb.w,onsets(1),0); - if EyelinkWanted - StartEyelinkRecording(trialID,phase,cc(current_chain),tt,current_chain,isref(1),trial(1),delta_ref(1),delta_csp(1),abs_FGangle(1),fix(1,1),fix(1,2)); - end - %face trial(1) - Screen('DrawTexture',p.ptb.w,p.ptb.stim_sprites(trial(1))); - Screen('FillRect', p.ptb.w, [255,255,255], FixCross'); - Screen('Flip',p.ptb.w,onsets(2),0); - if EyelinkWanted - Eyelink('Message', 'Stim Onset'); - Eyelink('Message', 'SYNCTIME'); - end - %fixJUMP trial(1) - fix = [p.ptb.CrossPosition_x p.ptb.CrossPosition_y(setdiff(1:2,fix_i))];%take the other position - FixCross = [fix(1)-1,fix(2)-p.ptb.fc_size,fix(1)+1,fix(2)+p.ptb.fc_size;fix(1)-p.ptb.fc_size,fix(2)-1,fix(1)+p.ptb.fc_size,fix(2)+1]; - %FixCross = [fix(2,1)-1,fix(2,2)-p.ptb.fc_size,fix(2,1)+1,fix(2,2)+p.ptb.fc_size; fix(2,1)-p.ptb.fc_size,fix(2,2)-1,fix(2,1)+p.ptb.fc_size,fix(2,2)+1]; - Screen('DrawTexture',p.ptb.w,p.ptb.stim_sprites(trial(1))); - Screen('FillRect', p.ptb.w, [255,255,255], FixCross'); - Screen('Flip',p.ptb.w,onsets(3),0); - while GetSecscross2onset->onset2shock->shock2offset - %these (duration.BLA) are average duration values: - % 1.5 0.5 0.5 - p.duration.stim = 1.5;%s - p.duration.fix = .7; - p.duration.crossmoves = p.duration.stim./2; - p.duration.isi = 1.0; - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - %create the randomized design - p.stim.csp_id = csp; - csp_degree = mod((p.stim.csp_id-1) * 45,360); - p.stim.cs_plus = csp_degree;%index of cs stimulus, this is the one paired to shock in the main experiment - %p.stim.cs_neg = csn; - - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %Set up Constant Stimuli procedure - csn_shift = [0 180]; - tchain = 2; - interval = 22.5; - maxdegree = 180; - maxtrials = 80; % this will be exceeded, if addzeros > 0 - addzeros = 0; - - tsteps = (2*maxdegree./interval)+1; - if maxdegree == 180 - tsteps = tsteps - 2;%spares out the CSN - end - rep = floor(maxtrials./(tsteps+1));%+1 so that zero can be doubled... - steps = [repmat(0:interval:180-interval,1,rep) repmat(0:interval:180-interval,1,rep)*-1 zeros(1,addzeros)]; - % we chose to have higher resolution around zero and take this from - % the easiest intensity level, i.e. replace 157.5 - steps(steps== 157.5) = 11.25; - steps(steps== -157.5) = -11.25; - - for n = 1:tchain - x(:,n) = Shuffle(steps); - fix_start(:,n) = ones(length(x(:,n)),1)*2; %1 = mouth2eye, 2 = eye2mouth - end - - fprintf('This is the distribution of stimuli we will use:\n') - histi = histc(x,unique(x)); - uniquex = unique(x); - for l = 1:length(unique(x)) - fprintf('Level %+ 7.2f: %02d repetitions. \n',uniquex(l,1),histi(l,1)) - end - fprintf('---------------------------\nTotal trials: %03d per chain.\n',sum(histi(:,1))) - WaitSecs(3); - %store everything in p - p.psi.presentation.x = x; - p.psi.presentation.interval = interval; - p.psi.presentation.numtrials_chain = length(x(:,1)); - p.psi.presentation.tsteps = tsteps; - p.psi.presentation.rep = histi(:,1); - p.psi.presentation.uniquex = unique(x); - p.psi.presentation.fix_start = fix_start; - p.var.current_bg = p.stim.bg;%current background to be used. - %Save the stuff - save(p.path.path_param,'p'); - % - - end - function [rating]=RatingSlider(rect,tSection,position,up,down,confirm,labels,message1,message2,numbersOn) - % - %Detect the bounding boxes of the labels. - for nlab = 1:2 - [nx, ny, bb(nlab,:)]=DrawFormattedText(p.ptb.w,labels{nlab}, 'center', 'center', p.stim.white,[],[],[],2); - Screen('FillRect',p.ptb.w,p.stim.bg); - end - bb = max(bb); - bb_size = bb(3)-bb(1);%vertical size of the bb. - % - DrawSkala; - ok = 1; - while ok == 1 - [secs, keyCode, deltaSecs] = KbStrokeWait; - - keyCode = find(keyCode); - if (keyCode == up) | (keyCode == down) - next = position + increment(keyCode); - if next < (tSection+1) & next > 0 - position = position + increment(keyCode); - rating = tSection - position + 1; - end - DrawSkala; - elseif keyCode == confirm - WaitSecs(0.1); - ok = 0; - Screen('FillRect',p.ptb.w,p.stim.bg); - Screen('Flip',p.ptb.w); - end - end - - function DrawSkala - rating = tSection - position + 1; - increment([up down]) = [1 -1];%delta - tick_x = linspace(rect(1),rect(1)+rect(3),tSection+1);%tick positions - tick_size = rect(3)./tSection; - ss = tick_size/5*0.9;%slider size. - % - for tick = 1:length(tick_x)%draw ticks - Screen('DrawLine', p.ptb.w, [255 0 0], tick_x(tick), rect(2), tick_x(tick), rect(2)+rect(4) , 3); - if tick <= tSection && numbersOn - Screen('TextSize', p.ptb.w,p.text.fontsize./2); - DrawFormattedText(p.ptb.w, mat2str(tick) , tick_x(tick)+ss/2, rect(2)+rect(4), p.stim.white); - Screen('TextSize', p.ptb.w,p.text.fontsize); - end - if tick == 1 - DrawFormattedText(p.ptb.w, labels{1},tick_x(tick)-bb_size*1.6,rect(2), p.stim.white); - elseif tick == tSection+1 - DrawFormattedText(p.ptb.w, labels{2},tick_x(tick)+bb_size*0.2,rect(2), p.stim.white); - end - end - %slider coordinates - slider = [ tick_x(position)+tick_size*0.1 rect(2) tick_x(position)+tick_size*0.9 rect(2)+rect(4)]; - %draw the slider - Screen('FillRect',p.ptb.w, p.stim.white, round(slider)); - Screen('TextSize', p.ptb.w,p.text.fontsize); - DrawFormattedText(p.ptb.w,message1, 'center', p.ptb.midpoint(2)*0.2, p.stim.white,[],[],[],2); - Screen('TextSize', p.ptb.w,p.text.fontsize./2); - DrawFormattedText(p.ptb.w,message2, 'center', p.ptb.midpoint(2)*0.4, p.stim.white,[],[],[],2); - Screen('TextSize', p.ptb.w,p.text.fontsize); - Screen('Flip',p.ptb.w); - end - end - - function [shuffled,idx] = Shuffle(vector,N) - %takes first N from the SHUFFLED before outputting. This function - %could be used as a replacement for randsample - if nargin < 2;N = length(vector);end - [dummy, idx] = sort(rand([1 length(vector)])); - shuffled = vector(idx(1:N)); - shuffled = shuffled(:); - end - - function [a]=MinimumAngleQuartile(y,x) - %[a]=MinimumAngle(x,y); - % - %finds the minimum angle between two angles given in degrees, the answer is - %also in degrees. The clockwise distances from Y to X are considered as - %positive. Opposite angles are considered as positive 180. - - x = deg2rad(x); - y = deg2rad(y); - - a = atan2(sin(x-y), cos(x-y)); - - a = -round(((180/pi)*a)*4)/4; - - if any(abs(a) == 180); - a(abs(a) == 180) = 180; - end - end - - function ShowInstruction(nInstruct) - - [text]=GetText(nInstruct); - ShowText(text); - %let subject read it and ask confirmation to proceed. - if nInstruct ~= 2 - KbStrokeWait; - else - WaitSecs(2) - end - Screen('FillRect',p.ptb.w,p.stim.bg); - Screen('Flip',p.ptb.w); - - end - function ShowText(text) - - - Screen('FillRect',p.ptb.w,p.stim.bg); - %DrawFormattedText(p.ptb.w, text, p.text.start_x, 'center',p.stim.white,[],[],[],2,[]); - DrawFormattedText(p.ptb.w, text, 'center', 'center',p.stim.white,[],[],[],2,[]); - Screen('Flip',p.ptb.w); - - %show the messages at the experimenter screen - fprintf([repmat('=',1,50) '\n']); - fprintf('Subject''s monitor:\n'); - fprintf(text); - fprintf([repmat('=',1,50) '\n']); - - end - - - function [text]=GetText(nInstruct) - - if nInstruct == 0%Eyetracking calibration - - text = ['Um Ihre Augenbewegungen zu messen, \n' ... - 'müssen wir jetzt den Eye-Tracker kalibrieren.\n' ... - 'Dazu zeigen wir Ihnen einige Punkte auf dem Bildschirm, \n' ... - 'bei denen Sie sich wie folgt verhalten:\n' ... - 'Bitte fixieren Sie den Fixationspunkt und \n' ... - 'bleiben Sie so lange darauf, wie er zu sehen ist.\n' ... - 'Bitte drücken Sie jetzt den oberen Knopf, \n' ... - 'um mit der Kalibrierung weiterzumachen.\n' ... - ]; - - elseif nInstruct == 1 - text = ['In diesem Experiment sehen Sie nacheinander jeweils zwei Gesichter.\n'... - 'Danach werden Sie gefragt, ob die Gesichter unterschiedlich oder gleich waren.\n'... - '\n'... - 'Benutzen Sie zum Antworten die Pfeiltasten (links, rechts) und die Leertaste zum Bestätigen.\n'... - '\n'... - 'Sie erhalten in diesem Teil keine Schmerzreize.\n'... - 'Folgen Sie aber bitte auch hier streng den Fixationskreuzen!\n'... - '\n'... - 'Sie werden alle ' num2str(breakpoint) ' Durchgänge eine Pause machen können,\nnach der der Eyetracker neu kalibriert wird.\n'... - 'Das heißt, Sie können in der Pause den Kopf ruhig aus der Kopfstütze nehmen und sich entspannen. \n'... - '\n'... - 'Wenn Sie noch Fragen haben, können Sie jetzt die Versuchsleiter/in fragen.\n'... - '\n'... - 'Drücken Sie ansonsten die Leertaste,\n'... - ' um das Experiment zu starten.\n' ... - ]; - elseif nInstruct == 11 - text = ['In diesem Experiment sehen Sie nacheinander jeweils zwei Gesichter.\n'... - 'Danach werden Sie gefragt, ob die Gesichter unterschiedlich oder gleich waren.\n'... - '\n'... - 'Benutzen Sie zum Antworten die Pfeiltasten (links, rechts) und die Leertaste zum Bestätigen.\n'... - '\n'... - 'Sie erhalten in diesem Teil keine Schmerzreize.\n'... - 'Folgen Sie aber bitte streng den Fixationskreuzen!\n'... - '\n'... - 'Sie werden alle ' num2str(breakpoint) ' Durchgänge eine Pause machen können \n'... - 'nach der Sie durch Tastendruck fortfahren können. \n'... - '\n'... - 'Wenn Sie noch Fragen haben, können Sie jetzt die Versuchsleiter/in fragen.\n'... - '\n'... - 'Drücken Sie ansonsten die Leertaste,\n'... - ' um das Experiment zu starten.\n' ... - ]; - elseif nInstruct == 3 - text = ['Der Eyetracker ist nun kalibiert.\n'... - '\n'... - 'Bitte verändern Sie Ihre Kopfposition nun nicht mehr.\n'... - '\n'... - 'Zur Erinnerung: Im Experiment sehen Sie jeweils zwei Gesichter und geben anschließend an,\n'... - '\n'... - 'ob die Gesichter gleich oder unterschiedlich waren.\n'... - '\n'... - 'Benutzen Sie dazu die Pfeiltasten (links, rechts) und die Leertaste zum Bestätigen.\n'... - '\n'... - 'Zusätzlich folgen Sie auch hier immer den Fixationskreuzen.\n'... - '\n'... - 'Drücken Sie nun die Leertaste,\n'... - ' um das Experiment zu starten!\n' ... - ]; - elseif nInstruct == 2%end - text = 'Experiment beendet!\n'; - elseif nInstruct==4%break - text = [sprintf('Sie haben bereits %g von %g Durchgängen geschafft!\n',tt-1,p.psi.presentation.numtrials_chain*tchain)... - 'Machen Sie eine kurze Pause, lehnen Sie sich gern einen Moment zurück\n'... - 'und schließen Sie die Augen, um diese zu entspannen.\n'... - 'Drücken Sie anschließend die Leertaste, um weiterzumachen.\n']; - end - end - - function SetupLog - - p.psi.log.globaltrial= NaN(tchain,length(x)); - p.psi.log.signal = NaN(tchain,length(x)); - p.psi.log.x = NaN(tchain,length(x)); - p.psi.log.refface = NaN(tchain,length(x)); - p.psi.log.testface = NaN(tchain,length(x)); - p.psi.log.response = NaN(tchain,length(x)); - % p.psi.log.xrounded = NaN(p.stim.tFace/tchain+1,p.psi.presentation.numtrials_chain,tchain); - p.psi.log.xrounded = NaN(length(unique(x)),max(p.psi.presentation.rep),tchain); - p.psi.log.sdt = NaN(tchain,length(x)); - p.psi.log.trial_counter = zeros(length(unique(x)),tchain); - end - - function SetLog - - p.psi.log.globaltrial(current_chain,cc(current_chain))= tt; - p.psi.log.signal(current_chain,cc(current_chain)) = signal; - p.psi.log.x(current_chain,cc(current_chain)) = x(cc(current_chain),current_chain); - p.psi.log.refface(current_chain,cc(current_chain)) = ref_face; - p.psi.log.testface(current_chain,cc(current_chain)) = test_face; - p.psi.log.response(current_chain,cc(current_chain)) = response; - p.psi.log.sdt(current_chain,cc(current_chain)) = sdt;%1=hit 2=FA 3=miss 4=CR - - - end -% function PlotProcedure -% plotproc=figure(1); -% % title(sprintf('Threshold Estimation for subject %02d',tchain),'FontSize',14) -% for sub=1:tchain; -% subplot(2,2,sub) -% t = 1:length(p.log.x(sub)); -% hold on; -% plot(t,abs(p.log.x(sub)),'bo-'); -% errorbar(t,p.log.alpha(sub),p.log.seAlpha(sub),'r--') -% plot(t(p.log.response(sub) == 1),p.log.x(sub)(p.log.response(sub) == 1),'ko', ... -% 'MarkerFaceColor','k'); -% plot(t(p.log.response(sub) == 0),p.log.x(sub)(p.log.response(sub) == 0),'ko', ... -% 'MarkerFaceColor','w'); -% -% set(gca,'FontSize',12); -% axis([0 max(t)+1 0 max(p.log{sub}.alpha)+max(p.log{sub}.seAlpha)+20]) -% xlabel('Trial'); -% ylabel('xCurrent (Deg)'); -% -% end -% annotation('textbox', [0 0.9 1 0.1], 'String',... -% (sprintf('Threshold Estimation for subject %02d',tchain)), ... -% 'EdgeColor', 'none', ... -% 'HorizontalAlignment', 'center','FontSize',14) -% legend('xCurrent','estimated Threshold','Response = 1','Response = 0','Location','northeast'); -% -% % end -% function Plot_Fit -% plotfit=figure(2); -% for sub=1:tchain; -% subplot(2,2,sub) -% t = 1:length(p.log{sub}.x); -% hold on; -% plot(t,abs(p.log{sub}.x),'bo-'); -% errorbar(t,p.log{1}.alpha,p.log{1}.seAlpha,'r--') -% plot(t(p.log{sub}.response == 1),p.log{sub}.x(p.log{sub}.response == 1),'ko', ... -% 'MarkerFaceColor','k'); -% plot(t(p.log{sub}.response == 0),p.log{sub}.x(p.log{sub}.response == 0),'ko', ... -% 'MarkerFaceColor','w'); -% -% set(gca,'FontSize',12); -% axis([0 max(t)+1 0 max(p.log{sub}.alpha)+max(p.log{sub}.seAlpha)+20]) -% xlabel('Trial'); -% ylabel('xCurrent (Deg)'); -% -% end - - function [t]=StartEyelinkRecording(trialID,phase,cc,tt,current_chain,isref,file,delta_ref,delta_csp,abs_FGangle,fixx,fixy) - - t = []; - - - Eyelink('Message', 'TRIALID:%04d, PHASE:%04d, CHAIN:%04d, CHAINTRIAL:%04d, TTRIAL:%04d, ISREF:%04d, FILE:%04d, DELTAREF:%04d, DELTACSP:%04d, FGDEG:%04d, FXX:%04d, FXY:%04d',trialID, phase,... - current_chain, cc, tt, isref, file, delta_ref*100, delta_csp*100, abs_FGangle*100,fixx,fixy); - % an integration message so that an image can be loaded as - % overlay background when performing Data Viewer analysis. - WaitSecs(0.01); - Eyelink('Message', '!V IMGLOAD CENTER %s %d %d', p.stim.files(file,:), p.ptb.midpoint(1), p.ptb.midpoint(2)); - % This supplies the title at the bottom of the eyetracker display - Eyelink('Command', 'record_status_message "Stim: %d, Phase: %d"',file, phase); - % - %Put the tracker offline and draw the stimuli. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - % clear tracker display and draw box at center - Eyelink('Command', 'clear_screen %d', 0); - %draw the image on the screen - Eyelink('ImageTransfer',p.stim.files24(file,:),p.ptb.imrect(1),p.ptb.imrect(2),p.ptb.imrect(3),p.ptb.imrect(4),p.ptb.imrect(1),p.ptb.imrect(2)); - Eyelink('Command', 'draw_cross %d %d %d',p.ptb.midpoint(1),p.ptb.CrossPositionET_y(1),p.ptb.fc_size); - Eyelink('Command', 'draw_cross %d %d %d',p.ptb.midpoint(1),p.ptb.CrossPositionET_y(2),p.ptb.fc_size); - % - %drift correction - %EyelinkDoDriftCorrection(el,crosspositionx,crosspositiony,0,0); - %start recording following mode transition and a short pause. - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('StartRecording'); - - t = GetSecs; - Log(t,8,NaN); - end - - function [t] = StopEyelinkRecording - - Eyelink('Message', 'Stim Offset'); - Eyelink('Message', 'BLANK_SCREEN'); - Eyelink('StopRecording'); - t = GetSecs; - %this is the end of the trial scope. - WaitSecs(0.01); - Eyelink('Message', 'TRIAL_RESULT 0'); - % - WaitSecs(0.01); - Eyelink('Command', 'set_idle_mode'); - WaitSecs(0.01); - Eyelink('Command', 'clear_screen %d', 0); - - Log(t,-8,NaN); - end - - function InitEyeLink - % - if EyelinkInit(0)%use 0 to init normaly - fprintf('=================\nEyelink initialized correctly...\n') - else - fprintf('=================\nThere is problem in Eyelink initialization\n') - keyboard; - end - % - WaitSecs(0.5); - [~, vs] = Eyelink('GetTrackerVersion'); - fprintf('=================\nRunning experiment on a ''%s'' tracker.\n', vs ); - - %load 24bits pictures for eyelink... - dummy = dir([p.path.stim24 '*.bmp']); - p.stim.files24 = [repmat([fileparts(p.path.stim24) filesep],length(dummy),1) vertcat(dummy(:).name)]; - % for i=1:32 - % filename = p.stim.files24(nStim,:); - % [im , ~, ~] = imread(filename); - % end - % - % - el = EyelinkInitDefaults(p.ptb.w); - %update the defaults of the eyelink tracker - el.backgroundcolour = p.stim.bg; - el.msgfontcolour = WhiteIndex(el.window); - el.imgtitlecolour = WhiteIndex(el.window); - el.targetbeep = 0; - el.calibrationtargetcolour = WhiteIndex(el.window); - el.calibrationtargetsize = 1.5; - el.calibrationtargetwidth = 0.5; - el.displayCalResults = 1; - el.eyeimgsize = 50; - el.waitformodereadytime = 25;%ms - el.msgfont = 'Times New Roman'; - el.cal_target_beep = [0 0 0];%[1250 0.6 0.05]; - %shut all sounds off - el.drift_correction_target_beep = [0 0 0]; - el.calibration_failed_beep = [0 0 0]; - el.calibration_success_beep = [0 0 0]; - el.drift_correction_failed_beep = [0 0 0]; - el.drift_correction_success_beep= [0 0 0]; - EyelinkUpdateDefaults(el); - %PsychEyelinkDispatchCallback(el) - - % open file. - res = Eyelink('Openfile', p.path.edf); - if res == -3 - fprintf('File cannot be created!!!!\n'); - return; - end - % - Eyelink('command', 'add_file_preamble_text ''Recorded by EyelinkToolbox FearCloud Experiment'''); - Eyelink('command', 'screen_pixel_coords = %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - Eyelink('message', 'DISPLAY_COORDS %ld %ld %ld %ld', 0, 0, p.ptb.width-1, p.ptb.height-1); - % set calibration type. - Eyelink('command', 'calibration_type = HV5'); - Eyelink('command','auto_calibration_messages = YES'); - Eyelink('command', 'select_parser_configuration = 1'); - %what do we want to record - Eyelink('command', 'file_sample_data = LEFT,RIGHT,GAZE,HREF,AREA,GAZERES,STATUS,INPUT,HTARGET'); - Eyelink('command', 'file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON,INPUT'); - Eyelink('command', 'use_ellipse_fitter = no'); - % set sample rate in camera setup screen - Eyelink('command', 'sample_rate = %d',1000); - end - function StopEyelink(filename) - try - fprintf('Trying to stop the Eyelink system with StopEyelink\n'); - Eyelink('StopRecording'); - WaitSecs(0.5); - Eyelink('Closefile'); - display('receiving the EDF file...'); - Eyelink('ReceiveFile',filename,[p.path.subject '\eye\'],1); - display('...finished!') - % Shutdown Eyelink: - Eyelink('Shutdown'); - catch - display('StopEyeLink routine didn''t really run well'); - end - end - function CalibrateEL - fprintf('=================\n=================\nEntering Eyelink Calibration\n') - p.var.ExpPhase = 0; - ShowInstruction(0); - EyelinkDoTrackerSetup(el); - %Returns 'messageString' text associated with result of last calibration - [~, messageString] = Eyelink('CalMessage'); - Eyelink('Message','%s',messageString);% - WaitSecs(0.05); - fprintf('=================\n=================\nNow we are done with the calibration\n') - end - - function Log(ptb_time, event_type, event_info) - %Phases: - %Pre-Experiment : 1 - %Post-Experiment : 2 - % %Instruction : 1 - % %Baseline : 2 - % %Conditioning : 3 - % %Test : 4 - % %Rating : 5 - % %Calibration : 0 - % - %event types are as follows: - % - %Scan Detection : 0 info: NaN; - %Cross Onset : 1 info: position - %Stimulus Onset/Offset: 2/-2 info: stim_id - %Cross Movement : 3 info: NaN; - %Stimulus Offset : -2 info: NaN; - %UCS Delivery : 4 info: NaN; - %Key Presses : 7 info: NaN; - %Tracker Onset/Offset : 8 info: NaN; - % - %Text on the screen : 5 info: Which Text? - %RatingScreen Onset : 6 info: NaN; - - p.var.event_count = p.var.event_count + 1; - p.out.log(p.var.event_count,:) = [ptb_time event_type event_info phase]; - % % p_out_log(p.out.event_counter,:) - %logstring([ 'Logged: ' mat2str(p_out_log(p.out.event_counter,:)) ' - Type: ' p.verbose.eventtype{abs(event_type)} ' - Phase: ' p.verbose.eventphase{CurrentExperimentalPhase}]) - %for i = 1:3;subplot(3,1,i);plot(p_out_log(1:p.out.event_counter ,i),'o-');drawnow;end - % - - end - function cleanup - - % Close window: - sca; - %set back the old resolution - if strcmp(p.hostname,'triostim1') - Screen('Resolution',p.ptb.screenNumber, p.ptb.oldres.width, p.ptb.oldres.height ); - %show the cursor - ShowCursor(p.ptb.screenNumber); - end - % - % %IOPort('ConfigureSerialPort', p.com.serial,' StopBackgroundRead'); - % %IOPort('Close',p.com.serial); - % commandwindow; - % ListenChar(0); - % KbQueueRelease(p_ptb_device); - end - -end diff --git a/exp_treatgen_calib.m b/exp_treatgen_calib.m deleted file mode 100644 index 4ecb776..0000000 --- a/exp_treatgen_calib.m +++ /dev/null @@ -1,1110 +0,0 @@ -function [p]=exp_treatgen_calib(subject,run) -%[p]=exp_treatgen_calib(subject,run) -% -%Used for fearamy project, based on the FearGen_eyelab code. It increments -%it by adding scanner pulse communications. -% -% - -debug = 0;%debug mode; -arduino = 1; -commandwindow; -%clear everything -clear mex global functions -cgshut; -global cogent; - -%%%%%%%%%%%load the GETSECS mex files so call them at least once -GetSecs; -WaitSecs(0.001); -% -p = []; -s = []; - -SetParams; -echo on -diary(p.path.diary) -if arduino - SetArduino; -end -SetPTB; -%Tes -%init all the variables -t = []; -nTrial = 0; -%% -%Time Storage -TimeCrossOn = []; -p.var.event_count = 0; -%% -KbQueueStop(p.ptb.device); -KbQueueRelease(p.ptb.device); -%save again the parameter file -save(p.path.path_param,'p'); - - -p.var.ExpPhase = run; -Screen('TextSize', p.ptb.w, p.text.fontsize+4); -[nx, ny, textbounds]=DrawFormattedText(p.ptb.w, GetText(0), 'center', 'center'); -Screen('TextSize', p.ptb.w, p.text.fontsize); -%Instructions -if run == 2 - ShowInstruction(0,0,3) - ShowInstruction(1,1); - LimitsProcedure; - ShowInstruction(10,1); -elseif run == 1 - warning('Trigger connected?') - warning('Arduino active?') - ShowInstruction(0,0,3) - ShowInstruction(3,1); - BuzzDemo; - ShowInstruction(1,1); - LimitsProcedure; - ShowInstruction(10,0,3); - ExperimenterInput(1); - ShowInstruction(2,1); %calibration with long instruction - ShowInstruction(22,1); - ConfirmIntensity; - ExperimenterInput(2) - PresentStimuli; - GetTemps; -elseif run == 3 - ShowInstruction(10,0,3); - ExperimenterInput(1); - ShowInstruction(2,1); %calibration with long instruction - ShowInstruction(22,1); - ConfirmIntensity; - ExperimenterInput(2) - PresentStimuli; - GetTemps; -end - - -%trim the log file and save -p.out.log = p.out.log(sum(isnan(p.out.log),2) ~= size(p.out.log,2),:); -%shift the time so that the first timestamp is equal to zero -p.out.log(:,1) = p.out.log(:,1) - p.out.log(1); -save(p.path.path_param,'p'); -diary off -% -%move the file to its final location. -try - copyfile(p.path.subject,p.path.finalsubject); -catch - movefile(p.path.subject,p.path.finalsubject); -end -%close everything down -% try -% addpath('/USER/onat/Code/globalfunctions/ssh2_v2_m1_r6/ssh2_v2_m1_r6/') -% p.path.tarname = [p.path.finalsubject(1:end-1) '.tar']; -% tar(p.path.tarname,p.path.finalsubject); -% [a b c] = fileparts( p.path.tarname); -% cd(a) -% scp_simple_put('sanportal','onat','',[b c]); -% fprintf('Copying to neuronass succesfull...\n'); -% catch -% fprintf('Copying to neuronass failed...\n'); -% end -cleanup; - - function LimitsProcedure - fprintf('Is the thermode set? Press v to start experiment from your side!\n') - k = 0; - while ~(k == p.keys.v); - pause(0.1); - [~, k] = KbStrokeWait(p.ptb.device); - k = find(k); - end - for n = 1:p.presentation.limits.ntrials - if n ==1 - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.rect); %always create a gray background - Screen('FillRect', p.ptb.w, p.stim.white, p.ptb.FixCross');%draw the prestimus cross atop - Screen('DrawingFinished',p.ptb.w,0); - TimeCrossOn = Screen('Flip',p.ptb.w); - WaitSecs(1); - end - if arduino - serialcom(s,'START'); - end - tic - %prepare red cross - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.rect); %always create a gray background - Screen('FillRect', p.ptb.w, p.ptb.fc_color, p.ptb.FixCross');%draw the prestimus cross atop - Screen('DrawingFinished',p.ptb.w,0); - TimeCrossOn = Screen('Flip',p.ptb.w); - fprintf('Trigger sent, raising temperature. '); - fprintf('Waiting for keypress...\n') - %toc - %wait for keypress - k = 0; - while ~(k == p.keys.space); - [~, k] = KbStrokeWait(p.ptb.device); - k = find(k); - end - if arduino - serialcom(s,'MOVE',20);%this opens the "up" channel for xx ms, to stop thermode; - end - RT(n) = toc; - stoplim(n) = RT(n)*p.presentation.limits.ror + p.presentation.limits.base; - fprintf('Subject stopped at %5.2f °C.\n',stoplim(n)); - %turn back to white cross - if ncross2onset->onset2shock->shock2offset - %these (duration.BLA) are average duration values: - p.duration.painstim = 5;% - p.duration.prestim = [2 4]; - p.duration.anticip = 1; - p.duration.poststim = 1; - p.duration.ISI = 1; - p.duration.rate = 5; - - p.duration.tens = .7; %this is only for TensDEMO - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %stimulus sequence - s = load([p.path.stim 'stimlist\caliblist.mat']); - p.presentation.steps = s.steps; - - p.presentation.tens = NaN; - p.presentation.calib_target_vas = NaN; - p.presentation.calib_est = NaN; - p.presentation.basetemp = NaN; % will be defined after limits procedure - p.presentation.ror = 5; - p.presentation.run = run; - p.presentation.hardwarebasetemp = 25; - - p.presentation.limits.base = 20; - p.presentation.limits.ror = 2; - p.presentation.limits.isi = 5; - p.presentation.limits.ntrials = 3; - p.presentation.limits.RT = zeros(p.presentation.limits.ntrials,1); - p.presentation.limits.threshold = zeros(p.presentation.limits.ntrials,1); - - %this will deal all the presentation sequence related information -% p.presentation.Tmax = threshold + 3; - p.presentation.stimlist = p.presentation.basetemp + p.presentation.steps;%basetemp + 3 is maximum temperature - p.presentation.tTrial = length(p.presentation.stimlist); - % - - p.log.ratingEventCount = 0; - p.log.ratings = []; - p.out.log = zeros(1000000,4).*NaN; - p.out.response = zeros(p.presentation.tTrial,1); - %Save the stuff - save(p.path.path_param,'p'); - % - function [FM labels] = FileMatrix(path) - %Takes a path with file extension associated to regexp (e.g. - %C:\blabl\bla\*.bmp) returns the file matrix - dummy = dir(path); - FM = [repmat([fileparts(path) filesep],length(dummy),1) vertcat(dummy(:).name)]; - labels = {dummy(:).name}; - end - end - function SetArduino - s = serial('COM5','BaudRate',19200); - fopen(s); - WaitSecs(1); - serialcom(s,'T',p.presentation.basetemp); - serialcom(s,'ROR',p.presentation.ror); - WaitSecs(.5); - serialcom(s,'DIAG'); - WaitSecs(1); - end - function Buzzduino(duration) - arg = ['SHOCK;' num2str(duration)]; - try - fprintf(s,arg); - catch - fprintf([repmat('*',1,50) '\n']); - fprintf(['Didn' char(39) 't find Arduino!\n']) - end - end - function [finalRating,reactionTime,response] = vasScale(window,windowRect,durRating,defaultRating,backgroundColor,StartY,keys,type,varargin) - - %% key settings - KbName('UnifyKeyNames'); - lessKey = keys.decrease; % yellow button - moreKey = keys.increase; % red button - confirmKey = keys.confirm; % green button - escapeKey = keys.esc; - - if isempty(window); error('Please provide window pointer for likertScale!'); end - if isempty(windowRect); error('Please provide window rect for likertScale!'); end - if isempty(durRating); error('Duration length of rating has to be specified!'); end - - %% Default values - nRatingSteps = p.rating.division; - if strcmp(type,'confirm') - nRatingSteps = 2; - end - scaleWidth = 700; - textSize = 20; - lineWidth = 4; - scaleColor = [255 255 255]; - % if strcmp(type,'pain') - % activeColor = [255 0 0]; - % elseif strcmp(type,'relief') - % activeColor = [0 0 255]; - % else - % activeColor = [255 255 255]; - % end - activeColor = p.ptb.fc_color; - if isempty(defaultRating); defaultRating = round(nRatingSteps/2); end - if isempty(backgroundColor); backgroundColor = 0; end - - % if length(ratingLabels) ~= nRatingSteps - % error('Rating steps and label numbers do not match') - % end - - %% Calculate rects - activeAddon_width = 3; - activeAddon_height = 20; - [xCenter, yCenter] = RectCenter(windowRect); - yCenter = StartY; - axesRect = [xCenter - scaleWidth/2; yCenter - lineWidth/2; xCenter + scaleWidth/2; yCenter + lineWidth/2]; - lowLabelRect = [axesRect(1),yCenter-20,axesRect(1)+6,yCenter+20]; %6 means width of the Rect - highLabelRect = [axesRect(3)-6,yCenter-20,axesRect(3),yCenter+20]; - ticPositions = linspace(xCenter - scaleWidth/2,xCenter + scaleWidth/2-lineWidth,nRatingSteps); %actually this lineWidth doesnt make sense, because that relies to y-coords - activeTicRects = [ticPositions-activeAddon_width;ones(1,nRatingSteps)*yCenter-activeAddon_height;ticPositions + activeAddon_width;ones(1,nRatingSteps)*yCenter+activeAddon_height]; - if strcmp(type,'confirm') - axesRect = [xCenter - scaleWidth/8; yCenter - lineWidth/2; xCenter + scaleWidth/8; yCenter + lineWidth/2]; - lowLabelRect = [axesRect(1)-20,yCenter-20,axesRect(1)+20,yCenter+20]; - highLabelRect = [axesRect(3)-20,yCenter-20,axesRect(3)+20,yCenter+20]; - activeAddon_width = 20; - activeAddon_height = 20; - ticPositions = [axesRect(1) axesRect(3)]; - activeTicRects = [ticPositions-activeAddon_width ; ones(1,nRatingSteps)*yCenter-activeAddon_height; ticPositions + activeAddon_width; ones(1,nRatingSteps)*yCenter+activeAddon_height]; - end - %define text rects - if strcmp(type,'relief') - stringArray={ 'keine','Linderung','maximale','Linderung'}; - elseif strcmp(type,'pain') - stringArray={ 'kein','Schmerz','maximaler','Schmerz'}; - elseif strcmp(type,'confirm') - stringArray ={ 'ja','nein'}; - end - for i = 1:length(stringArray) - [~, ~, textBox] = DrawFormattedText(window,char(stringArray(i)),0,0,backgroundColor); - textWidths(i)=textBox(3)-textBox(1); - end - % keyboard - inactivecol = [130 130 130]; - - Screen('TextSize',window,textSize); - Screen('TextColor',window,[255 255 255]); - Screen('TextFont', window, 'Arial'); - currentRating = defaultRating; - finalRating = currentRating; - reactionTime = 0; - response = 0; - first_flip = 1; - startTime = GetSecs; - numberOfSecondsRemaining = durRating; - nrbuttonpresses = 0; - - %%%%%%%%%%%%%%%%%%%%%%% loop while there is time %%%%%%%%%%%%%%%%%%%%% - % tic; % control if timing is as long as durRating - while numberOfSecondsRemaining > 0 - Screen('FillRect',window,backgroundColor); - if or(strcmp(type,'relief'),strcmp(type,'pain')) - Screen('FillRect',window,scaleColor,axesRect); %draw white axis - Screen('FillRect',window,activeColor,activeTicRects(:,currentRating)); - Screen('FillRect',window,scaleColor,lowLabelRect); - Screen('FillRect',window,scaleColor,highLabelRect); - end - if strcmp(type,'pain') - DrawFormattedText(window, 'Bitte bewerten Sie den zuvor erhaltenen Reiz.', 'center',yCenter-100, scaleColor); - Screen('DrawText',window,'kein',axesRect(1)-textWidths(1)/2,yCenter+25,scaleColor); - Screen('DrawText',window,'Schmerz',axesRect(1)-textWidths(2)/2,yCenter+45,scaleColor); - Screen('DrawText',window,'maximaler',axesRect(3)-textWidths(3)/2,yCenter+25,scaleColor); - Screen('DrawText',window,'Schmerz',axesRect(3)-textWidths(4)/2,yCenter+45,scaleColor); - elseif strcmp(type,'relief') - DrawFormattedText(window, 'Bitte bewerten Sie die Wirksamkeit der Behandlung.', 'center',yCenter-100, scaleColor); - Screen('DrawText',window,'keine',axesRect(1)-textWidths(1)/2,yCenter+25,scaleColor); - Screen('DrawText',window,'Linderung',axesRect(1)-textWidths(2)/2,yCenter+45,scaleColor); - Screen('DrawText',window,'maximale',axesRect(3)-textWidths(3)/2,yCenter+25,scaleColor); - Screen('DrawText',window,'Linderung',axesRect(3)-textWidths(4)/2,yCenter+45,scaleColor); - Screen('FillRect',window,activeColor,activeTicRects(:,currentRating)); - elseif strcmp(type,'confirm') - text = GetText(varargin{1}); - DrawFormattedText(window, text, 'center',yCenter-100, scaleColor); - Screen('DrawText',window,'ja',axesRect(1)-textWidths(1)/2,yCenter-20,scaleColor); - Screen('DrawText',window,'nein',axesRect(3)-textWidths(2)/2,yCenter-20,scaleColor); - if currentRating ==1 - Screen('DrawText',window,'ja',axesRect(1)-textWidths(1)/2,yCenter-20,activeColor); - elseif currentRating == 2 - Screen('DrawText',window,'nein',axesRect(3)-textWidths(2)/2,yCenter-20,activeColor); - end - end - % Remove this line if a continuous key press should result in a continuous change of the scale - % while KbCheck; end - - if response == 0 - % set time 0 (for reaction time) - if first_flip == 1 - secs0 = Screen('Flip', window); % output Flip -> starttime rating - first_flip = 0; - % after 1st flip -> just flips without setting secs0 to null - else - Screen('Flip', window); - end - [ keyIsDown, secs, keyCode ] = KbCheck; % this checks the keyboard very, very briefly. - Log(secs,7,keyCode); - if keyIsDown % only if a key was pressed we check which key it was - response = 0; % predefine variable for confirmation button 'space' - nrbuttonpresses = nrbuttonpresses + 1; - if keyCode(moreKey) % if it was the key we named key1 at the top then... - currentRating = currentRating + 1; - finalRating = currentRating; - response = 0; - if currentRating > nRatingSteps - currentRating = nRatingSteps; - end - elseif keyCode(lessKey) - currentRating = currentRating - 1; - finalRating = currentRating; - response = 0; - if currentRating < 1 - currentRating = 1; - end - elseif keyCode(confirmKey) - finalRating = currentRating-1; - if ~strcmp(type,'confirm') - disp(['VAS Rating: ' num2str(finalRating)]); - end - response = 1; - reactionTime = secs - secs0; - break; - end - end - end - - numberOfSecondsElapsed = (GetSecs - startTime); - numberOfSecondsRemaining = durRating - numberOfSecondsElapsed; - end - if nrbuttonpresses ~= 0 && response == 0 - finalRating = currentRating - 1; - reactionTime = durRating; - if ~strcmp(type,'confirm') - disp(['VAS Rating: ' num2str(finalRating)]); - fprintf('***********No Confirmation!***********\n'); - end - end - if nrbuttonpresses == 0 - finalRating = NaN; %NaN is NaN, no recoding necessary - reactionTime = durRating; - disp(['VAS Rating: ' num2str(finalRating)]); - warning(sprintf('\n***********No Response! Please check participant!***********\n')); - end - % toc - end - function ShowInstruction(nInstruct,waitforkeypress,varargin) - %ShowInstruction(nInstruct,waitforkeypress) - %if waitforkeypress is 1, ==> subject presses a button to proceed - %if waitforkeypress is 0, ==> text is shown for VARARGIN seconds. - - - [text]= GetText(nInstruct); - ShowText(text); - if waitforkeypress %and blank the screen as soon as the key is pressed - KbStrokeWait(p.ptb.device); - else - WaitSecs(varargin{1}); - end - Screen('FillRect',p.ptb.w,p.stim.bg); - t = Screen('Flip',p.ptb.w); - - function ShowText(text) - - Screen('FillRect',p.ptb.w,p.stim.bg); - DrawFormattedText(p.ptb.w, text, 'center', 'center',p.stim.white,[],[],[],2,[]); - t=Screen('Flip',p.ptb.w); - Log(t,-1,nInstruct); - %show the messages at the experimenter screen - fprintf('=========================================================\n'); - fprintf('Text shown to the subject:\n'); - fprintf(text); - fprintf('=========================================================\n'); - - end - end - function [text]=GetText(nInstruct) - if nInstruct == 0% - text = 'Kalibrationsphase'; - elseif nInstruct == 1 %Instruction - text = ['Bestimmung der Schmerzschwelle von Hitzereizen.\n'... - 'Wir bestimmen nun Ihre individuelle Hitzeschmerzschwelle.\n'... - 'Wir werden dazu die Temperatur schrittweise erhöhen.\n'... - 'Bitte schauen Sie während des Vorgangs auf das kleine Kreuz.\n'... - 'Ihre Aufgabe ist es, die Leertaste zu drücken, sobald Sie die Temperatur als schmerzhaft empfinden,\n'... - 'd.h. sobald zum Gefühl von Wärme ein unangenehmes Gefühl wie Brennen oder Stechen hinzukommt.\n'... - 'Der Vorgang wird drei mal wiederholt.\n'... - '\n'... - 'Falls Sie noch Fragen haben, wenden Sie sich bitte noch einmal an die Versuchsleiterin.\n'... - 'Drücken Sie sonst bitte die Leertaste, um zu starten.\n']; - elseif nInstruct == 2 %Instruction - text = ['Im Folgenden möchten wir Ihre individuelle Schmerzwahrnehmung noch genauer bestimmen.\n' ... - 'Dazu erhalten Sie Reize unterschiedlicher Temperaturen.\n' ... - 'Anschließend bewerten Sie den jeweiligen Reiz auf einer Skala,\n' ... - 'die von "kein Schmerz bis "maximaler Schmerz" reicht. Sie haben dazu 5 Sek Zeit.\n' ... - 'Falsche Antworten gibt es bei dieser Aufgabe nicht, da individuelle Empfindungen sehr unterschiedlich sein können.\n' ... - 'Nutzen Sie die Pfeiltasten zum Bewerten & bestätigen Sie Ihre Eingabe immer\n' ... - 'mit der Leertaste. Bitte versuchen Sie sich auch auf kleinste Reizänderungen\n' ... - 'zu konzentrieren & bewerten Sie diese so präzise wie möglich.\n'... - '\n'... - 'Falls Sie noch Fragen haben, wenden Sie sich bitte noch einmal an die Versuchsleiterin.\n' ... - 'Drücken Sie sonst bitte die Leertaste, um weiterzumachen.\n']; - elseif nInstruct == 22 %Instruction - text = ['Wir werden nun die für Sie individuell ausgewählte Grundtemperatur\n' ... - 'für die folgende Kalibration anbringen.\n' ... - 'Diese kann sich etwas unangenehm anfühlen, sollte aber nicht wirklich schmerzhaft sein.\n' ... - 'Wir fragen Sie zudem vor Beginn der Kalibration, ob diese Temperatur für Sie gut aushaltbar ist.\n' ... - '\n' ... - 'Drücken Sie bitte die Leertaste, wenn Sie bereit sind zu starten.\n']; - elseif nInstruct == 9 - text = 'Temperatur wird angepasst...\n'; - elseif nInstruct == 3%short Digitimer stimulation - text = ['Kalibration der TENS-Intensität.\n' ... - '\n'... - 'Wir werden nun als Erstes das TENS-Gerät kalibrieren.\n'... - 'Wir gehen dazu gemeinsam einige Reizintensitäten durch, und Sie geben jeweils an,\n'... - 'ob Sie eine Stimulation verspürt haben.\n'... - '\n'... - 'Die Stimulation während des Experiments wird dann unterschwellig durchgeführt,\n'... - 'd.h. Sie werden diese nicht mehr bewusst wahrnehmen.\n'... - '\n'... - '\n'... - 'Falls Sie noch Fragen haben, wenden Sie sich bitte noch einmal an die Versuchsleiterin.\n' ... - 'Drücken Sie sonst bitte die Leertaste, um zu starten.\n']; - elseif nInstruct == 200%short instruction for second run - text = ['Wiederholung der Schwellenkalibrierung.\n'... - '\n'... - 'Nutzen Sie die Tasten von Zeigefinger (links) & Ringfinger (rechts) zum Bewerten.\n'... - 'Bestätigen Sie Ihre Eingabe immer mit der mittleren Taste (oben). Falls Sie noch \n'... - 'Fragen haben, teilen Sie dies gleich noch einmal der Versuchsleiterin mit. \n'... - ]; - elseif nInstruct == 10 - text = ['Vielen Dank!\n'... - 'Es geht gleich weiter. \n']; - elseif nInstruct == 101 %confirm intensity - text = 'Ist diese Temperatur gut erträglich?'; - elseif nInstruct == 102 %These two below are the possible responses to the question in 11 - text = 'Haben Sie eine elektrische Stimulation verspürt?'; - else - text = {''}; - end - end - function SetPTB - %KbName('UnifyKeyNames'); - %Sets the parameters related to the PTB toolbox. Including - %fontsizes, font names. - %Default parameters - Screen('Preference', 'SkipSyncTests', 1); - Screen('Preference', 'DefaultFontSize', p.text.fontsize); - Screen('Preference', 'DefaultFontName', p.text.fontname); - Screen('Preference', 'TextAntiAliasing',2);%enable textantialiasing high quality - Screen('Preference', 'VisualDebuglevel', 0); - Screen('Preference', 'SkipSyncTests', 1); - Screen('Preference', 'SuppressAllWarnings', 1); - %%Find the number of the screen to be opened - screens = Screen('Screens'); - p.ptb.screenNumber = max(screens);%the maximum is the second monitor - %Make everything transparent for debugging purposes. - if debug - commandwindow; - PsychDebugWindowConfiguration; - end - %set the resolution correctly - res = Screen('resolution',p.ptb.screenNumber); - HideCursor(p.ptb.screenNumber); - %spit out the resolution - fprintf('Resolution of the screen is %dx%d...\n',res.width,res.height); - - %Open a graphics window using PTB - [p.ptb.w p.ptb.rect] = Screen('OpenWindow', p.ptb.screenNumber, p.stim.bg); - %Screen('BlendFunction', p.ptb.w, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - Screen('Flip',p.ptb.w);%make the bg - p.ptb.slack = Screen('GetFlipInterval',p.ptb.w)./2; - [p.ptb.width, p.ptb.height] = Screen('WindowSize', p.ptb.screenNumber); - p.ptb.startY = p.ptb.height./2; %should be px(yaxis)./4; - %find the mid position on the screen. - p.ptb.midpoint = [ p.ptb.width./2 p.ptb.height./2]; - %NOTE about RECT: - %RectLeft=1, RectTop=2, RectRight=3, RectBottom=4. - % p.ptb.CrossPosition_x = p.ptb.midpoint(1);%bb(1);%always the same - % p.ptb.CrossPosition_y = p.ptb.midpoint(2)./2; - - p.ptb.fc_size = 20; - p.ptb.fc_width = 4; - p.ptb.fc_color = [130 50 0]; - % p.ptb.screenFix1 = [p.ptb.midpoint(1)-p.ptb.fc_size p.ptb.startY-p.ptb.fc_width p.ptb.midpoint(1)+p.ptb.fc_size p.ptb.startY+p.ptb.fc_width]; %I guess this is X - % p.ptb.screenFix2 = [p.ptb.midpoint(1)-p.ptb.fc_width p.ptb.startY-p.ptb.fc_size p.ptb.midpoint(1)+p.ptb.fc_width p.ptb.startY+p.ptb.fc_size]; %I guess this is Y - fix = [p.ptb.midpoint(1) p.ptb.startY]; % yaxis is 1/4 of total yaxis - p.ptb.FixCross = [fix(1)-p.ptb.fc_width,fix(2)-p.ptb.fc_size,fix(1)+p.ptb.fc_width,fix(2)+p.ptb.fc_size;fix(1)-p.ptb.fc_size,fix(2)-p.ptb.fc_width,fix(1)+p.ptb.fc_size,fix(2)+p.ptb.fc_width]; - - % - %% - %priorityLevel=MaxPriority(['GetSecs'],['KbCheck'],['KbWait'],['GetClicks']); - Priority(MaxPriority(p.ptb.w)); - %this is necessary for the Eyelink calibration - %InitializePsychSound(0) - %sound('Open') - % Beeper(1000) - LoadPsychHID - %%%%%%%%%%%%%%%%%%%%%%%%%%%Prepare the keypress queue listening. - p.ptb.device = []; - %get all the required keys in a vector - p.ptb.keysOfInterest = [];for i = fields(p.keys)';p.ptb.keysOfInterest = [p.ptb.keysOfInterest p.keys.(i{1})];end - fprintf('Key listening will be restricted to %d\n',p.ptb.keysOfInterest) - RestrictKeysForKbCheck(p.ptb.keysOfInterest); - - p.ptb.keysOfInterest=zeros(1,256); - p.ptb.keysOfInterest(p.keys.confirm) = 1; - %create a queue sensitive to only relevant keys. - % KbQueueCreate(p.ptb.device,p.ptb.keysOfInterest);%default device. - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %prepare parallel port communication. This relies on cogent i - %think. We could do it with PTB as well. - if ~ismac - config_io; - outp(p.com.lpt.address,0); - if( cogent.io.status ~= 0 ) - error('inp/outp installation failed'); - end - end - - %CORRECT - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %test whether CED receives the triggers correctly... - % k = 0; - % while ~(k == 25 | k == 86 ); - % pause(0.1); - % outp(p.com.lpt.address,244);%244 means all but the UCS channel (so that we dont shock the subject during initialization). - % fprintf('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'); - % fprintf('1/ Red cable has to be connected to the Cogent BOX\n'); - % fprintf('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'); - % fprintf('2/ D2 Connection not to forget on the LPT panel\n'); - % fprintf('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'); - % fprintf('3/ Switch the SCR cable\n'); - % fprintf('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'); - % fprintf('4/ Button box has to be on\n'); - % fprintf('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'); - % fprintf('5/ Did the trigger test work?\n!!!!!!You MUST observe 5 pulses on the PHYSIOCOMPUTER!!!!!\n\n\nPress c to send it again, v to continue...\n') - % [~, k] = KbStrokeWait(p.ptb.device); - % k = find(k); - % end - % fprintf('Continuing...\n'); - %%%%%%%%%%%%%%%%%%%%%%%%%%% - - end - function [shuffled idx] = Shuffle(vector,N) - %takes first N from the SHUFFLED before outputting. This function - %could be used as a replacement for randsample - if nargin < 2;N = length(vector);end - [~, idx] = sort(rand([1 length(vector)])); - shuffled = vector(idx(1:N)); - shuffled = shuffled(:); - end - function ConfirmIntensity - fprintf(' Experimenter: Set thermode sequence baseline to %4.2f C and press v to start.\n',p.presentation.basetemp); - fprintf([repmat('=',1,50) '\n']); - k = 0; - while ~(k == p.keys.v); - pause(0.1); - [~, k] = KbStrokeWait(p.ptb.device); - k = find(k); - end - rampdur = (p.presentation.basetemp - 25)./p.presentation.ror; - ShowInstruction(9,0,rampdur+1);%"raising temp.." - Screen('Flip',p.ptb.w,0); - WaitSecs(2) - response = vasScale(p.ptb.w,p.ptb.rect,180,2,p.stim.bg,p.ptb.startY,p.keys,'confirm',101); - Screen('Flip',p.ptb.w,0); - if response == 0 - fprintf('All is fine :)\n'); - fprintf('Subject confirmed temp..\n'); - elseif response == 1 - if arduino - serialcom(s,'SET',p.presentation.hardwarebasetemp); - end - fprintf(':(, subject complained, press Stop!\n'); - p.presentation.basetemp = p.presentation.basetemp - .5; - ConfirmIntensity; - end - end - function [countedDown]=CountDown(secs, countedDown, countString) - if secs>countedDown - fprintf('%s', countString); - countedDown=ceil(secs); - end - end - - function MarkCED(socket,port) - %send pulse to SCR# - outp(socket,port); - WaitSecs(0.01); - outp(socket,0); - end - - function cleanup - % Close window: - sca; - %set back the old resolution - if strcmp(p.hostname,'triostim1') - % Screen('Resolution',p.ptb.screenNumber, p.ptb.oldres.width, p.ptb.oldres.height ); - %show the cursor - ShowCursor(p.ptb.screenNumber); - end - % - commandwindow; - KbQueueStop(p.ptb.device); - KbQueueRelease(p.ptb.device); - if arduino - fclose(s); - end - diary off - end - function Log(ptb_time, event_type, event_info) - %Phases: - %Instruction : 0 - %Test : 1 - %Rating : 5 - %Calibration : 0 - % - %event types are as follows: - % - % % % %Pulse Detection : 0 info: NaN; - % % % %Tracker Onset : 1 - % % % %Cross Onset : 2 info: position - % % % %Stimulus Onset : 3 info: dist_id - % % % %Cross Movement : 4 info: NaN; - % % % %UCS Delivery : 5 info: NaN; - % % % %Stimulus Offset : 6 info: NaN; - % % % %Key Presses : 7 info: NaN; - % % % %Tracker Offset : 8 info: NaN; - % % % %MicroBlock : 9 info:rank - %%%%%%%%%%%%%%%%% - % %Pulse Detection : 0 info: NaN; - % %Tracker Onset : 1 - % %Cross (white) Onset : 2 info: position - % %Cross (red) Onset : 3 info: position - % %Ramp Up Onset : 4 info: ror - % %Pain Plateau : 5 info: temp - % %Ramp Down Onset : 6 info: ror; - % %Key Presses : 7 info: NaN; - % %Tracker Offset : 8 info: NaN; - % %Rate Onset : 9 info: NaN; - % %Rate Offset : 10 info: NaN; - % %dummy fixflip : 22 info: NaN; - %Text on the screen : -1 info: Which Text? - for iii = 1:length(ptb_time) - p.var.event_count = p.var.event_count + 1; - p.out.log(p.var.event_count,:) = [ptb_time(iii) event_type event_info(iii) p.var.ExpPhase]; - end - % plot(p.out.log(1:p.var.event_count,1) - p.out.log(1,1),p.out.log(1:p.var.event_count,2),'o','markersize',10); - % ylim([-2 8]); - % set(gca,'ytick',[-2:8],'yticklabel',{'Rating On','Text','Pulse','Tracker+','Cross+','Stim+','CrossMov','UCS','Stim-','Key+','Tracker-'}); - % grid on - % drawnow; - - end - function PutRatingLog(Trialnum,currentRating,tempC,rateinit) - - p.log.ratingEventCount = p.log.ratingEventCount + 1; - p.log.ratings(p.log.ratingEventCount,1) = tempC; - p.log.ratings(p.log.ratingEventCount,2) = Trialnum; - p.log.ratings(p.log.ratingEventCount,3) = currentRating.finalRating; - p.log.ratings(p.log.ratingEventCount,4) = currentRating.response; - p.log.ratings(p.log.ratingEventCount,5) = currentRating.RT; - p.log.ratings(p.log.ratingEventCount,6) = rateinit; - end - - function [keycode, secs] = KbQueueDump; - %[keycode, secs] = KbQueueDump - % Will dump all the events accumulated in the queue. - - keycode = []; - secs = []; - pressed = []; - %fprintf('there are %03d events\n',KbEventAvail(p.ptb.device)); - while KbEventAvail(p.ptb.device) - [evt, n] = KbEventGet(p.ptb.device); - n = n + 1; - keycode(n) = evt.Keycode; - pressed(n) = evt.Pressed; - secs(n) = evt.Time; - % fprintf('Event is: %d\n',keycode(n)); - end - i = pressed == 1; - keycode(~i) = []; - secs(~i) = []; - %fprintf('there are %03d events found...\n',length(keycode)); - end - function GetTemps - mustbeconfirmed = 0; - figure - if mustbeconfirmed - ind = p.log.ratings(:,4) == 1; - else - ind = or((p.log.ratings(:,4) == 1),(p.log.ratings(:,4) ~= p.log.ratings(:,6))); %response must not have been confirmed, but shouldn't be init - end - y = p.log.ratings(ind,3); - x = p.log.ratings(ind,1); - trial = p.log.ratings(ind,2); - - trialnum = length(y); - fprintf('Identified %g valid trials. \n',trialnum) - - plot(x,y,'bo','MarkerFaceColor','b');hold on; - %% - % set params - target_vas = [60 40 20]; - - % estimate linear function - ind = ~isnan(p.log.ratings(:,3)); - blin = [ones(numel(x(ind)),1) x(ind)]\y(ind); - est_lin(1) = linreverse(blin,target_vas(1)); - est_lin(2) = linreverse(blin,target_vas(2)); - est_lin(3) = linreverse(blin,target_vas(3)); - - - % estimate sigmoid function - a = mean(x); b = 1; % l/u bounds to be fitted - beta0 = [a b 0 100]; - options = statset('Display','final','Robust','on','MaxIter',10000); - [bsig,~] = nlinfit(x,y,@localsigfun,beta0,options); - est_sig(1) = sigreverse(bsig,target_vas(1)); - est_sig(2) = sigreverse(bsig,target_vas(2)); - est_sig(3) = sigreverse(bsig,target_vas(3)); - - % plot - xplot = linspace(min(x),max(x),100); - plot(xplot,localsigfun(bsig,xplot),'r',... - est_sig,localsigfun(bsig,est_sig),'ro',est_lin,target_vas,'bd',... - xplot,blin(1)+xplot.*blin(2),'b--'); - xlim([min(xplot)-.5 max(xplot)+.5]); - ylim([0 100]); - - % display - target_temp = est_sig; %clc; - results = [trial x y]; - disp(results); - fprintf(1,'estimates from sigmoidal fit (n=%d)\n\n',trialnum); - fprintf(1,'%g : %2.1f °C \tlinear: %2.1f °C\n',target_vas(1),target_temp(1),est_lin(1)); - fprintf(1,'%g : %2.1f °C \tlinear: %2.1f °C\n',target_vas(2),target_temp(2),est_lin(2)); - fprintf(1,'%g : %2.1f °C \tlinear: %2.1f °C\n',target_vas(3),target_temp(3),est_lin(3)); - - p.presentation.calib_est = [est_sig; est_lin]; - p.presentation.calib_target_vas = target_vas; - function xsigpred = sigreverse(bsig1,ytarget) - v=.5; a1 = bsig1(1); b1 = bsig1(2); L1 = bsig1(3); U1 = bsig1(4); - xsigpred = a1 + 1/-b1 * log((((U1-L1)/(ytarget-L1))^v-1)./v); - end - - function xlinpred = linreverse(blin1,ytarget) - a1 = blin1(1); b1 = blin1(2); - xlinpred = (ytarget - a1) / b1; - end - end -end diff --git a/exp_treatgen_calib16.m b/exp_treatgen_calib16.m deleted file mode 100644 index 93d09ba..0000000 --- a/exp_treatgen_calib16.m +++ /dev/null @@ -1,885 +0,0 @@ -function [p]=exp_treatgen_calib16(subject,run) -%[p]=FearGen_eyelab(subject,run,csp,PainThreshold) -% -%Used for fearamy project, based on the FearGen_eyelab code. It increments -%it by adding scanner pulse communications. -% -% - -debug = 0;%debug mode; -arduino = 0; -commandwindow; -%clear everything -clear mex global functions -cgshut; -global cogent; - -%%%%%%%%%%%load the GETSECS mex files so call them at least once -GetSecs; -WaitSecs(0.001); -% -p = []; -s = []; - -SetParams; -if arduino - SetArduino; -end -SetPTB; -% -%init all the variables -t = []; -nTrial = 0; -%% -%Time Storage -TimeCrossOn = []; -p.var.event_count = 0; -%% -KbQueueStop(p.ptb.device); -KbQueueRelease(p.ptb.device); -%save again the parameter file -save(p.path.path_param,'p'); - - -p.var.ExpPhase = run; -Screen('TextSize', p.ptb.w, 30); -[nx, ny, textbounds]=DrawFormattedText(p.ptb.w, GetText(0), 'center', 'center'); -Screen('TextSize', p.ptb.w, p.text.fontsize); -%Instructions -if run == 0 - ShowInstruction(0,0,3) - ShowInstruction(1,1); - LimitsProcedure; - ShowInstruction(10,1); -elseif run == 1 - ShowInstruction(0,0,3) - BuzzDemo; - ShowInstruction(1,1); - LimitsProcedure; - ShowInstruction(10,0,3); - ExperimenterInput(1);sc - ShowInstruction(2,1); % calibration with long instruction - PresentStimuli; -end - - -%trim the log file and save -p.out.log = p.out.log(sum(isnan(p.out.log),2) ~= size(p.out.log,2),:); -%shift the time so that the first timestamp is equal to zero -p.out.log(:,1) = p.out.log(:,1) - p.out.log(1); -save(p.path.path_param,'p'); -% -%move the file to its final location. -movefile(p.path.subject,p.path.finalsubject); -%close everything down -try - addpath('/USER/onat/Code/globalfunctions/ssh2_v2_m1_r6/ssh2_v2_m1_r6/') - p.path.tarname = [p.path.finalsubject(1:end-1) '.tar']; - tar(p.path.tarname,p.path.finalsubject); - [a b c] = fileparts( p.path.tarname); - cd(a) - scp_simple_put('sanportal','onat','',[b c]); - fprintf('Copying to neuronass succesfull...\n'); -catch - fprintf('Copying to neuronass failed...\n'); -end -cleanup; - - function LimitsProcedure - fprintf('Is the thermode set? Press v to start experiment from your side!\n') - k = 0; - while ~(k == p.keys.v); - pause(0.1); - [~, k] = KbStrokeWait(p.ptb.device); - k = find(k); - end - for n = 1:p.presentation.limits.ntrials - if n ==1 - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.rect); %always create a gray background - Screen('FillRect', p.ptb.w, p.stim.white, p.ptb.FixCross');%draw the prestimus cross atop - Screen('DrawingFinished',p.ptb.w,0); - TimeCrossOn = Screen('Flip',p.ptb.w); - WaitSecs(1); - end - if arduino - serialcom(s,'START'); - end - tic - %prepare red cross - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.rect); %always create a gray background - Screen('FillRect', p.ptb.w, p.ptb.fc_color, p.ptb.FixCross');%draw the prestimus cross atop - Screen('DrawingFinished',p.ptb.w,0); - TimeCrossOn = Screen('Flip',p.ptb.w); - fprintf('Trigger sent, raising temperature. '); - fprintf('Waiting for keypress...\n') - toc - %wait for keypress - k = 0; - while ~(k == p.keys.space); - pause(0.1); - [~, k] = KbStrokeWait(p.ptb.device); - k = find(k); - end - if arduino - serialcom(s,'MOVE',20)%this opens the "up" channel for xx ms, to stop thermode; - end - RT(n) = toc; - %turn back to white cross - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.rect); %always create a gray background - Screen('FillRect', p.ptb.w, p.stim.white, p.ptb.FixCross');%draw the prestimus cross atop - Screen('DrawingFinished',p.ptb.w,0); - Screen('Flip',p.ptb.w); - stoplim(n) = RT(n)*p.presentation.limits.ror + p.presentation.limits.base; - fprintf('Subject stopped at %5.2f °C.\n',stoplim(n)); - fprintf('ISI is on.') - tic - while toc<=p.presentation.limits.isi - pause(1) - fprintf('.') - end - end - p.presentation.limits.RT = RT; - p.presentation.limits.threshold = stoplim;%uncorrected - %p.presentation.limits.threshold_c = .05+.98*stoplim; %rough correction from lin. regression of pilote test - fprintf('------------------------------------------------------------------\n'); - fprintf('Estimated limits are: \n') - for n = 1:p.presentation.limits.ntrials - fprintf('(%g) %5.2f °C\n',n,stoplim(n)); - end - fprintf('Mean limits temp is %5.2f °C.\n',mean(stoplim)); - end - function BuzzDemo - ShowInstruction(3,1); - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.rect); %always create a gray background - Screen('FillRect', p.ptb.w, p.stim.white, p.ptb.FixCross');%draw the prestimus cross atop - Screen('DrawingFinished',p.ptb.w,0); - Screen('Flip',p.ptb.w); - fprintf('When done, turn the digitimer OFF and press v to continue.\n') - k = 0; - while ~(k == p.keys.v); - pause(0.1); - [~, k] = KbStrokeWait(p.ptb.device); - k = find(k); - end - Screen('Flip',p.ptb.w); - end - function PresentStimuli - - %Enter the presentation loop and wait for the first pulse to - %arrive. - %wait for the dummy scans - % [secs] = WaitPulse(p.keys.pulse,p.mrt.dummy_scan);%will log it - KbQueueStop(p.ptb.device); - WaitSecs(.05); - KbQueueCreate(p.ptb.device); - KbQueueStart(p.ptb.device);%this means that from now on we are going to log pulses. - %If the scanner by mistake had been started prior to this point - %those pulses would have been not logged. - % %log the pulse timings. - % TimeEndStim = secs(end)- p.ptb.slack;%take the first valid pulse as the end of the last stimulus. - for nTrial = 1:p.presentation.tTrial; - - %Get the variables that Trial function needs. - tempC = p.presentation.stimlist(nTrial); - prestimdur = randi([p.duration.prestim],1,1) + rand(1)*.25; - rampdur = abs((tempC - p.presentation.basetemp)/p.presentation.ror); % this is the time the thermode needs to ramp up/down. - % - FixOnset = GetSecs + p.duration.ISI; % white Fixcross - FixColor = FixOnset + prestimdur; % red Fixcross - Ramp1Onset = FixColor + p.duration.anticip + rand(1)*.7; % actual ramp to trial's temp - PlateauOnset = Ramp1Onset + rampdur; % reached plateau, then wait - Ramp2Onset = PlateauOnset + p.duration.painstim; % ramp back to baseline - RateOnset = Ramp2Onset + rampdur + p.duration.poststim; % - RateOffset = RateOnset + p.duration.rate; - - fprintf('Starting Trial %02d of %02d, Destination Temp is %5.2f C, White fix on for %5.2f s. \n',nTrial,p.presentation.tTrial,tempC,prestimdur); - %Start with the trial, here is time-wise sensitive must be - %optimal - PainTrial(nTrial,FixOnset,FixColor,Ramp1Onset,PlateauOnset,Ramp2Onset,RateOnset,RateOffset, tempC,rampdur); - end - Screen('Flip',p.ptb.w); - WaitSecs(1); - ShowInstruction(10,0,3); - end - function PainTrial(numTrial,FixOnset,FixColor,Ramp1Onset,PlateauOnset,Ramp2Onset, RateOnset,RateOffset, tempC,rampdur) - - %% Fixation (white) Onset - if numTrial ==1 % needed for first trial - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.rect); %always create a gray background - Screen('FillRect', p.ptb.w, p.stim.white, p.ptb.FixCross');%draw the prestimus cross atop - Screen('DrawingFinished',p.ptb.w,0); - TimeCrossOn = Screen('Flip',p.ptb.w,FixOnset,0); - Log(TimeCrossOn, 2, p.ptb.FixCross');%white cross onset. - MarkCED(p.com.lpt.address, p.com.lpt.Fix1) - end - %% Fixation (red) Onset - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.rect); %always create a gray background - Screen('FillRect', p.ptb.w, p.ptb.fc_color, p.ptb.FixCross');%draw the prestimus cross atop - Screen('DrawingFinished',p.ptb.w,0); - TimeCrossOn = Screen('Flip',p.ptb.w,FixColor,0); - Log(TimeCrossOn, 3, p.ptb.FixCross');%red cross onset. - MarkCED(p.com.lpt.address, p.com.lpt.Fix2) - %% Ramp to destination, wait there, ramp down. - if arduino - serialcom(s,'START',[],'verbose'); - end - Log(Ramp1Onset, 4, p.presentation.ror) % ramp up - MarkCED(p.com.lpt.address, p.com.lpt.RampUp) - fprintf('Ramping to %5.2f C in %.02f s.\n',tempC,rampdur) - if arduino - serialcom(s,'SET',tempC); - end - while GetSecs < PlateauOnset - end - Log(PlateauOnset, 5, tempC); % begin of stim plateau - MarkCED(p.com.lpt.address, p.com.lpt.Plateau) - fprintf('Plateau is on. \n') - countedDown = 1; - while GetSecs < Ramp2Onset - [countedDown]=CountDown(GetSecs-PlateauOnset,countedDown,'.'); - end - fprintf('\nRamping back to baseline %5.2f C in %.02f s. \n',p.presentation.basetemp,rampdur) - if arduino - serialcom(s,'SET',p.presentation.basetemp) - end - WaitSecs(rampdur); - Log(Ramp2Onset, 6, p.presentation.ror) % ramp down - MarkCED(p.com.lpt.address, p.com.lpt.RampDown) - - %% Rating - Screen('Flip', p.ptb.w); - while GetSecs < RateOnset - end - Log(RateOnset,9,NaN); % log the rating onset - MarkCED(p.com.lpt.address, p.com.lpt.RateOn) - rateinit = randi(p.rating.initrange); - [currentRating.finalRating,currentRating.RT,currentRating.response] = vasScale(p.ptb.w,p.ptb.rect,p.duration.rate,rateinit,... - p.stim.bg,p.ptb.startY,p.keys); - Log(GetSecs,10,NaN); % log the rating offset - MarkCED(p.com.lpt.address, p.com.lpt.RateOff) - PutRatingLog(numTrial,currentRating,tempC,rateinit) - %% put fixation cross if rating ended before time ran out - Screen('FillRect', p.ptb.w , p.stim.bg, p.ptb.rect); %always create a gray background - Screen('FillRect', p.ptb.w, p.stim.white, p.ptb.FixCross');%draw the prestimus cross atop - Screen('DrawingFinished',p.ptb.w,0); - TimeCrossOn = Screen('Flip',p.ptb.w); - Log(TimeCrossOn, 2, p.ptb.FixCross');%white cross onset. - MarkCED(p.com.lpt.address, p.com.lpt.Fix1) - while GetSecs < RateOffset - end - end - function ExperimenterInput(num) - if num == 1 - mantemps = input('Please enter the limits temps: \n'); - p.stim.limits.threshold_m = mantemps; - p.stim.limits.threshold_ave = mean(mantemps); - p.presentation.basetemp = mean(mantemps); - p.presentation.stimlist = p.presentation.basetemp + p.presentation.steps; - fprintf('Your stimlist: %g \n',p.presentation.stimlist'); - fprintf('----------------------------------\n') - fprintf('Please set thermode baseline to: %5.2f C.\n',p.presentation.stimlist'); - fprintf('----------------------------------\n') - fprintf('Is the thermode set? Press v to start calibration procedure from your side!\n') - k = 0; - while ~(k == p.keys.v); - pause(0.1); - [~, k] = KbStrokeWait(p.ptb.device); - k = find(k); - end - else - %other options - end - end - function SetParams - %relative path to stim and experiments - %Path Business. - [~, hostname] = system('hostname'); - p.hostname = deblank(hostname); - if strcmp(p.hostname,'triostim1') - p.path.baselocation = 'C:\USER\kampermann\Experiments\'; - elseif strcmp(p.hostname,'isn3464a9d59588') % Lea's HP - p.path.baselocation = 'C:\Users\Lea\Documents\Experiments\'; - else - error('Unknown PC found, please define it for folder structure.') - end - - p.path.experiment = [p.path.baselocation 'Treatgen\']; - p.path.stim = [p.path.experiment 'Stimuli\']; - % - p.subID = sprintf('sub%02d',subject); - p.path.edf = sprintf([p.subID 'p%02d' ],run); - timestamp = datestr(now,30); - p.path.subject = [p.path.experiment 'data\tmp\' p.subID '_' timestamp '\']; - p.path.finalsubject = [p.path.experiment 'data\calibration\' p.subID '_Session' num2str(run) '\' ]; - %create folder hierarchy - mkdir(p.path.subject); - mkdir([p.path.subject 'scr']); - % mkdir([p.path.subject 'eye']); - % mkdir([p.path.subject 'quadruplet']); - mkdir([p.path.subject 'stimulation']); - mkdir([p.path.subject 'midlevel']); - p.path.path_param = sprintf([regexprep(p.path.subject,'\\','\\\') 'stimulation\\param_phase_%02d'],run); - - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %get stim files to anticipate bg color - [p.stim.files p.stim.label] = FileMatrix([p.path.stim '*.bmp']); - im = imread(p.stim.files(1,:)); - p.stim.bg = im(1,1,1); %151 - % - %font size and background gray level - p.text.fontname = 'Arial'; - p.text.fontsize = 18;%30; - p.text.linespace = 10; - p.text.lineheight = p.text.fontsize + p.text.linespace; - %rating business - p.rating.division = 101; %number of divisions for the rating slider - p.rating.initrange = [35,65]; - % - p.stim.white = [255 255 255]; - if strcmp(p.hostname,'triostim1') - p.keys.space = KbName('space'); - p.keys.confirm = KbName('7'); - p.keys.increase = KbName('8'); - p.keys.decrease = KbName('6'); - p.keys.esc = KbName('esc'); - else - %All settings for laptop computer. - p.keys.confirm = KbName('up'); - p.keys.increase = KbName('right'); - p.keys.decrease = KbName('left'); - p.keys.space = KbName('space'); - p.keys.esc = KbName('esc'); - p.keys.null = KbName('0)'); - p.keys.one = KbName('1!'); - p.keys.v = KbName('v'); - end - - %get all the required keys in a vector - p.ptb.keysOfInterest = [];for i = fields(p.keys)';p.ptb.keysOfInterest = [p.ptb.keysOfInterest p.keys.(i{1})];end - fprintf('Key listening will be restricted to %d\n',p.ptb.keysOfInterest) - RestrictKeysForKbCheck(p.ptb.keysOfInterest); - - p.ptb.keysOfInterest=zeros(1,256); - p.ptb.keysOfInterest(p.keys.confirm) = 1; - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %Communication business - %parallel port - p.com.lpt.address = 888; - %codes for different events - p.com.lpt.Fix1 = 1; - p.com.lpt.Fix2 = 2; - %2 is empty because - p.com.lpt.RampUp = 4; - p.com.lpt.Plateau = 8; - p.com.lpt.RampDown = 16; - p.com.lpt.RateOn = 32; - p.com.lpt.RateOff = 64; - %p.com.lpt.CS_neg = 128; - % - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %timing business - %these are the intervals of importance - %time2fixationcross->cross2onset->onset2shock->shock2offset - %these (duration.BLA) are average duration values: - p.duration.painstim = 5;% - p.duration.prestim = [2 4]; - p.duration.anticip = 1; - p.duration.poststim = 1; - p.duration.ISI = 1; - p.duration.rate = 5; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %stimulus sequence - s = load([p.path.stim 'stimlist\caliblist.mat']); - p.presentation.steps = s.steps; - - p.presentation.basetemp = NaN; - p.presentation.ror = 5; - p.presentation.run = run; - - p.presentation.limits.base = 25; - p.presentation.limits.ror = 5; - p.presentation.limits.isi = 5; - p.presentation.limits.ntrials = 3; - p.presentation.limits.RT = zeros(p.presentation.limits.ntrials,1); - p.presentation.limits.threshold = zeros(p.presentation.limits.ntrials,1); - - %this will deal all the presentation sequence related information -% p.presentation.Tmax = threshold + 3; - p.presentation.stimlist = p.presentation.basetemp + p.presentation.steps;%Threshold + 3 is maximum temperature - p.presentation.tTrial = length(p.presentation.stimlist); - % - - p.log.ratingEventCount = 0; - p.log.ratings = []; - p.out.log = zeros(1000000,4).*NaN; - p.out.response = zeros(p.presentation.tTrial,1); - %Save the stuff - save(p.path.path_param,'p'); - % - function [FM labels] = FileMatrix(path) - %Takes a path with file extension associated to regexp (e.g. - %C:\blabl\bla\*.bmp) returns the file matrix - dummy = dir(path); - FM = [repmat([fileparts(path) filesep],length(dummy),1) vertcat(dummy(:).name)]; - labels = {dummy(:).name}; - end - end - function SetArduino - s = serial('COM5','BaudRate',19200); - fopen(s); - WaitSecs(1); - serialcom(s,'T',p.presentation.basetemp); - serialcom(s,'ROR',p.presentation.ror); - WaitSecs(.5); - serialcom(s,'DIAG'); - WaitSecs(1); - end - function [finalRating,reactionTime,response] = vasScale(window,windowRect,durRating,defaultRating,backgroundColor,StartY,keys) - - %% key settings - KbName('UnifyKeyNames'); - lessKey = keys.decrease; % yellow button - moreKey = keys.increase; % red button - confirmKey = keys.confirm; % green button - escapeKey = keys.esc; - - if isempty(window); error('Please provide window pointer for likertScale!'); end - if isempty(windowRect); error('Please provide window rect for likertScale!'); end - if isempty(durRating); error('Duration length of rating has to be specified!'); end - - %% Default values - nRatingSteps = p.rating.division; - scaleWidth = 700; - textSize = 20; - lineWidth = 6; - scaleColor = [255 255 255]; - activeColor = [255 0 0]; - if isempty(defaultRating); defaultRating = round(nRatingSteps/2); end - if isempty(backgroundColor); backgroundColor = 0; end - - - - % if length(ratingLabels) ~= nRatingSteps - % error('Rating steps and label numbers do not match') - % end - - %% Calculate rects - activeAddon_width = 1.5; - activeAddon_height = 20; - [xCenter, yCenter] = RectCenter(windowRect); - yCenter = StartY; - axesRect = [xCenter - scaleWidth/2; yCenter - lineWidth/2; xCenter + scaleWidth/2; yCenter + lineWidth/2]; - lowLabelRect = [axesRect(1),yCenter-20,axesRect(1)+6,yCenter+20]; - highLabelRect = [axesRect(3)-6,yCenter-20,axesRect(3),yCenter+20]; - ticPositions = linspace(xCenter - scaleWidth/2,xCenter + scaleWidth/2-lineWidth,nRatingSteps); - % ticRects = [ticPositions;ones(1,nRatingSteps)*yCenter;ticPositions + lineWidth;ones(1,nRatingSteps)*yCenter+tickHeight]; - activeTicRects = [ticPositions-activeAddon_width;ones(1,nRatingSteps)*yCenter-activeAddon_height;ticPositions + lineWidth+activeAddon_width;ones(1,nRatingSteps)*yCenter+activeAddon_height]; - % keyboard - - - Screen('TextSize',window,textSize); - Screen('TextColor',window,[255 255 255]); - Screen('TextFont', window, 'Arial'); - currentRating = defaultRating; - finalRating = currentRating; - reactionTime = 0; - response = 0; - first_flip = 1; - startTime = GetSecs; - numberOfSecondsRemaining = durRating; - nrbuttonpresses = 0; - - %%%%%%%%%%%%%%%%%%%%%%% loop while there is time %%%%%%%%%%%%%%%%%%%%% - % tic; % control if timing is as long as durRating - while numberOfSecondsRemaining > 0 - Screen('FillRect',window,backgroundColor); - Screen('FillRect',window,scaleColor,axesRect); - Screen('FillRect',window,scaleColor,lowLabelRect); - Screen('FillRect',window,scaleColor,highLabelRect); - Screen('FillRect',window,activeColor,activeTicRects(:,currentRating)); - - DrawFormattedText(window, 'Bitte bewerten Sie die Schmerzhaftigkeit', 'center',yCenter-100, scaleColor); - DrawFormattedText(window, 'des Hitzereizes', 'center',yCenter-70, scaleColor); - - Screen('DrawText',window,'kein',axesRect(1)-17,yCenter+25,scaleColor); - Screen('DrawText',window,'Schmerz',axesRect(1)-40,yCenter+45,scaleColor); - - Screen('DrawText',window,'unerträglicher',axesRect(3)-55,yCenter+25,scaleColor); - Screen('DrawText',window,'Schmerz',axesRect(3)-40,yCenter+45,scaleColor); - - - - % Remove this line if a continuous key press should result in a continuous change of the scale - % while KbCheck; end - - if response == 0 - - % set time 0 (for reaction time) - if first_flip == 1 - secs0 = Screen('Flip', window); % output Flip -> starttime rating - first_flip = 0; - % after 1st flip -> just flips without setting secs0 to null - else - Screen('Flip', window); - end - - [ keyIsDown, secs, keyCode ] = KbCheck; % this checks the keyboard very, very briefly. - if keyIsDown % only if a key was pressed we check which key it was - response = 0; % predefine variable for confirmation button 'space' - nrbuttonpresses = nrbuttonpresses + 1; - if keyCode(moreKey) % if it was the key we named key1 at the top then... - currentRating = currentRating + 1; - finalRating = currentRating; - response = 0; - if currentRating > nRatingSteps - currentRating = nRatingSteps; - end - elseif keyCode(lessKey) - currentRating = currentRating - 1; - finalRating = currentRating; - response = 0; - if currentRating < 1 - currentRating = 1; - end - elseif keyCode(confirmKey) - finalRating = currentRating-1; - disp(['VAS Rating: ' num2str(finalRating)]); - response = 1; - reactionTime = secs - secs0; - break; - end - end - end - - numberOfSecondsElapsed = (GetSecs - startTime); - numberOfSecondsRemaining = durRating - numberOfSecondsElapsed; - end - if nrbuttonpresses ~= 0 && response == 0 - finalRating = currentRating - 1; - reactionTime = durRating; - disp(['VAS Rating: ' num2str(finalRating)]); - warning(sprintf('\n***********\nNo Confirmation!\n***********\n')); - end - if nrbuttonpresses == 0 - finalRating = NaN; - reactionTime = durRating; - disp(['VAS Rating: ' num2str(finalRating)]); - warning(sprintf('\n***********\nNo Response!\nPlease check participant!\n***********\n')); - end - % toc - end - - - - function ShowInstruction(nInstruct,waitforkeypress,varargin) - %ShowInstruction(nInstruct,waitforkeypress) - %if waitforkeypress is 1, ==> subject presses a button to proceed - %if waitforkeypress is 0, ==> text is shown for VARARGIN seconds. - - - [text]= GetText(nInstruct); - ShowText(text); - if waitforkeypress %and blank the screen as soon as the key is pressed - KbStrokeWait(p.ptb.device); - else - WaitSecs(varargin{1}); - end - Screen('FillRect',p.ptb.w,p.stim.bg); - t = Screen('Flip',p.ptb.w); - - function ShowText(text) - - Screen('FillRect',p.ptb.w,p.stim.bg); - DrawFormattedText(p.ptb.w, text, 'center', 'center',p.stim.white,[],[],[],2,[]); - t=Screen('Flip',p.ptb.w); - Log(t,-1,nInstruct); - %show the messages at the experimenter screen - fprintf('=========================================================\n'); - fprintf('Text shown to the subject:\n'); - fprintf(text); - fprintf('=========================================================\n'); - - end - end - function [text]=GetText(nInstruct) - if nInstruct == 0% - - text = ['Kalibrationsphase']; - - elseif nInstruct == 1 %Instruction - text = ['Bestimmung der Schmerzschwelle von Hitzereizen.\n'... - 'Wir bestimmen nun Ihre individuelle Hitzeschmerzempfindung.' - 'Wir werden dazu die Temperatur langsam schrittweise erhöhen.\n'... - 'Bitte schauen Sie während des Vorgangs auf das weiße Kreuz.\n'... - 'Ihre Aufgabe ist es, die Leertaste zu drücken, sobald Sie die Temperatur als schmerzhaft empfinden,\n' ... - 'd.h. sobald zum Gefühl von Wärme ein unangenehmes Gefühl wie Brennen oder Stechen hinzukommt.\n' ... - 'Der Vorgang wird drei mal wiederholt.\n' ... - '\n'... - 'Falls Sie noch Fragen haben, wenden Sie sich bitte noch einmal an die Versuchsleiterin.\n' ... - 'Drücken Sie sonst bitte die obere Taste, um zu starten.\n']; - elseif nInstruct == 2 %Instruction - text = ['Im Folgenden möchten wir Ihre individuelle Schmerzempfindung noch genauer bestimmen.\n' ... - 'Dazu senden wir Ihnen mehrere Hitzereize, die Sie anschließend mittels\n' ... - 'einer Schmerz-Skala bewerten sollen. Sie haben dazu 5 Sek Zeit. Falsche Antworten gibt es bei dieser\n' ... - 'Aufgabe nicht, da individuelle Empfindungen sehr unterschiedlich sein können.\n' ... - 'Nutzen Sie die Pfeiltasten zum Bewerten & bestätigen Sie Ihre Eingabe immer\n' ... - 'mit der oberen Pfeiltaste. Bitte versuchen Sie sich auch auf kleinste Reizänderungen\n' ... - 'zu konzentrieren & bewerten Sie diese so präzise wie möglich.\n'... - '\n'... - 'Falls Sie noch Fragen haben, wenden Sie sich bitte noch einmal an die Versuchsleiterin.\n' ... - 'Drücken Sie sonst bitte die obere Taste, um zu starten.\n']; - elseif nInstruct == 3%short Digitimer stimulation - text = ['Kalibration der TENS-Intensität.\n' ... - '\n'... - 'Wir werden nun als Erstes das TENS-Gerät kalibrieren.\n'... - 'Dazu erhalten Sie kurze Stimulationen aufsteigender Intensität.\n'... - '\n'... - 'Bitte geben Sie der Versuchsleiterin Bescheid, sobald Sie ein Kribbeln an der Elektrode spüren.\n'... - '\n'... - 'Die Stimulation während des Experiments wird dann unterschwellig durchgeführt,\n'... - 'd.h. Sie werden diese nicht mehr bewusst wahrnehmen.\n'... - '\n'... - '\n'... - 'Falls Sie noch Fragen haben, wenden Sie sich bitte noch einmal an die Versuchsleiterin.\n' ... - 'Drücken Sie sonst bitte die obere Taste, um zu starten.\n']; - elseif nInstruct == 200%short instruction for second run - text = ['Wiederholung der Schwellenkalibrierung.\n'... - '\n'... - 'Nutzen Sie die Tasten von Zeigefinger (links) & Ringfinger (rechts) zum Bewerten.\n'... - 'Bestätigen Sie Ihre Eingabe immer mit der mittleren Taste (oben). Falls Sie noch \n'... - 'Fragen haben, teilen Sie dies gleich noch einmal der Versuchsleiterin mit. \n'... - ]; - elseif nInstruct == 10 - text = ['Vielen Dank!\n'... - 'Es geht gleich weiter. \n']; - elseif nInstruct == 11 %end - text = ['Bitte bewerten Sie, wie schmerzhaft der soeben erhaltene Reiz für Sie war.']; - elseif nInstruct == 12 %These two below are the possible responses to the question in 11 - text = {'unerträglich\nschmerzhaft'}; - elseif nInstruct == 13 - text = {'Überhaupt\nnicht\nschmerzhaft'}; - else - text = {''}; - end - end - function SetPTB - %KbName('UnifyKeyNames'); - %Sets the parameters related to the PTB toolbox. Including - %fontsizes, font names. - %Default parameters - Screen('Preference', 'SkipSyncTests', 1); - Screen('Preference', 'DefaultFontSize', p.text.fontsize); - Screen('Preference', 'DefaultFontName', p.text.fontname); - Screen('Preference', 'TextAntiAliasing',2);%enable textantialiasing high quality - Screen('Preference', 'VisualDebuglevel', 0); - Screen('Preference', 'SkipSyncTests', 1); - Screen('Preference', 'SuppressAllWarnings', 1); - %%Find the number of the screen to be opened - screens = Screen('Screens'); - p.ptb.screenNumber = max(screens);%the maximum is the second monitor - %Make everything transparent for debugging purposes. - if debug - commandwindow; - PsychDebugWindowConfiguration; - end - %set the resolution correctly - res = Screen('resolution',p.ptb.screenNumber); - HideCursor(p.ptb.screenNumber); - %spit out the resolution - fprintf('Resolution of the screen is %dx%d...\n',res.width,res.height); - - %Open a graphics window using PTB - [p.ptb.w p.ptb.rect] = Screen('OpenWindow', p.ptb.screenNumber, p.stim.bg); - %Screen('BlendFunction', p.ptb.w, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - Screen('Flip',p.ptb.w);%make the bg - p.ptb.slack = Screen('GetFlipInterval',p.ptb.w)./2; - [p.ptb.width, p.ptb.height] = Screen('WindowSize', p.ptb.screenNumber); - p.ptb.startY = p.ptb.height./2; %should be px(yaxis)./4; - %find the mid position on the screen. - p.ptb.midpoint = [ p.ptb.width./2 p.ptb.height./2]; - %NOTE about RECT: - %RectLeft=1, RectTop=2, RectRight=3, RectBottom=4. - % p.ptb.CrossPosition_x = p.ptb.midpoint(1);%bb(1);%always the same - % p.ptb.CrossPosition_y = p.ptb.midpoint(2)./2; - - p.ptb.fc_size = 20; - p.ptb.fc_width = 4; - p.ptb.fc_color = [255 0 0]; - % p.ptb.screenFix1 = [p.ptb.midpoint(1)-p.ptb.fc_size p.ptb.startY-p.ptb.fc_width p.ptb.midpoint(1)+p.ptb.fc_size p.ptb.startY+p.ptb.fc_width]; %I guess this is X - % p.ptb.screenFix2 = [p.ptb.midpoint(1)-p.ptb.fc_width p.ptb.startY-p.ptb.fc_size p.ptb.midpoint(1)+p.ptb.fc_width p.ptb.startY+p.ptb.fc_size]; %I guess this is Y - fix = [p.ptb.midpoint(1) p.ptb.startY]; % yaxis is 1/4 of total yaxis - p.ptb.FixCross = [fix(1)-p.ptb.fc_width,fix(2)-p.ptb.fc_size,fix(1)+p.ptb.fc_width,fix(2)+p.ptb.fc_size;fix(1)-p.ptb.fc_size,fix(2)-p.ptb.fc_width,fix(1)+p.ptb.fc_size,fix(2)+p.ptb.fc_width]; - - % - %% - %priorityLevel=MaxPriority(['GetSecs'],['KbCheck'],['KbWait'],['GetClicks']); - Priority(MaxPriority(p.ptb.w)); - %this is necessary for the Eyelink calibration - %InitializePsychSound(0) - %sound('Open') - % Beeper(1000) - LoadPsychHID - %%%%%%%%%%%%%%%%%%%%%%%%%%%Prepare the keypress queue listening. - p.ptb.device = []; - %get all the required keys in a vector - p.ptb.keysOfInterest = [];for i = fields(p.keys)';p.ptb.keysOfInterest = [p.ptb.keysOfInterest p.keys.(i{1})];end - fprintf('Key listening will be restricted to %d\n',p.ptb.keysOfInterest) - RestrictKeysForKbCheck(p.ptb.keysOfInterest); - - p.ptb.keysOfInterest=zeros(1,256); - p.ptb.keysOfInterest(p.keys.confirm) = 1; - %create a queue sensitive to only relevant keys. - % KbQueueCreate(p.ptb.device,p.ptb.keysOfInterest);%default device. - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %prepare parallel port communication. This relies on cogent i - %think. We could do it with PTB as well. - if ~ismac - config_io; - outp(p.com.lpt.address,0); - if( cogent.io.status ~= 0 ) - error('inp/outp installation failed'); - end - end - - %CORRECT - %%%%%%%%%%%%%%%%%%%%%%%%%%% - %test whether CED receives the triggers correctly... - % k = 0; - % while ~(k == 25 | k == 86 ); - % pause(0.1); - % outp(p.com.lpt.address,244);%244 means all but the UCS channel (so that we dont shock the subject during initialization). - % fprintf('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'); - % fprintf('1/ Red cable has to be connected to the Cogent BOX\n'); - % fprintf('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'); - % fprintf('2/ D2 Connection not to forget on the LPT panel\n'); - % fprintf('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'); - % fprintf('3/ Switch the SCR cable\n'); - % fprintf('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'); - % fprintf('4/ Button box has to be on\n'); - % fprintf('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'); - % fprintf('5/ Did the trigger test work?\n!!!!!!You MUST observe 5 pulses on the PHYSIOCOMPUTER!!!!!\n\n\nPress c to send it again, v to continue...\n') - % [~, k] = KbStrokeWait(p.ptb.device); - % k = find(k); - % end - % fprintf('Continuing...\n'); - %%%%%%%%%%%%%%%%%%%%%%%%%%% - - end - function [shuffled idx] = Shuffle(vector,N) - %takes first N from the SHUFFLED before outputting. This function - %could be used as a replacement for randsample - if nargin < 2;N = length(vector);end - [~, idx] = sort(rand([1 length(vector)])); - shuffled = vector(idx(1:N)); - shuffled = shuffled(:); - end - - function [countedDown]=CountDown(secs, countedDown, countString) - if secs>countedDown - fprintf('%s', countString); - countedDown=ceil(secs); - end - end - - function MarkCED(socket,port) - %send pulse to SCR# - outp(socket,port); - WaitSecs(0.01); - outp(socket,0); - end - - function cleanup - % Close window: - sca; - %set back the old resolution - if strcmp(p.hostname,'triostim1') - % Screen('Resolution',p.ptb.screenNumber, p.ptb.oldres.width, p.ptb.oldres.height ); - %show the cursor - ShowCursor(p.ptb.screenNumber); - end - % - commandwindow; - KbQueueStop(p.ptb.device); - KbQueueRelease(p.ptb.device); - if arduino - fclose(s); - end - end - function Log(ptb_time, event_type, event_info) - %Phases: - %Instruction : 0 - %Test : 1 - %Rating : 5 - %Calibration : 0 - % - %event types are as follows: - % - % % % %Pulse Detection : 0 info: NaN; - % % % %Tracker Onset : 1 - % % % %Cross Onset : 2 info: position - % % % %Stimulus Onset : 3 info: dist_id - % % % %Cross Movement : 4 info: NaN; - % % % %UCS Delivery : 5 info: NaN; - % % % %Stimulus Offset : 6 info: NaN; - % % % %Key Presses : 7 info: NaN; - % % % %Tracker Offset : 8 info: NaN; - % % % %MicroBlock : 9 info:rank - %%%%%%%%%%%%%%%%% - % %Pulse Detection : 0 info: NaN; - % %Tracker Onset : 1 - % %Cross (white) Onset : 2 info: position - % %Cross (red) Onset : 3 info: position - % %Ramp Up Onset : 4 info: ror - % %Pain Plateau : 5 info: temp - % %Ramp Down Onset : 6 info: ror; - % %Key Presses : 7 info: NaN; - % %Tracker Offset : 8 info: NaN; - % %Rate Onset : 9 info: NaN; - % %Rate Offset : 10 info: NaN; - % %dummy fixflip : 22 info: NaN; - %Text on the screen : -1 info: Which Text? - for iii = 1:length(ptb_time) - p.var.event_count = p.var.event_count + 1; - p.out.log(p.var.event_count,:) = [ptb_time(iii) event_type event_info(iii) p.var.ExpPhase]; - end - % plot(p.out.log(1:p.var.event_count,1) - p.out.log(1,1),p.out.log(1:p.var.event_count,2),'o','markersize',10); - % ylim([-2 8]); - % set(gca,'ytick',[-2:8],'yticklabel',{'Rating On','Text','Pulse','Tracker+','Cross+','Stim+','CrossMov','UCS','Stim-','Key+','Tracker-'}); - % grid on - % drawnow; - - end - function PutRatingLog(Trialnum,currentRating,tempC,rateinit) - - p.log.ratingEventCount = p.log.ratingEventCount + 1; - p.log.ratings(p.log.ratingEventCount,1) = tempC; - p.log.ratings(p.log.ratingEventCount,2) = Trialnum; - p.log.ratings(p.log.ratingEventCount,3) = currentRating.finalRating; - p.log.ratings(p.log.ratingEventCount,4) = currentRating.response; - p.log.ratings(p.log.ratingEventCount,5) = currentRating.RT; - p.log.ratings(p.log.ratingEventCount,6) = rateinit; - end - - function [keycode, secs] = KbQueueDump; - %[keycode, secs] = KbQueueDump - % Will dump all the events accumulated in the queue. - - keycode = []; - secs = []; - pressed = []; - %fprintf('there are %03d events\n',KbEventAvail(p.ptb.device)); - while KbEventAvail(p.ptb.device) - [evt, n] = KbEventGet(p.ptb.device); - n = n + 1; - keycode(n) = evt.Keycode; - pressed(n) = evt.Pressed; - secs(n) = evt.Time; - % fprintf('Event is: %d\n',keycode(n)); - end - i = pressed == 1; - keycode(~i) = []; - secs(~i) = []; - %fprintf('there are %03d events found...\n',length(keycode)); - end -end diff --git a/exprndtrunc.m b/exprndtrunc.m new file mode 100644 index 0000000..7b01590 --- /dev/null +++ b/exprndtrunc.m @@ -0,0 +1,10 @@ +function sample = exprndtrunc(rate, low, high) +x = low:high; +y = exppdf(x, rate); +y = cumsum(y/sum(y)); +y = y/max(y); +t = rand; +idx = find(t<=y, 1, 'first'); +sample = x(idx); + +end \ No newline at end of file diff --git a/fearcloud_FitPMFs.m b/fearcloud_FitPMFs.m deleted file mode 100644 index 9cc6cc9..0000000 --- a/fearcloud_FitPMFs.m +++ /dev/null @@ -1,127 +0,0 @@ -function [out]=fearcloud_FitPMFs(subjects) -for subject=subjects - -% -fig=figure('units','normalized','position',[0 1 0.7 0.9]); -suptitle(sprintf('Fitting Subject %g',subject)); - -out.params1 = NaN(4,4); -out.Likelihood = NaN(4,1); -out.ExitFlag = NaN(4,1); - - -cr=0; -for run = [1 5]; - for chain = [1 2]; - - StimLevels = 0:11.25:180; - x = linspace(0,180,1000); - - %get responses, and resulting PMF from PAL algorithm - responses = fearcloud_GetPMFresponses(subject,run,chain,'yes'); - pmf = isn_getPMF(subject,run); - p = isn_GetData(subject,run,'stimulation');p = p.p; - - i = ~isnan(responses.yes); - - NumPos = responses.yes(i); % number of "different" responses - OutOfNum = responses.num(i); % number of presentations at that level - PropCorrectData = NumPos./OutOfNum; - StimLevels = StimLevels(i); - - minn = 5; - maxn = 25; - - dotsize = Scale(sum(~isnan(p.psi.log.xrounded(:,:,chain)),2))*(maxn-minn)+minn; - dotsize = dotsize(i); - error = nanstd(p.psi.log.xrounded(:,:,chain),0,2); - error = error(i); - - - % take the priors as search grid (gamma extended to .5, resolution very low -% % for little Laptop of Lea's) -% searchGrid.alpha = pmf.alpha(chain); -% searchGrid.beta = 4; -% searchGrid.gamma = PropCorrectData(1); -% searchGrid.lambda = 1-PropCorrectData(end); -% params0 = [ searchGrid.alpha searchGrid.beta searchGrid.gamma searchGrid.lambda]; -% -% - % %ooor use the params that PAL gave as results - searchGrid.alpha = 80; - searchGrid.beta = 2;%10.^pmf.beta(chain); - searchGrid.gamma = PropCorrectData(1);%pmf.gamma(chain); - searchGrid.lambda = 1-PropCorrectData(end);%pmf.lambda(chain); - params0 = [ searchGrid.alpha searchGrid.beta searchGrid.gamma searchGrid.lambda]; - - %oooor use the params that the first Weibull try gave as subject's -% %mean across all four PMFs: -% data=load('C:\Users\onat\Desktop\Lea\Weibulldata_allsubj_1st.mat','fits'); -% data=data.fits; -% -% submean = mean(data(subject).params1(1:4,:),1); -% -% searchGrid.alpha = submean(1); -% searchGrid.beta = submean(2); -% searchGrid.gamma = submean(3); -% searchGrid.lambda = submean(4); -% -% -% params0 = [ searchGrid.alpha searchGrid.beta searchGrid.gamma searchGrid.lambda]; -% -% % paramsFree = [1 1 1 1]; - PF = @PAL_Weibull; - - %% run the Fit! - options = PAL_minimize('options'); - options.MaxIter = 10.^6; - options.MaxFunEvals = 10.^6; - options.Display = 'On'; - options.TolX = 10.^-4; - options.TolFun = 10.^-4; - - % [paramsValues LL exitflag output] = PAL_PFML_Fit(StimLevels, NumPos, OutOfNum, searchGrid, paramsFree, PF,'lapseLimits',[0 1],'guessLimits',[0 1],'searchoptions',options); - X = abs(p.psi.log.x(chain,:)); - Y = abs(p.psi.log.response(chain,:)); - % funny = @(params) sum( (Y - PF(params,X)).^2); - - funny = @(params) sum(-log (binopdf(NumPos,OutOfNum,PF(params,StimLevels)))); - %params(end) - - - options = optimset('Display','iter','maxfunevals',10000,'tolX',10^-12,'tolfun',10^-12,'MaxIter',10000,'Algorithm','interior-point'); - - [o.params1, o.Likelihood, o.ExitFlag] = fmincon(funny, params0, [],[],[],[],[-Inf -Inf 0 0],[Inf Inf 1 1],[],options); - - out.params1(chain+cr,:) = o.params1; - out.Likelihood(chain+cr,1) = o.Likelihood; - out.ExitFlag(chain+cr,1) = o.ExitFlag ; - out.subInd = subject; - %% plot the Fit - Fit = PF(o.params1,x); - - subplot(2,2,chain+cr) - hold on; - plot(x,PAL_CumulativeNormal([pmf.alpha(chain) 10.^(pmf.beta(chain)) pmf.gamma(chain) pmf.lambda(chain)],x),'k','linewidth',3); - plot(x,PF([searchGrid.alpha searchGrid.beta searchGrid.gamma searchGrid.lambda],x),'r-','Linewidth',3); - plot(x,Fit,'g-','Linewidth',3); - xlim([-5 180]); - legend('PALs PMF','InitialValues','New Fit','location','southeast') - title(sprintf('Run %g, Chain %g, L = %03g',run,chain,o.Likelihood)) - for i = 1:length(StimLevels) - errorbar(StimLevels(i),PropCorrectData(i),error(i),'o','Markersize',dotsize(i),'markerfacecolor',[0.3 0.3 0.3],'color',[0.3 0.3 0.3]); - end - hold off; - - end -cr=cr+2; -end - -%% -% save_path = sprintf('%sfigures/%s_test.eps',isn_GetPath(subject,run),mfilename); -% hgexport(fig,save_path); -% saveas(fig,sprintf('%sfigures/%s_png_test.png',isn_GetPath(subject,run),mfilename)); -% saveas(fig,sprintf('%sfigures/%s_test.fig',isn_GetPath(subject,run),mfilename)); -% close all -end -end diff --git a/fearcloud_GetPMFresponses.m b/fearcloud_GetPMFresponses.m deleted file mode 100644 index 0f36fce..0000000 --- a/fearcloud_GetPMFresponses.m +++ /dev/null @@ -1,32 +0,0 @@ -function [out]=fearcloud_GetPMFresponses(sub,run,chain,mod) -%Gets responses from the Discrimination Task for one subject, one run -%(before or after), one CS (CS+ or CS-), and allows to choose output -%format: -%MATRIX gives you the P_correct matrix with NaNs and 0 and 1, where rows -%are stimlevels and columns are trials -%P_CORRECT gives the percentage correct for stimlevels -%YES gives out.yes = number of yes -% out.num = number of trials it was asked -global project_path - - -p=isn_GetData(sub,run,'stimulation'); -p=p.p; -resp=p.psi.log.xrounded(:,:,chain); -if strcmp(mod,'matrix') - out=resp; -elseif strcmp(mod,'p_correct') - out=nanmean(resp,2); -elseif strcmp(mod,'yes') - out=struct('yes',NaN(1,size(resp,1)),'num',NaN(1,size(resp,1))); - for level=1:size(resp,1); - if ~isnan(resp(level,1)); - out.yes(level)=sum(resp(level,~isnan(resp(level,:)))); - out.num(level)=length(resp(level,~isnan(resp(level,:)))); - end - end -else - fprintf('Select correct Input : matrix, p_correct, or yes!') - out=[]; -end -end \ No newline at end of file diff --git a/fearcloud_analyze_pmf600.m b/fearcloud_analyze_pmf600.m deleted file mode 100644 index 80e0a13..0000000 --- a/fearcloud_analyze_pmf600.m +++ /dev/null @@ -1,142 +0,0 @@ -%%%%%%%%%%600ms version analysis and plot script.... - -global project_path;project_path='C:\Users\onat\Google Drive\EthnoMaster\data\' - -subjects=[40,42,44,45,46,47,48,49,51]; -pmf=isn_getPMF(subjects,[1 5]); - -n=length(subjects); - -betaSD=10.^-pmf.beta; -%compute the means and stds -alpha.mean=mean(pmf.alpha); -alpha.std=std(pmf.alpha); -alpha.sem=alpha.std/sqrt(n); -beta.mean=mean(pmf.beta); -beta.std=std(pmf.beta); -beta.sem=beta.std/sqrt(n); -gamma.mean=mean(pmf.gamma); -lambda.mean=mean(pmf.lambda); - - -%%%%%%SCATTERPLOT 2x2 -betaSD=10.^-(pmf.beta); - -fig=figure('Position',[3 50 700 500]); -subplot(2,2,1)%CS+ alpha -plot(pmf.alpha(:,1,1),pmf.alpha(:,1,2),'go','MarkerFaceColor','g'); -ylabel(sprintf('after')) -axis square -xlim([0 170]) -ylim([0 170]) -DrawIdentityLine(gca); -title('CS+ alpha') -box off -hold on; -plot(mean(pmf.alpha(:,1,1)),mean(pmf.alpha(:,1,2)),'k+','MarkerSize',10) - -subplot(2,2,2)%CS+ beta -plot(betaSD(:,1,1),betaSD(:,1,2),'go','MarkerFaceColor','g'); -title('CS+ beta') -axis square -xlim([0 100]) -ylim([0 100]) -DrawIdentityLine(gca); -box off -hold on; -plot(mean(betaSD(:,1,1)),mean(betaSD(:,1,2)),'k+','MarkerSize',10) - -subplot(2,2,3)%CS- alpha -plot(pmf.alpha(:,2,1),pmf.alpha(:,2,2),'ko','MarkerFaceColor','y'); -xlim([0 170]) -ylim([0 170]) -xlabel('before') -ylabel(sprintf('after')) -axis square -DrawIdentityLine(gca); -title('CS- alpha') -box off -hold on; -plot(mean(pmf.alpha(:,2,1)),mean(pmf.alpha(:,2,2)),'k+','MarkerSize',10) - -subplot(2,2,4)%CS- beta -plot(betaSD(:,2,1),betaSD(:,2,2),'ko','MarkerFaceColor','y'); -xlabel(sprintf('before')) -axis square -xlim([0 100]) -ylim([0 100]) -DrawIdentityLine(gca); -title('CS- beta') -box off -hold on; -plot(mean(betaSD(:,2,1)),mean(betaSD(:,2,2)),'k+','MarkerSize',10) - -t=supertitle(['mean threshold \alpha and slope \beta, 600ms version, ' sprintf('N=%d',n)]); -set(t,'FontSize',14) - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%barplot for means -%compute the mean -alpha.mean=mean(pmf.alpha); -alpha.std=std(pmf.alpha); -alpha.sem=alpha.std/sqrt(length(subjects)); -beta.mean=mean(pmf.beta); -beta.std=std(pmf.beta); -beta.sem=beta.std/sqrt(length(subjects)); -gamma.mean=mean(pmf.gamma); -lambda.mean=mean(pmf.lambda); -lower=10.^-(beta.mean+beta.sem); -upper=10.^-(beta.mean-beta.sem); -ubar=upper-(10.^-beta.mean); -lbar=10.^-beta.mean-lower; -beta.errorbars=NaN(2,2,2); -beta.errorbars(:,:,1)=squeeze(lbar); -beta.errorbars(:,:,2)=squeeze(ubar); - -fig=figure('Position',[3 50 700 500]); -subplot(1,2,1) -[h,e] = barwitherr(squeeze(alpha.sem),squeeze(alpha.mean)); -set(gca,'XTickLabel',{'CS+','CS-'}) -set(e,'LineWidth',1.5) -set(h(1), 'FaceColor','r') -set(h(2), 'FaceColor',[143/255 0 0]) -ylabel('threshold \alpha (degrees)') -axis square -legend('before','after','orientation','horizontal','location','southoutside') - -subplot(1,2,2) -[h,e] = barwitherr(beta.errorbars,squeeze(10.^-mean(pmf.beta))); -set(gca,'XTickLabel',{'CS+','CS-'}) -set(h(1), 'FaceColor','b') -set(h(2), 'FaceColor',[0 0.05 0.2]) -set(e,'LineWidth',1.5) -legend('before','after','orientation','horizontal','location','southoutside') -ylabel('slope \beta (SD)') -ylim([0 80]) -axis square - -t=supertitle(['mean threshold \alpha and slope \beta, 600ms version, ' sprintf('N=%d',n)]); -set(t,'FontSize',14) - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -[p_csp_alpha,h,stats]=signtest(pmf.alpha(:,1,1),pmf.alpha(:,1,2)) -[p_csn_alpha,h,stats]=signtest(pmf.alpha(:,2,1),pmf.alpha(:,2,2)) -[p_csp_beta,h,stats]=signtest(pmf.beta(:,1,1),pmf.beta(:,1,2)) -[p_csn_beta,h,stats]=signtest(pmf.beta(:,2,1),pmf.beta(:,2,2)) - -[p_csp_alpha,h]=signrank(pmf.alpha(:,1,1),pmf.alpha(:,1,2)) -[p_csn_alpha,h]=signrank(pmf.alpha(:,2,1),pmf.alpha(:,2,2)) -[p_csp_beta,h]=signrank(pmf.beta(:,1,1),pmf.beta(:,1,2)) -[p_csn_beta,h]=signrank(pmf.beta(:,2,1),pmf.beta(:,2,2)) - -[h,p_csp_alpha]=ttest(pmf.alpha(:,1,1),pmf.alpha(:,1,2)) -[h,p_csn_alpha]=ttest(pmf.alpha(:,2,1),pmf.alpha(:,2,2)) -[h,p_csp_beta]=ttest(pmf.beta(:,1,1),pmf.beta(:,1,2)) -[h,p_csp_beta]=ttest(pmf.beta(:,2,1),pmf.beta(:,2,2)) - -alph=[pmf.alpha(:,1,1),pmf.alpha(:,2,1);pmf.alpha(:,1,2),pmf.alpha(:,2,2)]; -beta=[pmf.beta(:,1,1),pmf.beta(:,2,1);pmf.beta(:,1,2),pmf.beta(:,2,2)]; -[p_a,table,stats]=anova2(alph,n); -[p_b,table,stats]=anova2(beta,n); - diff --git a/fearcloud_analyze_pmfs.m b/fearcloud_analyze_pmfs.m deleted file mode 100644 index 20ec3d7..0000000 --- a/fearcloud_analyze_pmfs.m +++ /dev/null @@ -1,81 +0,0 @@ -global project_path -project_path='C:\Users\onat\Google Drive\EthnoMaster\data\' - -subjects=[6:26,28:36];%PMF -%subjects to exclude bc of bad fitting: -%subexcl=6,8,9,18,21,22,23,28,29 -subjects=[7,10,11:17,19:20,24:26,30,31,34:35]; -subjects_eye=[6:26,28:36]; -%subjects slower vs faster version -subjects_1500=[6:26,28:36]; -subjects_600=[27,39,41:51]; -%37 and 38 have smaller stimranges... - -pmf=isn_getPMF(subjects,[1 5]); -% % %alternatively load them (this is the file with all subjects for Lea's Masterthesis): -% % pmf=load('C:\Users\onat\Google Drive\EthnoMaster\pmfmaster.mat'); -% % pmf=pmf.pmf; - -n=length(subjects); - -betaSD=10.^-pmf.beta; -%compute the means and stds -alpha.mean=mean(pmf.alpha); -alpha.std=std(pmf.alpha); -alpha.sem=alpha.std/sqrt(n); -beta.mean=mean(pmf.beta); -beta.std=std(pmf.beta); -beta.sem=beta.std/sqrt(n); -gamma.mean=mean(pmf.gamma); -lambda.mean=mean(pmf.lambda); - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% statistical tests -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -[p_csp_alpha,h,stats]=signtest(pmf.alpha(:,1,1),pmf.alpha(:,1,2)) -[p_csn_alpha,h,stats]=signtest(pmf.alpha(:,2,1),pmf.alpha(:,2,2)) -[p_csp_beta,h,stats]=signtest(pmf.beta(:,1,1),pmf.beta(:,1,2)) -[p_csn_beta,h,stats]=signtest(pmf.beta(:,2,1),pmf.beta(:,2,2)) - -[p_csp_alpha,h]=signrank(pmf.alpha(:,1,1),pmf.alpha(:,1,2)) -[p_csn_alpha,h]=signrank(pmf.alpha(:,2,1),pmf.alpha(:,2,2)) -[p_csp_beta,h]=signrank(pmf.beta(:,1,1),pmf.beta(:,1,2)) -[p_csn_beta,h]=signrank(pmf.beta(:,2,1),pmf.beta(:,2,2)) - -[h,p_csp_alpha]=ttest(pmf.alpha(:,1,1),pmf.alpha(:,1,2)) -[h,p_csn_alpha]=ttest(pmf.alpha(:,2,1),pmf.alpha(:,2,2)) -[h,p_csp_beta]=ttest(pmf.beta(:,1,1),pmf.beta(:,1,2)) -[h,p_csp_beta]=ttest(pmf.beta(:,2,1),pmf.beta(:,2,2)) - -alph=[pmf.alpha(:,1,1),pmf.alpha(:,2,1);pmf.alpha(:,1,2),pmf.alpha(:,2,2)]; -beta=[pmf.beta(:,1,1),pmf.beta(:,2,1);pmf.beta(:,1,2),pmf.beta(:,2,2)] -[p_a,table,stats]=anova2(alph,n); -[p_b,table,stats]=anova2(beta,n); - - -%%%%%%%%%%%%%%%GAUSS%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -[o]=fearcloud_fitgauss(subjects,[3 4]) -sigma_cond=o.sigma(:,1); -sigma_test=o.sigma(:,2); -alpha_before=mean(pmf.alpha(:,:,1),2); -beta_before=10.^-mean(pmf.beta(:,:,1),2); -diff_a_csp = pmf.alpha(:,1,1)-pmf.alpha(:,1,2); -diff_b_csp=pmf.beta(:,1,1)-pmf.beta(:,1,2); -SI=sigma_cond-sigma_test; - - -[rho, pval] = corr([alpha_before,beta_before,diff_a_csp,diff_b_csp,sigma_cond,sigma_test,SI], 'rows','pairwise') - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%correlation between performance before, and diff -%%%%%%%%%%%%%%%%%%%%%%%%%%% -diff_b=10.^-pmf.beta(:,1,1)-10.^-pmf.beta(:,1,2); -%csminus -diff_bm=10.^-pmf.beta(:,2,1)-10.^-pmf.beta(:,2,2); -[r,p]=corr([diff_b,10.^-pmf.beta(:,1,1)],'rows','pairwise') -[r,p]=corr([diff_bm,10.^-pmf.beta(:,2,1)],'rows','pairwise') - - diff --git a/fearcloud_fitgauss.m b/fearcloud_fitgauss.m deleted file mode 100644 index 4bc6691..0000000 --- a/fearcloud_fitgauss.m +++ /dev/null @@ -1,21 +0,0 @@ -function [o,out]=fearcloud_fitgauss(subjects,runs) -% gets aligned mean ratings per subject via the isn_GetRatings function, -% then fits gaussian to this data -o=[]; -cs=0; -for sub=subjects - cs=cs+1; - cr=0; - for run=runs - cr=cr+1; - r=isn_GetRatings(sub,run,1); - out = FitGauss(deg2rad(-135:45:180),r,3); - o.a(cs,cr)=out.Est(1); - o.sigma(cs,cr)=rad2deg(out.Est(2)); - o.p(cs,cr)=out.pval; - o.likelihood(cs,cr)=out.Likelihood; - end -end - -end - diff --git a/fearcloud_plot_PMFresults.m b/fearcloud_plot_PMFresults.m deleted file mode 100644 index 5af5cf2..0000000 --- a/fearcloud_plot_PMFresults.m +++ /dev/null @@ -1,669 +0,0 @@ - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%What is a PMF? -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -fig=figure('position',[3 100 1000 400]); -subplot(1,3,1) -x=0:1:150; -plot(x,... - PAL_CumulativeNormal([45 1/15 0.1 0.05],x),'r','linewidth',2) -hold on; -ylim([0 1]) -xlim([0 100]) -set(gca,'XTick',0:15:100) -ylabel('p("different")') -xlabel('stimulus intensity x (degrees)') -plot(45,PAL_CumulativeNormal([45 1/15 0.1 0.05],45),'bsquare','MarkerFaceColor','b') -line([45 45],[0 PAL_CumulativeNormal([45 1/15 0.1 0.05],45)],'linestyle',':','linewidth',2) -line([0 45],[PAL_CumulativeNormal([45 1/15 0.1 0.05],45) PAL_CumulativeNormal([45 1/15 0.1 0.05],45)],'linestyle',':','linewidth',2) -axis square - -subplot(1,3,2) -plot(x,... - PAL_CumulativeNormal([45 1/15 0.1 0.05],x),'r','linewidth',2) -hold on; -plot(45,PAL_CumulativeNormal([45 1/15 0.1 0.05],45),'bsquare','MarkerFaceColor','b') -ylim([0 1]) -xlim([0 100]) -set(gca,'XTick',0:15:100) -ylabel('p("different")') -plot(x,... - PAL_CumulativeNormal([30 1/15 0.1 0.05],x),'r--','linewidth',2) -plot(x,... - PAL_CumulativeNormal([60 1/15 0.1 0.05],x),'r--','linewidth',2) -axis square - -subplot(1,3,3) -p(1)=plot(x,... - PAL_CumulativeNormal([45 1/15 0.1 0.05],x),'r','linewidth',2) - -hold on; -ylim([0 1]) -xlim([0 100]) -xlabel('x (deg)') -set(gca,'XTick',0:15:100) -p(2)=plot(x,... - PAL_CumulativeNormal([45 1/7.5 0.1 0.05],x),'r--','linewidth',2) -plot(x,... - PAL_CumulativeNormal([45 1/22.5 0.1 0.05],x),'r--','linewidth',2) -plot(45,PAL_CumulativeNormal([45 1/15 0.1 0.05],45),'bsquare','MarkerFaceColor','b') -axis square - -legend(p,'before','after','location','eastoutside') - -s=supertitle('Varying parameters in psychometric functions'); -set(s,'FontSize',14) - - - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%1---COMPARE METHODS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -psi1=load('C:\Users\onat\Dropbox\feargen_lea\EthnoMaster\simdata\diffSDs\d_PSI_3SDs_end.mat'); -psi2=load('C:\Users\onat\Dropbox\feargen_lea\EthnoMaster\simdata\diffSDs\d_PSImarg2AFC_3SDs_end.mat'); -psi3=load('C:\Users\onat\Dropbox\feargen_lea\EthnoMaster\simdata\diffSDs\d_PSImargYN_3SDs_end.mat'); - -% how many trial levels do you want to display? -t=7; - -mean1=squeeze(nanmean(psi1.d.alpha(:,1,1:3,1:t)));%average estimation -mean2=squeeze(nanmean(psi2.d.alpha(:,1,1:3,1:t))); -mean3=squeeze(nanmean(psi3.d.alpha(:,1,1:3,1:t))); -E1=squeeze(nanstd(psi1.d.alpha(:,1,1:3,1:t))); -E2=squeeze(nanstd(psi2.d.alpha(:,1,1:3,1:t))); -E3=squeeze(nanstd(psi3.d.alpha(:,1,1:3,1:t))); - -mean11=squeeze(nanmean(psi1.d.sd(:,1,1:3,1:t)));%average estimation -mean22=squeeze(nanmean(psi2.d.sd(:,1,1:3,1:t))); -mean33=squeeze(nanmean(psi3.d.sd(:,1,1:3,1:t))); -E11=squeeze(nanstd(psi1.d.sd(:,1,1:3,1:t))); -E22=squeeze(nanstd(psi2.d.sd(:,1,1:3,1:t))); -E33=squeeze(nanstd(psi3.d.sd(:,1,1:3,1:t))); - - -fig=figure('position',[3 300 750 400]) -subplot(1,2,1)%alpha for 20, 100, 500 trials -ti=[1 4 7]; -t=[100 200 300]; -xlimits=[50 max(t)+50]; -ylimits=[0 100]; -line(xlimits, [45 45],'color','yellow','linewidth',2,'linestyle','-') -hold on; -errorbar(t-10,mean1(2,ti),E1(2,ti),'.','Color','blue','linewidth',2,'MarkerSize',20) -errorbar(t,mean2(2,ti),E2(2,ti),'.','Color','red','linewidth',2,'MarkerSize',20) -errorbar(t+10,mean3(2,ti),E3(2,ti),'k.','linewidth',2,'MarkerSize',20) -set(gca,'XTick',[100 200 300],'XTickLabel',{'20','100','500'}) -xlim(xlimits) -ylim(ylimits) -axis square -xlabel('nTrials') -ylabel('mean estimated alpha (degrees) (\pm std)') - - -subplot(1,2,2)%alpha for 20, 100, 500 trials -ti=[1 4 7]; -t=[100 200 300]; -line(xlimits, [30 30],'color','yellow','linewidth',2,'linestyle','-') -hold on; -errorbar(t-10,mean11(2,ti),E11(2,ti),'b.','linewidth',2,'MarkerSize',20) -errorbar(t,mean22(2,ti),E22(2,ti),'r.','linewidth',2,'MarkerSize',20) -errorbar(t+10,mean33(2,ti),E33(2,ti),'k.','linewidth',2,'MarkerSize',20) -set(gca,'XTick',[100 200 300],'XTickLabel',{'20','100','500'}) -xlim(xlimits) -ylim(ylimits) -axis square - -xlabel('nTrials') -ylabel('mean estimated beta (SD) (\pm std)') - -legend('generating value','PSI','PSImarg2AFC','PSImargYN','orientation','horizontal', 'location','northoutside') - -s=supertitle('Estimation of alpha and beta by different PSI-methods'); -set(s,'FontSize',14) - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%2 --- SEARCH TRIAL NUMBER WE WANT -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -load('C:\Users\onat\Dropbox\feargen_lea\EthnoMaster\simdata\diffSDs\trial_question\PSImargYN_a45_153045_20to120_merged.mat') - -fig=figure('position',[3 300 750 400]) -truealpha=45; -xlimits=[0 140]; -ylimits=[12.5 77.5]; -subplot(1,2,1) -%line([min(d.param.ttrials(:))-10 max(d.param.ttrials(:))+10], [truealpha truealpha],'color','yellow','linewidth',2); -line([0 140], [truealpha truealpha],'color','yellow','linewidth',2); -hold on; -errorbar(unique(d.param.ttrials(~isnan(d.param.ttrials)))-3,mean(d.alpha(:,1,1,1:6)),std(d.alpha(:,1,1,1:6)),'.','Color',[0 0 0.1],'linewidth',2,'MarkerSize',20); -errorbar(unique(d.param.ttrials(~isnan(d.param.ttrials))),mean(d.alpha(:,1,2,1:6)),std(d.alpha(:,1,2,1:6)),'.','Color',[0.08 0.17 0.55],'linewidth',2,'MarkerSize',20); -errorbar(unique(d.param.ttrials(~isnan(d.param.ttrials)))+3,mean(d.alpha(:,1,3,1:6)),std(d.alpha(:,1,3,1:6)),'.','Color',[0.05 0.5 0.8],'linewidth',2,'MarkerSize',20); -ylim(ylimits) -xlim(xlimits) -set(gca,'XTick',[20 40 60 80 100 120]) -axis square -xlabel('nTrials') -ylabel('mean estimated alpha (degrees) (\pm std)') -legend('generating value','SD=15','SD=30','SD=45','Location','southoutside','orientation','horizontal') - - -%[0.8 0.8 0] [0.9 0.9 0.2],[1 1 0.4] -subplot(1,2,2) -truebeta=[15 30 45]; -ylimits=[0 65]; -ylim(ylimits) -xlim(xlimits); -set(gca,'XTick',[20 40 60 80 100 120]) -xlabel('nTrials') -ylabel('mean estimated beta (in SD) (\pm std)') -axis square -line(xlimits, [truebeta(1) truebeta(1)],'color','yellow','linewidth',2);hold on; -errorbar(unique(d.param.ttrials(~isnan(d.param.ttrials)))-5,mean(d.sd(:,1,1,1:6)),std(d.sd(:,1,1,1:6)),'.--','Color',[0 0 0.05],'linewidth',2,'MarkerSize',20); -line(xlimits, [truebeta(2) truebeta(2)],'color','yellow','linewidth',2);hold on; -errorbar(unique(d.param.ttrials(~isnan(d.param.ttrials))),mean(d.sd(:,1,2,1:6)),std(d.sd(:,1,2,1:6)),'.--','Color',[0.08 0.17 0.55],'linewidth',2,'MarkerSize',20); -line(xlimits, [truebeta(3) truebeta(3)],'color','yellow','linewidth',2);hold on; -errorbar(unique(d.param.ttrials(~isnan(d.param.ttrials)))+5,mean(d.sd(:,1,3,1:6)),std(d.sd(:,1,3,1:6)),'.--','Color',[0.05 0.5 0.8],'linewidth',2,'MarkerSize',20); - -h=supertitle('Estimating alpha and beta by PSImargYN'); -set(h,'FontSize',14) -%n_{sim}=1000 -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%3--- ADD FORCED ZEROS OR NOT? -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -d=load('C:\Users\onat\Dropbox\feargen_lea\EthnoMaster\simdata\diffSDs\trial_question\PSImargYN_a45_153045_20to120_merged.mat'); -d=d.d; -a100trials_nozeros=mean(d.alpha(:,1,:,5),1); -a100trials_nozeros_std=std(d.alpha(:,1,:,5),1); -b100trials_nozeros=mean(d.sd(:,1,:,5),1); -b100trials_nozeros_std=std(d.sd(:,1,:,5),1); - -d0=load('C:\Users\onat\Dropbox\feargen_lea\EthnoMaster\simdata\diffSDs\zeros_nozeros\d_PSImargYN0_45_153045_100tr_pluszeros_20150430_2115.mat'); -d0=d0.d; -a100trials_zero_std=std(d0.alpha,1); -a100trials_zero=mean(d0.alpha,1); -b100trials_zero=mean(d0.sd,1); -b100trials_zero_std=std(d0.sd,1); - -fig=figure('position',[3 300 750 400]); - -subplot(1,2,1) -truealpha=45 -line([80 120], [truealpha truealpha],'color','yellow','linewidth',2,'linestyle',':') -hold on; -errorbar([90 100 110],a100trials_nozeros,a100trials_nozeros_std,'k.','linewidth',2,'MarkerSize',20); - -errorbar([91 101 111],a100trials_zero,a100trials_zero_std,'b.','linewidth',2,'MarkerSize',20) -xlim([80 120]) -ylim([0 60]) -set(gca,'XTick',[90.5 100.5 110.5],'XTickLabel',{'15' '30' '45'}) -xlabel('generating noise (SD)') -ylabel('mean estimated threshold in degrees (\pm std)') -title('Estimation of alpha by PSImargYN') -legend('generating value','no zeros','zeros added','orientation','horizontal','Location','best') -axis square - -subplot(1,2,2) -truebeta=[15,30,45]; -for i=1:3 -line([80 120], [truebeta(i) truebeta(i)],'color','yellow','linewidth',2,'linestyle',':') -hold on; -end -errorbar([90 100 110],b100trials_nozeros,b100trials_nozeros_std,'k.','linewidth',2,'MarkerSize',20); - -errorbar([91 101 111],b100trials_zero,b100trials_zero_std,'b.','linewidth',2,'MarkerSize',20) -xlim([80 120]) -ylim([0 60]) -set(gca,'XTick',[90.5 100.5 110.5],'XTickLabel',{'15' '30' '45'}) -xlabel('generating noise (SD)') -ylabel('mean estimated slope (SD) (\pm std)') -axis square -title('Estimation of beta by PSImargYN') - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%RESULTS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - -%%%%%%SCATTERPLOT 2x2 -subjects=[7,10,11:17,19:20,24:26,30,31,34:35]; -pmf=isn_getPMF(subjects,[1 5]); - -betaSD=10.^-(pmf.beta); - -fig=figure('Position',[3 50 700 500]); -subplot(2,2,1)%CS+ alpha -plot(pmf.alpha(:,1,1),pmf.alpha(:,1,2),'ro','MarkerFaceColor','r'); -ylabel(sprintf('after')) -axis square -xlim([0 100]) -ylim([0 100]) -DrawIdentityLine(gca); -title('CS+ alpha') -box off -hold on; -plot(mean(pmf.alpha(:,1,1)),mean(pmf.alpha(:,1,2)),'k+','MarkerSize',10) - -subplot(2,2,2)%CS+ beta -plot(betaSD(:,1,1),betaSD(:,1,2),'ro','MarkerFaceColor','r'); -title('CS+ beta') -axis square -xlim([0 100]) -ylim([0 100]) -DrawIdentityLine(gca); -box off -hold on; -plot(mean(betaSD(:,1,1)),mean(betaSD(:,1,2)),'k+','MarkerSize',10) - -subplot(2,2,3)%CS- alpha -plot(pmf.alpha(:,2,1),pmf.alpha(:,2,2),'bo','MarkerFaceColor','b'); -xlim([0 100]) -ylim([0 100]) -xlabel('before') -ylabel(sprintf('after')) -axis square -DrawIdentityLine(gca); -title('CS- alpha') -box off -hold on; -plot(mean(pmf.alpha(:,2,1)),mean(pmf.alpha(:,2,2)),'k+','MarkerSize',10) - -subplot(2,2,4)%CS- beta -plot(betaSD(:,2,1),betaSD(:,2,2),'bo','MarkerFaceColor','b'); -xlabel(sprintf('before')) -axis square -xlim([0 100]) -ylim([0 100]) -DrawIdentityLine(gca); -title('CS- beta') -box off -hold on; -plot(mean(betaSD(:,2,1)),mean(betaSD(:,2,2)),'k+','MarkerSize',10) - -t=supertitle('threshold \alpha before and after aversive learning'); -set(t,'FontSize',14) - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%barplot for means -%compute the mean -alpha.mean=mean(pmf.alpha); -alpha.std=std(pmf.alpha); -alpha.sem=alpha.std/sqrt(length(subjects)); -beta.mean=mean(pmf.beta); -beta.std=std(pmf.beta); -beta.sem=beta.std/sqrt(length(subjects)); -gamma.mean=mean(pmf.gamma); -lambda.mean=mean(pmf.lambda); -lower=10.^-(beta.mean+beta.sem); -upper=10.^-(beta.mean-beta.sem); -ubar=upper-(10.^-beta.mean); -lbar=10.^-beta.mean-lower; -beta.errorbars=NaN(2,2,2); -beta.errorbars(:,:,1)=squeeze(lbar); -beta.errorbars(:,:,2)=squeeze(ubar); - -fig=figure('Position',[3 50 700 500]); -subplot(2,2,1) -[h,e] = barwitherr(squeeze(alpha.sem),squeeze(alpha.mean)); -set(gca,'XTickLabel',{'CS+','CS-'}) -set(e,'LineWidth',1.5) -set(h(1), 'FaceColor','r') -set(h(2), 'FaceColor',[143/255 0 0]) -ylabel('threshold \alpha (degrees)') -axis square -legend('before','after','orientation','horizontal','location','southoutside') - -subplot(2,2,2) -[h,e] = barwitherr(beta.errorbars,squeeze(10.^-mean(pmf.beta))); -set(gca,'XTickLabel',{'CS+','CS-'}) -set(h(1), 'FaceColor','b') -set(h(2), 'FaceColor',[0 0.05 0.2]) -set(e,'LineWidth',1.5) -legend('before','after','orientation','horizontal','location','southoutside') -ylabel('slope \beta (SD)') -ylim([0 80]) -axis square - -% % %this adds * to mark significant differences, if they are there -% % annotation(gcf,'textbox',... -% % [0.193802056555268 0.806539509536784 0.0414164524421595 0.0790190735694823],... -% % 'String',{'*'},... -% % 'FontSize',24,... -% % 'FontName','Arial',... -% % 'FitBoxToText','off',... -% % 'EdgeColor',[1 1 1]); -% % annotation(gcf,'textbox',... -% % [0.638532133676092 0.637602179836512 0.0298483290488432 0.0817438692098088],... -% % 'String',{'*'},... -% % 'FontSize',24,... -% % 'FontName','Arial',... -% % 'FitBoxToText','off',... -% % 'EdgeColor',[1 1 1]); - - -%%%%%%%%%%PMFS%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -subplot(2,2,3) -x=0:1:150; -%CS+ left, CS- right figure - pre vs post in one figure. -plot(x,... - PAL_CumulativeNormal([alpha.mean(:,1,1) 10.^beta.mean(:,1,1) gamma.mean(:,1,1) lambda.mean(:,1,1)],x),'r-','linewidth',2) -hold on; -plot(x,... - PAL_CumulativeNormal([alpha.mean(:,1,2) 10.^beta.mean(:,1,2) gamma.mean(:,1,2) lambda.mean(:,1,2)],x),'r--','linewidth',2) -legend('before','after','location','southeast') -title('CS+') -xlabel('X (deg)') -ylabel('p("different")') -axis square -%%%%% -subplot(2,2,4) -plot(x,... - PAL_CumulativeNormal([alpha.mean(:,2,1) 10.^beta.mean(:,2,1) gamma.mean(:,2,1) lambda.mean(:,2,1)],x),'b-','linewidth',2) -hold on; -plot(x,... - PAL_CumulativeNormal([alpha.mean(:,2,2) 10.^beta.mean(:,2,2) gamma.mean(:,2,2) lambda.mean(:,2,2)],x),'b--','linewidth',2) -legend('before','after','location','southeast') -title('CS-') -xlabel('X (deg)') -ylabel('p("different")') -axis square - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% 600ms version -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%FITGAUSS -subject=6; -r=isn_GetRatings(subject,[3 4],1); -for i=1:2 -subplot(1,2,i) -h=bar(r(:,:,i)); -hold on; -SetFearGenBarColors(h) -set(gca,'XTickLabel',{'','','','CSP','','','','CSN'}) -[o]=fearcloud_fitgauss(subject,2+i); -h=gcf; -close(h) -plot(out.xsup+4,out.fitup,'k','linewidth',3); -ylabel('subjective rating p(shock)') -end - - - - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% V1 -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -figure -r=30; -[X_koord] = cos([0:11.25:355]*pi/180)*r -[Y_koord] = -sin([0:11.25:355]*pi/180)*r -[circle] = [X_koord;Y_koord]'; -plot(X_koord,Y_koord,'o','color',[0.4 0.4 0.4],'MarkerSize',8,'MarkerFaceColor','w','LineWidth',2) -xlim([-50 50]) -ylim([-50 50]) -% axis equal -axis square -axis off -box off -hold on; -[X_koord_2] = cos([0:45:355]*pi/180)*r; -[Y_koord_2] = -sin([0:45:355]*pi/180)*r; -[circle_2] = [X_koord_2;Y_koord_2]'; -plot(X_koord_2,Y_koord_2,'s','color',[0.4 0.4 0.4],'MarkerSize',20,'MarkerFaceColor','w','LineWidth',2) - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% MATRIX calibration business -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -face_space=textread('C:\Users\onat\Desktop\FaceSimilarityQuantification\SAVEDDROPBOX\5circles_RGB\circle_calculation_txt.txt'); -load('C:\Users\onat\Desktop\FaceSimilarityQuantification\SAVEDDROPBOX\5circles_RGB\smoothed_005_1.4\Normalized\smoothededges_004\V1responses\NewFaceSpaceCoord_r60.mat');%facespace_new - -ed_v1=load('C:\Users\onat\Desktop\FaceSimilarityQuantification\SAVEDDROPBOX\5circles_RGB\smoothed_005_1.4\Normalized\smoothededges_004\V1responses\EuclidianDistances.mat');ed_v1=ed_v1.ed; -r=60; -circle_coord = [cos([0:11.25:359]*pi/180)*r'; sin([0:11.25:359]*pi/180)*r']'; - -figure('position',[500 100 600 600]) -plot(face_space(:,1),face_space(:,2),'b.-') -hold on; -plot(facespace_new(:,1),facespace_new(:,2),'ro','MarkerFaceColor','r','MarkerSize',10) -axis equal -axis square - -figure('position',[500 100 600 600]) -plot(v1_space_2d(:,1),v1_space_2d(:,2),'b.-') -hold on; -plot(circle_coord(:,1),circle_coord(:,2),'ro','MarkerFaceColor','r','MarkerSize',10) -axis equal - - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%SUBJECTS PMF IN DISCUSSION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -global project_path;project_path='C:\Users\onat\Google Drive\EthnoMaster\data\' -Log = isn_GetData(12,5,'stimulation'); -p = Log.p; -psi = Log.p.psi; -x = 0:1:100; -xstimrange= psi.stimRange; -% collect number of trials per stimulus Level - -minn=5; -maxn=25; -% -fig=figure('units','normalized','outerposition',[0 0 0.45 0.6]); -suptitle('Fitting Subject 12, after conditioning, CS+'); - -chain=1; - %dotsize gets scaled by number of trials at this x - dotsize = Scale(sum(~isnan(p.psi.log.xrounded(:,:,chain)),2))*(maxn-minn)+minn; - pcorrect = nanmean(p.psi.log.xrounded(:,:,chain),2); - error = nanstd(p.psi.log.xrounded(:,:,chain),0,2); - - subplot(2,2,1) - plot(x,... - PAL_CumulativeNormal([p.psi.log.alpha(chain,end) 10.^(p.psi.log.beta(chain,end)) p.psi.log.gamma(chain,end) p.psi.log.lambda(chain,end)],x),'k','linewidth',3) - hold on; - - %detect the nonnan entries - % for i = find(~isnan(pcorrect(:))') - % errorbar(xstimrange(i),pcorrect(i),error(i),'ko','Markersize',dotsize(i)); - % hold on; - % end - for i = find(~isnan(pcorrect(:))') - errorbar(xstimrange(i),pcorrect(i),error(i),'o','Markersize',10,'markerfacecolor',[0.3 0.3 0.3],'color',[0.3 0.3 0.3]); - hold on; - end - ylabel('p(different)') - xlabel('X (deg)') - xlim([-10 100]) - ylim([-.4 1.4]) - if chain==1 - title('CS+') - else - title('CS-') - end - hold off - box off; - line([p.psi.log.alpha(chain,end) p.psi.log.alpha(chain,end)],[ylim],'Color','r') - - - subplot(2,2,3) - for i = find(~isnan(pcorrect(:))') - plot(xstimrange(i),1.2,'o','color',[0.3 0.3 0.3],'Markersize',dotsize(i),'MarkerFaceColor',[0.3 0.3 0.3]); - hold on; - end - xlim([-10 100]); - title('Number of Presentations') - box off; - grid on; - set(gca,'yticklabel',[],'ytick',[],'ycolor',[1 1 1],'xtick',xstimrange,'xtick',xstimrange(1:2:end)); - xlabel('X (deg)') - text(xstimrange(1),1.9,'20%') - - subplot(2,2,2) - plot(1:length(p.psi.log.alpha(chain,:)),p.psi.log.alpha(chain,:),'r-') - hold on; - errorbar([1 length(p.psi.log.alpha(chain,:))],p.psi.log.alpha(chain,[1 end]),p.psi.log.seAlpha(chain,[1 end]),'ro') - title(sprintf('estimated alpha=%3.3g (%3.3g)',p.psi.log.alpha(chain,end),p.psi.log.seAlpha(chain,end))) - xlim([-5 length(p.psi.log.beta(chain,:))+5]) - box off; - xlabel('# trials') - ylabel('alpha (degrees)'); - - subplot(2,2,4) -% plot(1:length(p.psi.log.beta(chain,:)),(10.^-p.psi.log.beta(chain,:)),'b-') -% hold on; -% errorbar([1 length(p.psi.log.beta(chain,:))],(10.^-p.psi.log.beta(chain,[1 end])),(10.^-p.psi.log.seBeta(chain,[1 end])),'bo') - plot(1:length(p.psi.log.beta(chain,:)),(p.psi.log.beta(chain,:)),'b-') - hold on; - errorbar([1 length(p.psi.log.beta(chain,:))],(p.psi.log.beta(chain,[1 end])),(p.psi.log.seBeta(chain,[1 end])),'bo') - %title(sprintf('estimated beta in SD = %3.3g (%3.3g)',(10.^-p.psi.log.beta(chain,end)),(10.^-p.psi.log.seBeta(chain,end)))) - title(sprintf('estimated beta = %3.3g (%3.3g)',(p.psi.log.beta(chain,end)),(p.psi.log.seBeta(chain,end)))) - xlim([-5 length(p.psi.log.beta(chain,:))+5]) - box off; - xlabel('# trials') - ylabel('beta'); - -%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%SUBJECTS PMF IN DISCUSSION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -global project_path;project_path='C:\Users\onat\Google Drive\EthnoMaster\data\' -Log = isn_GetData(9,5,'stimulation'); -p = Log.p; -psi = Log.p.psi; -x = 0:1:100; -xstimrange= psi.stimRange; -% collect number of trials per stimulus Level - -minn=5; -maxn=25; -% -fig=figure('units','normalized','outerposition',[0 0 0.45 0.6]); -suptitle('Fitting Subject 12, after conditioning, CS+'); - -chain=2; - %dotsize gets scaled by number of trials at this x - dotsize = Scale(sum(~isnan(p.psi.log.xrounded(:,:,chain)),2))*(maxn-minn)+minn; - pcorrect = nanmean(p.psi.log.xrounded(:,:,chain),2); - error = nanstd(p.psi.log.xrounded(:,:,chain),0,2); - - subplot(2,2,1) - plot(x,... - PAL_CumulativeNormal([p.psi.log.alpha(chain,end) 10.^(p.psi.log.beta(chain,end)) p.psi.log.gamma(chain,end) p.psi.log.lambda(chain,end)],x),'k','linewidth',3) - hold on; - - %detect the nonnan entries - % for i = find(~isnan(pcorrect(:))') - % errorbar(xstimrange(i),pcorrect(i),error(i),'ko','Markersize',dotsize(i)); - % hold on; - % end - for i = find(~isnan(pcorrect(:))') - errorbar(xstimrange(i),pcorrect(i),error(i),'o','Markersize',10,'markerfacecolor',[0.3 0.3 0.3],'color',[0.3 0.3 0.3]); - hold on; - end - ylabel('p(different)') - xlabel('X (deg)') - xlim([-10 100]) - ylim([-.4 1.4]) - if chain==1 - title('CS+') - else - title('CS-') - end - hold off - box off; - line([p.psi.log.alpha(chain,end) p.psi.log.alpha(chain,end)],[ylim],'Color','r') - - - subplot(2,2,3) - for i = find(~isnan(pcorrect(:))') - plot(xstimrange(i),1.2,'o','color',[0.3 0.3 0.3],'Markersize',dotsize(i),'MarkerFaceColor',[0.3 0.3 0.3]); - hold on; - end - xlim([-10 100]); - title('Number of Presentations') - box off; - grid on; - set(gca,'yticklabel',[],'ytick',[],'ycolor',[1 1 1],'xtick',xstimrange,'xtick',xstimrange(1:2:end)); - xlabel('X (deg)') - text(xstimrange(1),1.9,'20%') - - subplot(2,2,2) - plot(1:length(p.psi.log.alpha(chain,:)),p.psi.log.alpha(chain,:),'r-') - hold on; - errorbar([1 length(p.psi.log.alpha(chain,:))],p.psi.log.alpha(chain,[1 end]),p.psi.log.seAlpha(chain,[1 end]),'ro') - title(sprintf('estimated alpha=%3.3g (%3.3g)',p.psi.log.alpha(chain,end),p.psi.log.seAlpha(chain,end))) - xlim([-5 length(p.psi.log.beta(chain,:))+5]) - box off; - xlabel('# trials') - ylabel('alpha (degrees)'); - - subplot(2,2,4) -% plot(1:length(p.psi.log.beta(chain,:)),(10.^-p.psi.log.beta(chain,:)),'b-') -% hold on; -% errorbar([1 length(p.psi.log.beta(chain,:))],(10.^-p.psi.log.beta(chain,[1 end])),(10.^-p.psi.log.seBeta(chain,[1 end])),'bo') - plot(1:length(p.psi.log.beta(chain,:)),(p.psi.log.beta(chain,:)),'b-') - hold on; - errorbar([1 length(p.psi.log.beta(chain,:))],(p.psi.log.beta(chain,[1 end])),(p.psi.log.seBeta(chain,[1 end])),'bo') - %title(sprintf('estimated beta in SD = %3.3g (%3.3g)',(10.^-p.psi.log.beta(chain,end)),(10.^-p.psi.log.seBeta(chain,end)))) - title(sprintf('estimated beta = %3.3g (%3.3g)',(p.psi.log.beta(chain,end)),(p.psi.log.seBeta(chain,end)))) - xlim([-5 length(p.psi.log.beta(chain,:))+5]) - box off; - xlabel('# trials') - ylabel('beta'); - - - - - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %HYPOTHETICAL MEAN BARS - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - alphafake.sem=[5,4.7;5.5,5]; -alphafake.mean=[60,48;62,57]; - -betafake.sem=[4.5,4.3;5.1,4.9]; -betafake.mean=[30 20; 32 27]; - -fig=figure('Position',[3 50 700 500]); -subplot(1,2,1) -[h,e] = barwitherr(squeeze(alphafake.sem),squeeze(alphafake.mean)); -set(gca,'XTickLabel',{'CS+','CS-'}) -set(e,'LineWidth',1.5) -set(h(1), 'FaceColor','r') -set(h(2), 'FaceColor',[143/255 0 0]) -ylabel('threshold \alpha (degrees)') -ylim([0 100]) -axis square -legend('before','after','orientation','horizontal','location','southoutside') - -subplot(1,2,2) -[h,e] = barwitherr(betafake.sem,betafake.mean); -set(gca,'XTickLabel',{'CS+','CS-'}) -set(h(1), 'FaceColor','b') -set(h(2), 'FaceColor',[0 0.05 0.2]) -set(e,'LineWidth',1.5) -legend('before','after','orientation','horizontal','location','southoutside') -ylabel('slope \beta (SD)') -ylim([0 60]) -axis square - -t=supertitle('hypothetical changes in threshold \alpha and slope \beta') -set(t,'FontSize',14) \ No newline at end of file diff --git a/fearcloud_plotratings.m b/fearcloud_plotratings.m deleted file mode 100644 index c828770..0000000 --- a/fearcloud_plotratings.m +++ /dev/null @@ -1,46 +0,0 @@ -function fearcloud_plotratings(subject,run,aligned) - -r=isn_GetRatings(subject,run,aligned); -h=bar(r); -if run>2 - SetFearGenBarColors(h) - set(gca,'XTickLabel',{'-135','-90','-45','CSP','45','90','135','180'}) -elseif run==2 - xlabel('Number of Face') -end -ylim([0 10]) -ylabel('mean subjective p(shock)') -axis square -title(sprintf('Subject %d, Phase %d',subject,run)) -end -% -% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% %mean ratings business -% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% r1=isn_GetRatings(subjects,[2],0); -% r2=isn_GetRatings(subjects,[3 4],1); -% subplot(1,3,1) -% h=bar(mean(r1,2)); -% xlabel('Number of Face') -% ylim([0 10]) -% xlim([0 9]) -% ylabel('mean subjective p(shock)') -% axis square -% title('baseline') -% subplot(1,3,2) -% h=bar(mean(r2(:,:,1),2));SetFearGenBarColors(h); -% %set(gca,'XTickLabel',{'-135','-90','-45','CSP','45','90','135','180'}) -% set(gca,'XTickLabel',{'','','','CS+','','','','CS-'}) -% ylim([0 10]) -% xlim([0 9]) -% axis square -% title('conditioning') -% -% subplot(1,3,3) -% h=bar(mean(r2(:,:,2),2));SetFearGenBarColors(h); -% %set(gca,'XTickLabel',{'-135','-90','-45','CSP','45','90','135','180'}) -% set(gca,'XTickLabel',{'','','','CS+','','','','CS-'}) -% ylim([0 10]) -% xlim([0 9]) -% axis square -% title('testphase') diff --git a/fit_gamma.m b/fit_gamma.m new file mode 100644 index 0000000..947e16b --- /dev/null +++ b/fit_gamma.m @@ -0,0 +1,49 @@ +function [ gammaTable1, firstFit, displayGamma, inputV] = fit_gamma() +%% +% Fits gamma table for data recorded by sonat and nwilming in April 2017 on +% nordic neuro lab screen. +measurements = [... + 0.0400 0.0300... + 0.2000 0.2200... + 0.6300 0.6600... + 2.0700 2.0600... + 5.0900 5.0200... + 8.2600 8.2000... + 12.5700 12.4700... + 17.7700 17.6800... + 23.2600 23.1500... + 30.5600 30.4100... + 39.0500 38.6600... + 47.6600 47.5800... + 58.4700 58.3200... + 69.7800 69.7800... + 81.2200 81.3200... + 95.1100 95.1900... + 110.3000 110.5000... + 124.6000 125.0000... + 141.0000 141.4000... + 159.0000 159.6000... + 176.7000 177.0000... + 198.4000 199.0000... + 220.2000 220.0000... + 239.2000 240.0000... + 262.4000 263.3000]; + +inputV = linspace(0, 1, length(measurements))'; + +vals = (measurements - min(measurements)) / range(measurements); + +plot(inputV, vals) +hold on + +%Gamma function fitting +g = fittype('x^g'); +fittedmodel = fit(inputV, vals, g, 'StartPoint',1.5); +displayGamma = fittedmodel.g; + +inputV = linspace(0, 1, 255)'; +gammaTable1 = (((inputV))).^(1/fittedmodel.g); %#ok +firstFit = fittedmodel(inputV); %#ok +gammaTable1 = repmat(gammaTable1, 1, 3); +plot(inputV, firstFit, 'r') +end diff --git a/instructions/instruction_A.png b/instructions/instruction_A.png new file mode 100644 index 0000000..083512c Binary files /dev/null and b/instructions/instruction_A.png differ diff --git a/instructions/instruction_B.png b/instructions/instruction_B.png new file mode 100644 index 0000000..0ca1935 Binary files /dev/null and b/instructions/instruction_B.png differ diff --git a/instructions/instruction_B.svg b/instructions/instruction_B.svg new file mode 100644 index 0000000..9f5859c --- /dev/null +++ b/instructions/instruction_B.svg @@ -0,0 +1,4191 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Rule A + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Rule B + + + diff --git a/instructions/instruction_both.png b/instructions/instruction_both.png new file mode 100644 index 0000000..1d66988 Binary files /dev/null and b/instructions/instruction_both.png differ diff --git a/instructions/instruction_connectivity_A.svg b/instructions/instruction_connectivity_A.svg new file mode 100644 index 0000000..5553a8e --- /dev/null +++ b/instructions/instruction_connectivity_A.svg @@ -0,0 +1,4092 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/instructions/instruction_connectivity_A_S1.png b/instructions/instruction_connectivity_A_S1.png new file mode 100644 index 0000000..dd13c1a Binary files /dev/null and b/instructions/instruction_connectivity_A_S1.png differ diff --git a/instructions/instruction_connectivity_A_S1.svg b/instructions/instruction_connectivity_A_S1.svg new file mode 100644 index 0000000..0f72078 --- /dev/null +++ b/instructions/instruction_connectivity_A_S1.svg @@ -0,0 +1,3968 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/instructions/instruction_connectivity_A_S2.png b/instructions/instruction_connectivity_A_S2.png new file mode 100644 index 0000000..8b5b06e Binary files /dev/null and b/instructions/instruction_connectivity_A_S2.png differ diff --git a/instructions/instruction_connectivity_A_S2.svg b/instructions/instruction_connectivity_A_S2.svg new file mode 100644 index 0000000..907f54f --- /dev/null +++ b/instructions/instruction_connectivity_A_S2.svg @@ -0,0 +1,3970 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/instructions/instruction_connectivity_B.svg b/instructions/instruction_connectivity_B.svg new file mode 100644 index 0000000..00ed682 --- /dev/null +++ b/instructions/instruction_connectivity_B.svg @@ -0,0 +1,4106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/instructions/instruction_connectivity_B_S1.png b/instructions/instruction_connectivity_B_S1.png new file mode 100644 index 0000000..575ac09 Binary files /dev/null and b/instructions/instruction_connectivity_B_S1.png differ diff --git a/instructions/instruction_connectivity_B_S1.svg b/instructions/instruction_connectivity_B_S1.svg new file mode 100644 index 0000000..2de5e0e --- /dev/null +++ b/instructions/instruction_connectivity_B_S1.svg @@ -0,0 +1,3968 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/instructions/instruction_connectivity_B_S2.png b/instructions/instruction_connectivity_B_S2.png new file mode 100644 index 0000000..d42a260 Binary files /dev/null and b/instructions/instruction_connectivity_B_S2.png differ diff --git a/instructions/instruction_connectivity_B_S2.svg b/instructions/instruction_connectivity_B_S2.svg new file mode 100644 index 0000000..bed1d11 --- /dev/null +++ b/instructions/instruction_connectivity_B_S2.svg @@ -0,0 +1,3970 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/instructions/instruction_connectivity_both.svg b/instructions/instruction_connectivity_both.svg new file mode 100644 index 0000000..caac6fb --- /dev/null +++ b/instructions/instruction_connectivity_both.svg @@ -0,0 +1,4308 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/instructions/instruction_connectivity_template.svg b/instructions/instruction_connectivity_template.svg new file mode 100644 index 0000000..a9bfb73 --- /dev/null +++ b/instructions/instruction_connectivity_template.svg @@ -0,0 +1,4098 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Regel A: 100% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/instructions/instruction_glaze.png b/instructions/instruction_glaze.png new file mode 100644 index 0000000..bd6c907 Binary files /dev/null and b/instructions/instruction_glaze.png differ diff --git a/instructions/instruction_glaze.svg b/instructions/instruction_glaze.svg new file mode 100644 index 0000000..eb558cb --- /dev/null +++ b/instructions/instruction_glaze.svg @@ -0,0 +1,4253 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/instructions/left.png b/instructions/left.png new file mode 100644 index 0000000..8a24565 Binary files /dev/null and b/instructions/left.png differ diff --git a/instructions/right.png b/instructions/right.png new file mode 100644 index 0000000..d2c2368 Binary files /dev/null and b/instructions/right.png differ diff --git a/luminance.m b/luminance.m new file mode 100644 index 0000000..d08d9eb --- /dev/null +++ b/luminance.m @@ -0,0 +1,5 @@ +function lum = luminance() +cMatrix = ColorCal2('ReadColorMatrix'); +s = ColorCal2('MeasureXYZ'); +correctedValues = cMatrix(1:3,:) * [s.x s.y s.z]'; +lum = correctedValues(2); \ No newline at end of file diff --git a/make_connectivity_sequence.m b/make_connectivity_sequence.m new file mode 100644 index 0000000..0984ea1 --- /dev/null +++ b/make_connectivity_sequence.m @@ -0,0 +1,144 @@ +function stimuli = make_connectivity_sequence(ns, block_length) +%% +% Generate sequences for the complete connectivity experiment. +% +% Course of experiment: +% 1. Day 1. Phase 1. Behavioral only. +% Start with block that makes rule associations clear. +% +% 2. Day 2. Phase 2. fMRI: +% Wedge, Ring, Wedge - 3x Inference, 2x Localizer, T1 +% +% 3. Day 2. Phase 3. fMRI: +% Wedge, Ring, Wedge - 3x Inference, 2x Localizer, TSE + + + +duration = [2, 8]; +hazard_rate = 1/70; +fudge_factor = 0.7; % Determines by how much the instructed rule block + % length should be shortened to account for illusionary block changes. +glaze_duration = 0.4; +stimuli = {}; + + +% Define sequence of blocks. +block_types = {... + {'RW', 'IR', 'GL', 'GL', 'GL', 'GL', 'GL'},... + {'RW', 'RR', 'RW', 'GL', 'GL', 'GL', 'IR', 'IR', 'T1'},... + {'RW', 'RR', 'RW', 'GL', 'GL', 'GL', 'IR', 'IR', 'T1'}... + }; + + +for s = 1:ns % Iterates over subjects + stimuli{s} = {}; + for p = 1:3 % This iterates over sessions! + blocks = {}; + for block = 1:length(block_types{p}) + type = block_types{p}(block); + + if strcmp(type, 'IR') % Instructed rule + % Match block length to hazard rate. + avg_trial_length = 7.; % 2 sec Stim (incl. resp) + 5s + % Compute how long a rule is on display on average; + %avg_glaze_block_length = duration_glaze* avg_trials + choice_length*(duration_glaze*avg_trials*Q_rate); + avg_glaze_block_length = (1/hazard_rate) * glaze_duration * fudge_factor; + trials_per_block = floor(avg_glaze_block_length/avg_trial_length); + duration_per_block = trials_per_block*avg_trial_length; + n_trials = round(block_length/avg_trial_length); + validities = [0, 1]; + % Account for switches which also have 5s ISI+2 on average. + n_switches = floor(n_trials/(trials_per_block+1)); + [seq, es] = make_instructed_rule_onsets(600, validities, trials_per_block, duration); + blocks{block} = seq; + + elseif strcmp(type, 'GL') + [seq, es] = make_glaze_block(block_length); + blocks{block} = seq; %#ok<*AGROW> + else + seq = struct(); + seq.block_type = type{1}; + seq.rule = mod(block, 2); + blocks{block} = seq; + end + if p == 1 + blocks{block}.fmri = false; + else + blocks{block}.fmri = true; + end + end + + stimuli{s}{p} = blocks; %#ok + end +end + + function [seq, es] = make_instructed_rule_sequence(trials, validities, block_length, duration) + %% Makes a sequence of rules that change with a specific hazard rate. + %validities = [0, 0.25, 0.75, 1]; + seq.block_type = 'IR'; + seq.stim = randi(2, 1, trials)-1; + es = []; + seq.validity = repmat(randsample(validities, 1), 1, block_length); + seq.onset = [1, zeros(1, block_length-1)]; + seq.rewarded_rule = binornd(1, seq.validity(end), 1, block_length); + while length(seq.validity)1 + vs = randsample(newset, 1); + else + vs = newset; + end + seq.validity = [seq.validity, repmat(vs, 1, block_length)]; + seq.onset = [seq.onset, 1, zeros(1, block_length-1)]; + rewarded_rule = binornd(1, vs, 1, block_length); + seq.rewarded_rule = [seq.rewarded_rule, rewarded_rule]; + + end + seq.validity = seq.validity(1:trials); + seq.isi = duration(1) + (duration(2)-duration(1)).*rand(1, trials); + seq.isi2 = duration(1) + (duration(2)-duration(1)).*rand(1, trials); + seq.jitter = 0.3 + 0.7*rand(1, trials); + seq.isi = seq.isi-seq.jitter; + end + + function [seq, es] = make_instructed_rule_onsets(block_duration, validities, block_length, duration) + %% Makes a sequence of rules that change with a specific hazard rate. + % validities = [0, 0.25, 0.75, 1]; + isi = duration(1) + (duration(2)-duration(1)).*rand; + seq.block_type = 'IR'; + seq.stimulus_onset = isi; + seq.type = 0; + seq.stim = nan; + seq.rewarded_rule = binornd(1, 0.5, 1); + es = []; + %First determine stimulus onsets and number of trials + cur_block = 1; + while seq.stimulus_onset(end)<(block_duration-2) + isi = duration(1) + (duration(2)-duration(1)).*rand; + if seq.stimulus_onset(end) + isi > block_duration-2 + break + end + seq.stimulus_onset = [seq.stimulus_onset (seq.stimulus_onset(end) + isi +2)]; + % Determine next trial type + + + if cur_block == (block_length+1) + cur_block = 0; + seq.type = [seq.type 0]; + newset = setdiff(validities, seq.rewarded_rule(end)); + seq.stim = [seq.stim nan]; + rewarded_rule = binornd(1, newset, 1, 1); + seq.rewarded_rule = [seq.rewarded_rule, rewarded_rule]; + else + seq.type = [seq.type 1]; + seq.stim = [seq.stim randi(2, 1, 1);]; + seq.rewarded_rule = [seq.rewarded_rule, seq.rewarded_rule(end)]; + end + cur_block = cur_block +1; + seq.stimulus_onset(end); + end + + end + + +end \ No newline at end of file diff --git a/make_glaze_block.m b/make_glaze_block.m new file mode 100644 index 0000000..af9cb4f --- /dev/null +++ b/make_glaze_block.m @@ -0,0 +1,76 @@ +function [seq, es] = make_glaze_block(block_length) +duration = [2, 8]; +duration_glaze = .4; +hazard_rate = 1/70; +Q_rate = 1/35; +sigma = 1; +threshold = 0.5; + +% Compute number of trials necessary for specific block length. +mean_duration = duration_glaze; +trials = ceil(block_length/mean_duration); +[seq, es] = make_glaze_sequence(hazard_rate, block_length, threshold, sigma, Q_rate, [duration_glaze, duration_glaze]); + + function [seq, es] = make_glaze_sequence(hazard_rate, block_length, threshold, sigma, Q_rate, duration) + %% Makes a sequence of rules that change with a specific hazard rate. + seq.sample = []; + seq.generating_side = []; + seq.type = []; + %seq.isi = []; + seq.stimulus_onset = [0]; + seq.stim = []; + es = []; + mean_inter_change_length = 1/hazard_rate; + sides = [1, -1]; + side = randsample(sides, 1); + cnt = 0; + last_choice = false; + while seq.stimulus_onset(end) (mean_inter_change_length*2) + % continue + %end + e = exprndtrunc(mean_inter_change_length, 5, 2*mean_inter_change_length); + for i = 1:e + samples = (randn(1, 1)*sigma + side*threshold); + seq.sample = [seq.sample,samples]; + seq.generating_side = [seq.generating_side, side*threshold]; + % Sample spacing is between 200 and 300ms. + isi = duration(1) + (duration(2)-duration(1)).*rand; + %seq.isi = [seq.isi, isi]; + %if last_choice + % seq.stimulus_onset = [seq.stimulus_onset, seq.stimulus_onset(end) + 2 + isi + (3-2)*rand]; + % last_choice = false; + %else + seq.stimulus_onset = [seq.stimulus_onset, seq.stimulus_onset(end)+isi]; + %end + seq.type = [seq.type, 0]; + seq.stim = [seq.stim nan]; + cnt = cnt +1; + + if ((binornd(1, Q_rate) > 0.5) && (cnt > 10)) || (cnt > 20/.4) + seq.sample = [seq.sample, nan]; + seq.generating_side = [seq.generating_side, side*threshold]; + seq.type = [seq.type, 1]; + %seq.isi = [seq.isi, isi]; + seq.stimulus_onset = [seq.stimulus_onset, seq.stimulus_onset(end) + 2 + isi + (3-2)*rand]; + seq.stim = [seq.stim randi(2, 1)-1]; + cnt = 0; + last_choice = true; + end + end + side = side*-1; + es = [es e]; %#ok + end + idx = seq.stimulus_onset < block_length; + fields = fieldnames(seq); + for field = 1:length(fieldnames(seq)) + k = seq.(fields{field}); + seq.(fields{field}) = k(idx); + end + seq.sigma = sigma; + seq.block_type = 'GL'; + end + +end + diff --git a/make_immuno_sequence.m b/make_immuno_sequence.m new file mode 100644 index 0000000..cbd562c --- /dev/null +++ b/make_immuno_sequence.m @@ -0,0 +1,85 @@ + +function stimuli = make_immuno_sequence(ns, block_length) +%% +% One tral is: +% Prediction -> [wait] -> sample -> [wait] -> next trial +% Nassar has: +% [unknown] -> [0] -> [2s] -> [0] -> +% ns : number subjects +% mean_inter_change_length : 1/(hazard rate) +% trials : number of trials +% sigma : width of samples in degree +% pred_to_sample : [low, high] time between prediction and +% sample +% sample_to_pred : [low, high] time between sample and +% prediciton. +% ps : [p prediction, p choice, p sample_only] + +stimuli = {}; + +NS_mean_inter_change_length = 10; +NS_sample_duration = 3; +NS_sigma = 5; + +% Define sequence of blocks. +block_types = {... + {'GL', 'GL', 'GL', 'GL', 'GL', 'GL', 'GL'},... + {'NS', 'NS', 'NS', 'NS', 'NS', 'NS', 'NS'},... + {'GL', 'GL', 'GL', 'GL', 'GL', 'GL', 'GL'},... + {'NS', 'NS', 'NS', 'NS', 'NS', 'NS', 'NS'},... + {'GL', 'GL', 'GL', 'GL', 'GL', 'GL', 'GL'},... + {'NS', 'NS', 'NS', 'NS', 'NS', 'NS', 'NS'},... + }; + + +for s = 1:ns % Iterates over subjects + stimuli{s} = {}; + for p = 1:6 % This iterates over sessions! + blocks = {}; + for block = 1:length(block_types{p}) + type = block_types{p}(block); + if strcmp(type, 'NS') + avg_duration = NS_sample_duration + 2; + num_trials = block_length/avg_duration; + [seq, es] = make_nassar_sequence(NS_mean_inter_change_length, num_trials); + elseif strcmp(type, 'GL') + [seq es] = make_glaze_block(block_length); + end + blocks{block} = seq; %#ok + blocks{block}.fmri = false; %#ok + + end + stimuli{s}{p} = blocks; %#ok + end +end + + + + function [seq, es] = make_nassar_sequence(mean_inter_change_length, trials) + %% Make a sequence of random numbers drawn from a normal distribution, + % where the mean changes on average every + % mean_inter_change_length + seq.block_type = 'NR'; + seq.sigma = NS_sigma; + seq.sample = []; + seq.mu = []; + seq.stim = randi(2, 1, trials)-1; + es = []; + while length(seq.sample) + end + seq.mu = seq.mu(1:trials); + seq.sample = seq.sample(1:trials); + seq.isi = 0;%duration(1) + (duration(2)-duration(1)).*rand(1, trials); + seq.jitter = 0.3 + 0.7*rand(1, trials); + seq.isi = seq.jitter; + seq.sample_duration = 0*seq.isi + NS_sample_duration; + end + + + +end \ No newline at end of file diff --git a/make_retinotopy_experiment.m b/make_retinotopy_experiment.m new file mode 100644 index 0000000..0d8d68f --- /dev/null +++ b/make_retinotopy_experiment.m @@ -0,0 +1,38 @@ +function params = make_retinotopy_experiment() +%% Create a VistaDisp retinotopy experiment + +params = struct(); +params.experiment= 'rotating wedge (45deg duty)'; +params.fixation= 'double disk'; +params.modality= 'fMRI'; +params.savestimparams= 1; +params.repetitions= 1; +params.runPriority= 7; +params.skipCycleFrames= 0; +params.prescanDuration= 0; +%params.period= 192; +params.period= 24; +params.numCycles= 1; +params.motionSteps= 8; +params.tempFreq= 2.5; +params.contrast= 1; +params.interleaves= []; +params.tr= 0.88; +%params.loadMatrix= '/Users/nwilming/u/flexible_rule/experiment/retinotopy/forward_retino_stim.mat'; +params.loadMatrix=[]; +params.saveMatrix= '/Users/nwilming/u/flexible_rule/experiment/retinotopy/forward_retino_stim.mat'; +params.calibration= []; +params.stimSize= 'max'; +params.countdown= 0; +params.startScan= 0; +params.trigger= 'Scanner triggers computer'; +params.triggerKey= '5'; +params.calibration = 'NNL_UKE'; +params.calibration = 'Larry'; + +% now set rest of the params +params = setRetinotopyParams(params.experiment, params); + +% set response device +params = setRetinotopyDevices(params); +end \ No newline at end of file diff --git a/make_ring_experiment.m b/make_ring_experiment.m new file mode 100644 index 0000000..4dba045 --- /dev/null +++ b/make_ring_experiment.m @@ -0,0 +1,38 @@ +function params = make_ring_experiment() +%% Create a VistaDisp retinotopy experiment +tr = 0.88; + +params = struct() +params.experiment= 'expanding ring (45% duty)'; +params.fixation= 'double disk'; +params.modality= 'fMRI'; +params.savestimparams= 1; +params.repetitions= 1; +params.runPriority= 7; +params.skipCycleFrames= 0; +params.prescanDuration= 0; +%params.period= 24; +params.period = 27*tr%24; +params.numCycles= 1; +params.motionSteps= 10%8; +params.tempFreq= 2.5000; +params.contrast= 1; +params.interleaves= []; +params.tr= tr; +params.loadMatrix= []; +params.saveMatrix= []; +params.calibration= []; +params.stimSize= 'max'; +params.countdown= 0; +params.startScan= 0; +params.trigger= 'Scanner triggers computer'; +params.triggerKey= '5'; +params.calibration = 'NNL_UKE'; +params.calibration = 'Larry'; + +% now set rest of the params +params = setRetinotopyParams(params.experiment, params); + +% set response device +params = setRetinotopyDevices(params); +end \ No newline at end of file diff --git a/make_sample_stimuli.m b/make_sample_stimuli.m new file mode 100644 index 0000000..60fe031 --- /dev/null +++ b/make_sample_stimuli.m @@ -0,0 +1,112 @@ +function textures = make_sample_stimuli() +% Adapt psychtoolbox's CalibrateMonitorPhotometer to show two stimuli at +% different locations and to read measurements from a color hug. +[~, hostname] = system('hostname'); +hostname = hostname(1:end-1); + +cachefile = sprintf('%s_noise_nassar_sample_spec.mat', hostname); +%if ~exist(cachefile, 'file') + Screen('Preference', 'SkipSyncTests', 1); + screenid = min(Screen('Screens')); + psychlasterror('reset'); + luminances = []; + + % Open black window: + white = WhiteIndex(screenid); + black = BlackIndex(screenid); + grey = white / 2; + % Open the screen + [win, p.ptb.rect] = Screen('OpenWindow', screenid, [grey, grey, grey], [0, 0, 500, 400]); + stimuli = make_sample_textures(win, cachefile); + %Screen('Close All'); + sca +%else +% load(cachefile) +%end + +for k = 1:300 + stimuli_small{k} = stimuli{k}(520:603, 890:1030,:); +end + +textures = {}; +mms = []; +while true + [h, w] = size(stimuli{1}); + noise = rand(round(h), round(w))>0.5; + noise_small = noise(520:603, 890:1030); + crits = nan*ones(300,1); + for jj = 1:300 + mask = mean(stimuli_small{jj}, 3); + mask = mask>mean(mask(:)); + ms = mean(mask(:)); + crit = sum(mask(:))/2; + m = sum(noise_small(mask)); + crits(jj) = abs(m-crit); + %background = mask*0+128; + %background(mask) = noise(mask)*255; + %textures{jj} = background; + end + mms = [mms mean(crits)]; + fprintf('Min dev: %d\n', min(mms)) + if min(mms) < 7 + break + end +end + +for jj = 1:300 + mask = mean(stimuli{jj}, 3); + mask = mask>mean(mask(:)); + background = mask*0+128; + background(mask) = noise(mask)*255; + textures{jj} = background(1080/2-200:1080/2+200, 1960/2-200:1960/2+200); +end + +cachefile = sprintf('%s_nassar_sample_spec.mat', hostname); +save(cachefile, 'textures', '-v7.3'); + + + function stimuli= make_sample_textures(win, cachefile) + [~, hostname] = system('hostname'); + hostname = hostname(1:end-1); + + stimuli = {}; + + + w = 500; + h = 400; + I = cat(3, ones(h, w)*0); + numbers = {}; + for ii = 0:9 + txt = Screen('MakeTexture', win, I); + Screen('TextSize', txt, 70); + Screen('TextFont', txt, 'Courier'); + Screen('TextStyle', txt, 1); + DrawFormattedText(txt, num2str(ii), 'center', 'center', [255, 255, 255]); + imageArray=Screen('GetImage', txt); + numbers{ii+1} = imageArray(400/2 -25: 400/2+25, 500/2-20:500/2+20); %#ok + end + save('numbers.mat', 'numbers', '-v7.3'); + + w = 1960; + h = 1080; + for ii = 1:300 + txt = ones(h, w)*0; + hpos = 1080/2 + 15; + xc = 1960/2; + xpos = [-75 -25 25]; + d = sprintf('%03i', ii); + for k = 1:3 + %size(txt( hpos:hpos+50, xc+xpos(k):xc+xpos(k)+40)) + %size(double(numbers{1+str2num(d(k))})) + txt( hpos:hpos+50, xc+xpos(k):xc+xpos(k)+40) = double(numbers{1+str2num(d(k))}); + end + stimuli{ii} = txt; %#ok + end + + save(cachefile, 'stimuli', '-v7.3'); + + + end + + +end \ No newline at end of file diff --git a/make_sequence.m b/make_sequence.m new file mode 100644 index 0000000..3643167 --- /dev/null +++ b/make_sequence.m @@ -0,0 +1,155 @@ + +function stimuli = make_sequence(ns, mean_inter_change_length, trials, reward_probabilities, duration) +stimuli = {}; + +% Course of experiment: +% 1. Training, exp only +% 2. fMRI, E Q E Q E Q E Q E +% 3. Training, exp only +% 4. fMRI, E Q E Q E Q E Q E +% 5. Training, exp only +% 6. fMRI, E Q E Q E Q E Q E + +for s = 1:ns + stimuli{s} = {}; + for p = 1:6 % This iterates over days. + if mod(p, 2) == 1 % Training session + block_types = {'E', 'E', 'E', 'E', 'E', 'E', 'E'}; + else + block_types = {'E', 'QA', 'E', 'QB', 'E', 'QA', 'E', 'QB', 'E'}; + end + blocks = {}; + for block = 1:length(block_types) + type = block_types(block); + if strcmp(type, 'E') + es = 0; + while abs(mean(es)-mean_inter_change_length) > 1 + if length(reward_probabilities)==3 + [seq, es] = make_exp_sequence(mean_inter_change_length, trials); + else + [seq, es] = make_exp_sequence_two(mean_inter_change_length, trials); + end + end + else + seq = make_Q_sequence(trials, type); + end + blocks{block} = seq; %#ok + + end + stimuli{s}{p} = blocks; %#ok + end +end + + function [seq, es] = make_exp_sequence(mean_inter_change_length, trials) + %% Makes a sequence of rules that change with a specific hazard rate. + seq.type = 'EXP'; + seq.reward_probability = []; + seq.pRP = []; + seq.stim = randi(2, 1, trials)-1; + es = []; + + start = [0,1,2]; + nexts = [[1,2]; [0, 2]; [0,1]]; + + while length(seq.reward_probability) (mean_inter_change_length*2) + continue + end + if numel(seq.reward_probability)==0 + next_rp = randsample(start,1); + else + next_rp = randsample(nexts(seq.reward_probability(end)+1,:), 1); + end + next_set = repmat(next_rp, 1, e); + + seq.reward_probability = [seq.reward_probability, next_set]; + es = [es e]; %#ok + end + + seq.reward_probability = seq.reward_probability(1:trials); + seq.isi = duration(1) + (duration(2)-duration(1)).*rand(1, trials); + seq.jitter = 0.3 + 0.7*rand(1, trials); + seq.isi = seq.isi-seq.jitter; + gv_rule_a = []; + gv_rule_b = []; + for iii = 1:trials + seq.pRP = [seq.pRP reward_probabilities(seq.reward_probability(iii)+1)]; + P_a = seq.pRP(iii); + P_b = 1-P_a; + rew = boolean(binornd(1, P_a)); + gv_rule_a = [gv_rule_a rew]; %#ok + gv_rule_b = [gv_rule_b ~rew]; %#ok + end + seq.give_reward_rule_a = gv_rule_a; + seq.give_reward_rule_b = gv_rule_b; + end + + + function [seq, es] = make_exp_sequence_two(mean_inter_change_length, trials) + %% Makes a sequence of rules that change with a specific hazard rate. + seq.type = 'EXP'; + seq.reward_probability = []; + seq.pRP = []; + seq.stim = randi(2, 1, trials)-1; + es = []; + + start = [0,1]; + + while length(seq.reward_probability) (mean_inter_change_length*2) + continue + end + if numel(seq.reward_probability)==0 + next_rp = randsample(start,1); + else + next_rp = ~seq.reward_probability(end); + end + next_set = repmat(next_rp, 1, e); + + seq.reward_probability = [seq.reward_probability, next_set]; + es = [es e]; %#ok + end + + seq.reward_probability = seq.reward_probability(1:trials); + seq.isi = duration(1) + (duration(2)-duration(1)).*rand(1, trials); + seq.jitter = 0.7 + 0.2*rand(1, trials); + seq.isi = seq.isi-seq.jitter; + gv_rule_a = []; + gv_rule_b = []; + for iii = 1:trials + seq.pRP = [seq.pRP reward_probabilities(seq.reward_probability(iii)+1)]; + P_a = seq.pRP(iii); + rew = boolean(binornd(1, P_a)); + gv_rule_a = [gv_rule_a rew]; %#ok + gv_rule_b = [gv_rule_b ~rew]; %#ok + end + seq.give_reward_rule_a = gv_rule_a; + seq.give_reward_rule_b = gv_rule_b; + end + + + function [seq, es] = make_Q_sequence(trials, type) + %% Makes a sequence with one rule active + seq.type = type; + if strcmp(type, 'QA') + seq.reward_probability = 0*ones(1, trials); + seq.pRP = ones(1, trials); + seq.give_reward_rule_a = 1*ones(1, trials); + seq.give_reward_rule_b = 0*seq.give_reward_rule_a; + else + seq.reward_probability = 2*ones(1, trials); + seq.pRP = 0*ones(1, trials); + seq.give_reward_rule_a = 0*ones(1, trials); + seq.give_reward_rule_b = 1+seq.give_reward_rule_a; + end + seq.stim = randi(2, 1, trials)-1; + es = []; + seq.isi = duration(1) + (duration(2)-duration(1)).*rand(1, trials); + seq.jitter = 0.3 + 0.7*rand(1, trials); + seq.isi = seq.isi-seq.jitter; + seq.pRP = ones(1, trials); + seq.give_reward = ones(1, trials); + end +end \ No newline at end of file diff --git a/make_wedge_experiment.m b/make_wedge_experiment.m new file mode 100644 index 0000000..402b624 --- /dev/null +++ b/make_wedge_experiment.m @@ -0,0 +1,38 @@ +function params = make_wedge_experiment() +%% Create a VistaDisp retinotopy experiment +tr = 0.88; +params = struct(); +params.experiment= 'rotating wedge (45deg duty)'; +params.fixation= 'double disk'; +params.modality= 'fMRI'; +params.savestimparams= 1; +params.repetitions= 1; +params.runPriority= 7; +params.skipCycleFrames= 0; +params.prescanDuration= 0; +%params.period= 192; +params.period = 27*tr%24; +params.numCycles= 1; +params.motionSteps= 10 %8; +params.tempFreq= 2.5; +params.contrast= 1; +params.interleaves= []; +params.tr= tr; +%params.loadMatrix= '/Users/nwilming/u/flexible_rule/experiment/retinotopy/forward_retino_stim.mat'; +params.loadMatrix=[]; +params.saveMatrix= '/Users/nwilming/u/flexible_rule/experiment/retinotopy/forward_retino_stim.mat'; +params.calibration= []; +params.stimSize= 'max'; +params.countdown= 0; +params.startScan= 0; +params.trigger= 'Scanner triggers computer'; +params.triggerKey= '5'; +params.calibration = 'NNL_UKE'; +params.calibration = 'Larry'; + +% now set rest of the params +params = setRetinotopyParams(params.experiment, params); + +% set response device +params = setRetinotopyDevices(params); +end \ No newline at end of file diff --git a/measure_sample_luminances.m b/measure_sample_luminances.m new file mode 100644 index 0000000..513c672 --- /dev/null +++ b/measure_sample_luminances.m @@ -0,0 +1,76 @@ +function luminances = measure_sample_luminances() +% Adapt psychtoolbox's CalibrateMonitorPhotometer to show two stimuli at +% different locations and to read measurements from a color hug. +Screen('Preference', 'SkipSyncTests', 1); +screenid = min(Screen('Screens')); +psychlasterror('reset'); +luminances = []; + +o = load('vpixx_gamma_table'); +gt = o.table; + +% Open black window: +white = WhiteIndex(screenid); +black = BlackIndex(screenid); +grey = white / 2 +% Open the screen +[win, p.ptb.rect] = Screen('OpenWindow', screenid, [grey, grey, grey])%, [0, 0, 1000, 500]); +[old_table] = Screen('LoadNormalizedGammaTable', win, gt); + +sample_textures = make_sample_textures(win); + +maxLevel = Screen('ColorRange', win); +Screen('Flip',win); +draw_prd_sample(ii); +Screen('Flip', win); +%KbPressWait(); +WaitSecs(25); +bgcolors = linspace(0,1,300)*255; +samples = 1:300; +for ii = 1:length(bgcolors) + Screen('FillRect', win, [bgcolors(ii), bgcolors(ii), bgcolors(ii)]); + Screen('Flip', win); + WaitSecs(0.1); + luminances = [luminances, luminance()]; %#ok + Screen('FillRect', win, [grey grey grey]); + draw_prd_sample(samples(ii)); + Screen('Flip', win); + WaitSecs(0.1); + luminances = [luminances, luminance()]; %#ok +end + + +RestoreCluts; +Screen('CloseAll'); + + + + + function draw_prd_sample(sample) + Screen('BlendFunction', win, 'GL_SRC_ALPHA', 'GL_ONE_MINUS_SRC_ALPHA'); + Screen('DrawTexture', win, sample_textures(sample)); + Screen('BlendFunction', win, 'GL_ONE', 'GL_ZERO'); + end + + function textures = make_sample_textures(win) + [~, hostname] = system('hostname'); + hostname = hostname(1:end-1); + cachefile = sprintf('%s_nassar_sample_spec.mat', hostname); + stimuli = {}; + + stimuli = load(cachefile); + stimuli = stimuli.textures; + + %noise = (noise>mean(noise(:))); + textures = []; + for ii = 1:300 + stim = stimuli{ii}; + stim = cat(3, stim, (~(stim==128))*255); + txt = Screen('MakeTexture', win, stim); + textures = [textures, txt]; %#ok + end + p.stim.sample_textures = textures; + end + + +end \ No newline at end of file diff --git a/new_connectivity_sequences-S1-S6.mat b/new_connectivity_sequences-S1-S6.mat new file mode 100644 index 0000000..0d028c0 Binary files /dev/null and b/new_connectivity_sequences-S1-S6.mat differ diff --git a/new_connectivity_sequences-S7andfollowing.mat b/new_connectivity_sequences-S7andfollowing.mat new file mode 100644 index 0000000..6608e9a Binary files /dev/null and b/new_connectivity_sequences-S7andfollowing.mat differ diff --git a/new_connectivity_sequences.mat b/new_connectivity_sequences.mat new file mode 100644 index 0000000..0d028c0 Binary files /dev/null and b/new_connectivity_sequences.mat differ diff --git a/nne_uke_scanner.mat b/nne_uke_scanner.mat new file mode 100644 index 0000000..e918fab Binary files /dev/null and b/nne_uke_scanner.mat differ diff --git a/remi3_fmri_all.m b/remi3_fmri_all.m deleted file mode 100644 index db8f9bf..0000000 --- a/remi3_fmri_all.m +++ /dev/null @@ -1,1242 +0,0 @@ -function [p] = remi3_fmri_all(subject,run,group) - -if nargin == 0 - subject = 96; run = 1; group = 1; -end - -if group == 1 - name = 'NaCl'; -elseif group == 2 - name = 'Remi50'; -elseif goup == 3 - name = 'Remi100'; -end -fprintf('Sub%02d\nRun%d\nGroup: %s\n',subject,run,name); - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%% Put in your experiment choices here -debug = 1; % Use this function to have a transparent screen -p_mri_on = 0; % If on, waits for pulses and useses BrainVision Recorder marking BEFORE it marks CED. Otherwise, it only uses CED marking and sets BVR to 0 -p_slave_on = 0; % If on, waits for pulse from master and starts presentation at the same time. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Initialize Experiment Environment -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -ListenChar(2); % Disable pressed keys to printed out -commandwindow; -%clear everything without using 'clear all' -clear mex global functions - -%%%%%%%%%%%%%%%%%%%%%%%%%%% Load the GETSECS mex files so call them at -%%%%%%%%%%%%%%%%%%%%%%%%%%% least oncec -GetSecs; -WaitSecs(0.001); - -SetParameters; - -if strcmp(p.hostname,'triostim1') - debug = 0; -end - -SetPTB; - - -%%%%%%%%%%%%%%%%%%%%%%%%%%% Initialize all variables -nTrial = 0; -stimName = []; -itiDuration = []; -CueDuration = []; -TimeCrossOn = []; -TimeCueOn = []; -TimeHeatOn = []; -TimeStarOn = []; -TimeBlankOn = []; -TimeBreathOn = []; -p_stim_white = p.stim.white; -p_stim_red = p.stim.red; -p_stim_backgr = p.stim.backgr; -p_stim_sizeCross = p.stim.sizeCross; -p_stim_widthCross = p.stim.widthCross; -p_monitor_nx = p.monitor.Xaxis; % pixel x-axis -p_monitor_ny = p.monitor.Yaxis; % pixel y-axis -p_com_lpt_CEDaddress = p.com.lpt.CEDaddress; -p_com_lpt_CEDduration = p.com.lpt.CEDduration; -p_com_lpt_scannerPulseOnset = p.com.lpt.scannerPulseOnset; -p_com_lpt_ITIOnset = p.com.lpt.ITIOnset; -% p_com_lpt_CueOnset = p.com.lpt.CueOnset; -p_com_lpt_HeatOnset = p.com.lpt.HeatOnset; -p_com_lpt_VASOnset = p.com.lpt.VASOnset; -p_presentation_itiDuration = p.presentation.itiDuration; -p_presentation_CueDuration = p.presentation.CueDuration; -p_presentation_stimDuration = p.presentation.stimDuration; -p_presentation_blankDuration = p.presentation.blankDuration; -p_presentation_stimSequence = p.presentation.stimSequence; -p_presentation_TrialList = p.presentation.trialList; -p_presentation_scaleDuration = p.presentation.scaleDuration; -p_keys_trigger = p.keys.trigger; -p_keys_nextStep = p.keys.nextStep; -p_mri_tr = p.mri.tr; -p_ptb_w = p.ptb.w; -p_ptb_midpoint = p.ptb.midpoint; -p_ptb_midpoint_y = p.ptb.midpoint(2); -p_ptb_rect = p.ptb.rect; -p_ptb_startY = p.ptb.startY; -p_text_linespace = p.text.linespace; -p_ptb_lineheight = p.ptb.lineheight; - -% save again the parameter file -save(p.path.save ,'p'); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% Run Experiment -% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -putLog(GetSecs, 'Experiment Start'); -fprintf(['=================\n=================\nStart thermode protocol ' num2str(p_presentation_stimSequence) '!!!!\n']); - -% Show Instructions; -ShowInstruction; - -% Wait for Dummy Scans -firstScannerPulseTime = WaitPulse(p.keys.trigger,p.mri.dummyScan); -commandwindow; -p.log.mriExpStartTime = firstScannerPulseTime(end); -putLog(p.log.mriExpStartTime, 'FirstMRPulse_ExpStart'); - -% Actual stimulus presentation -runExperiment; - -% Show SessionEnd -ShowEndSessionText; - -cleanup; -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% End of Experiment -% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - -%% Set all parameters relevant for the whole experiment and the specific subject - function SetParameters - p.mri.on = p_mri_on; - p.mri.dummyScan = 5; - p.mri.tr = 2.65; - p.slave = p_slave_on; - p.subinfo.subID = subject; - p.subinfo.group = group; % nacl 1 remi50 2 remi100 3 - p.subinfo.groupname = name; % nacl 1 remi50 2 remi100 3 - p.subinfo.run = run; - - %%%%%%%%%%%%%%%%%%%%%%%%%%% create log structure - p.log.mriExpStartTime = 0; % Initialize as zero - p.log.events = {{},{},{},{}}; % event count, real time, experiment duration, event string - p.log.ratings1 = []; % event count, real time, experiment duration, event string - p.log.ratings2 = []; - p.log.eventCount = 0; - p.log.rating1EventCount = 0; - p.log.rating2EventCount = 0; - p.log.onratingEventCount = 0; - p.log.moodEventCount = 0; - p.log.scaleDefaultVAS1 = []; - p.log.scaleDefaultVAS2 = []; - p.log.PainOnset = []; - p.log.PainOnsetScan = []; - p.log.MoodRating = []; - p.log.Rating1 = []; - p.log.Rating2 = []; - - %%%%%%%%%%%%%%%%%%%%%%%%%%% relative paths to stim and experiments - [~, hostname] = system('hostname'); - p.hostname = deblank(hostname); - p.hostaddress = java.net.InetAddress.getLocalHost ; - p.hostIPaddress = char( p.hostaddress.getHostAddress); - if strcmp(p.hostname,'triostim1') - p.path.experiment = 'C:\USER\tinnermann\remi3\Paradigma_MRT\'; - p.monitor.Xaxis = 1024; % stim PC resolution - p.monitor.Yaxis = 768; % stim PC resolution - else - p.path.experiment = 'C:\Users\tinnermann\Documents\remi3\Paradigma_MRT\'; - p.monitor.Xaxis = 1920; % stim PC resolution - p.monitor.Yaxis = 1200; % stim PC resolution - end - % - p.subID = sprintf('sub%02d',subject); - p.timestamp = datestr(now,30); - - p.path.subject = [p.path.experiment '/logs/' p.subID '/']; - - p.path.save = [p.path.subject p.subID '_run' num2str(p.subinfo.run) '_' p.timestamp ]; - %create folder hierarchy - mkdir(p.path.subject); - - %%%%%%%%%%%%%%%%%%%%%%%%%%% font size, background gray level, monitor settings - p.text.fontname = 'Arial'; - p.text.fontsize = 20; %30; %18; - p.text.linespace = 10; - p.stim.white = [255 255 255]; - p.stim.red = [255 0 0]; - p.stim.backgr = [70 70 70]; - p.stim.widthCross = 3; - p.stim.sizeCross = 20; - - if strcmp(p.hostname,'triostim1') % curdes button box single diamond (HID NAR 12345) - p.keys.confirm = KbName('3#'); % green button - p.keys.right = KbName('4$'); % red button - p.keys.left = KbName('2@'); % yellow button - p.keys.esc = KbName('esc'); - p.keys.nextStep = KbName('space'); - p.keys.trigger = KbName('5%'); - else - %All settings for laptop computer. - KbName('UnifyKeyNames'); - p.keys.confirm = KbName('Return'); - p.keys.right = KbName('RightArrow'); - p.keys.left = KbName('LeftArrow'); - p.keys.esc = KbName('Escape'); - p.keys.nextStep = KbName('space'); - p.keys.trigger = KbName('5'); - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%% Parallel port settings - % Codes for different events - % device Thermode: 4 - % Spike-channel 4 : 32 - % Spike-channel 5 : 64 - % Spike-channel 6 : 128 - - if strcmp(p.hostname,'triostim1') - p.com.lpt.scannerPulseOnset = 224; % start of each run -> 32+64+128 (all 3 channels) - p.com.lpt.HeatOnset = 36; % Cue (spike channel 4) - p.com.lpt.VASOnset = 64; % Heat trigger for thermode plus spike channel 5 - p.com.lpt.ITIOnset = 128; % VAS/Mood scale on (Spike-channel 6) - % p.com.lpt.ITIOnset = 192; % white fixation cross on channel 5 and 6 - else - p.com.lpt.scannerPulseOnset = 0; % start of each run -> 32+64+128 (all 3 channels) - p.com.lpt.CueOnset = 0; % Cue (spike channel 4) - p.com.lpt.HeatOnset = 255; % Heat trigger for thermode - p.com.lpt.VASOnset = 0; % VAS/Mood scale on (Spike-channel 6) - p.com.lpt.ITIOnset = 0; % white fixation cross - end - p.com.lpt.CEDaddress = 888; - p.com.lpt.CEDduration = 0.005; - - %%%%%%%%%%%%%%%%%%%%%%%%%%% Stimulus sequence and startle timings - p.presentation.stimDuration = 17; - p.presentation.blankDuration = 0.5; - iti = [19 20 21 22 22 23 24 25]; - trialLists = load([p.path.experiment 'trial_seq.mat']); - trialLists = trialLists.trial_seq; - sequence = load([p.path.experiment 'rand_seq.mat']); - sequence = sequence.rand_seq; - p.presentation.stimSequence = sequence(run,subject); - p.presentation.trialList = trialLists(:,p.presentation.stimSequence); - p.presentation.tTrial = length(p.presentation.trialList); %number of trials - p.presentation.itiDuration = iti(randperm(length(iti))); - p.presentation.CueDuration = 4; - p.presentation.scaleDuration = 8; - p.presentation.scaleBackColor = p.stim.backgr; - p.presentation.BreathRem = 2; - p.presentation.starTime = 0.6; - p.presentation.lastITI = 4; - - clearvars trialLists - - %%%%%%%%%%%%%%%%%%%%%%%%%%% Save the parameters for this subject - save(p.path.save ,'p'); - end - -%% Set Up the PTB with parameters and initialize drivers - function SetPTB - screens = Screen('Screens'); % Find the number of the screen to be opened - p.ptb.screenNumber = max(screens); % The maximum is the second monitor - if debug - commandwindow; - PsychDebugWindowConfiguration; % Make everything transparent for debugging purposes. - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%% Default parameters - Screen('Preference', 'SkipSyncTests', 0); - Screen('Preference', 'DefaultFontSize', p.text.fontsize); - Screen('Preference', 'DefaultFontName', p.text.fontname); - %Screen('Preference', 'TextAntiAliasing',2); % Enable textantialiasing high quality - Screen('Preference', 'VisualDebuglevel', 0); % 0 disable all visual alerts - %Screen('Preference', 'SkipSyncTests', 0); - %Screen('Preference', 'SuppressAllWarnings', 0); - if debug == 0; - HideCursor(p.ptb.screenNumber); % Hide the cursor - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%% Open a graphics window using PTB - p.ptb.w = Screen('OpenWindow', p.ptb.screenNumber, p.stim.backgr); - % Screen('TextStyle', p.ptb.w, 1); % Make Text Bold - Screen('Flip',p.ptb.w); % Make the bg - p.ptb.slack = Screen('GetFlipInterval',p.ptb.w)./2; - % [p.ptb.width, p.ptb.height] = Screen('WindowSize', p.ptb.screenNumber); - p.ptb.rect = [0 0 p.monitor.Xaxis p.monitor.Yaxis]; - p.ptb.width = p.monitor.Xaxis; - p.ptb.height = p.monitor.Yaxis; - p.ptb.midpoint = [p.ptb.width./2 p.ptb.height./2]; % Find the mid position on the screen. - - p.ptb.startY = p.monitor.Yaxis/4; - p.ptb.lineheight = p.text.fontsize + p.text.linespace; - - p.ptb.whiteFix1 = [p.ptb.midpoint(1)-p.stim.sizeCross p.ptb.startY-p.stim.widthCross p.ptb.midpoint(1)+p.stim.sizeCross p.ptb.startY+p.stim.widthCross]; - p.ptb.whiteFix2 = [p.ptb.midpoint(1)-p.stim.widthCross p.ptb.startY-p.stim.sizeCross p.ptb.midpoint(1)+p.stim.widthCross p.ptb.startY+p.stim.sizeCross]; - % p.ptb.imrect = [ p_ptb_midpoint(1)-p.stim.width/2 p_ptb_midpoint(2)-p.stim.height/2 p.stim.width p.stim.height]; - - p.ptb.priorityLevel=MaxPriority('GetSecs','KbCheck','KbWait'); - Priority(MaxPriority(p.ptb.w)); - p.ptb.device = []; - - %%%%%%%%%%%%%%%%%%%%%%%%%%% Parallel port communication. - config_io; - outp(p.com.lpt.CEDaddress,0); - - end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Functions collection -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - function [secs]=WaitPulse(keycode,n) - %[secs]=WaitPulse(keycode,n) - % - % This function waits for the Nth upcoming pulse. If N=1, it will wait for - % the very next pulse to arrive. 1 MEANS NEXT PULSE. So if you wish to wait - % for 6 full dummy scans, you should use N = 7 to be sure that at least 6 - % full acquisitions are finished. - % - % The function avoids KbCheck, KbWait functions, but relies on the OS - % level event queues, which are much less likely to skip short events. A - % nice discussion on the topic can be found here: - % http://ftp.tuebingen.mpg.de/pub/pub_dahl/stmdev10_D/Matlab6/Toolboxes/Psychtoolbox/PsychDocumentation/KbQueue.html - - %KbQueueFlush;KbQueueStop;KbQueueRelease;WaitSecs(1); - fprintf('Will wait for %i dummy pulses...\n',n); - if n ~= 0 - secs = nan(1,n); - pulse = 0; - dummy = []; - while pulse < n - dummy = KbTriggerWait(keycode,p.ptb.device); - pulse = pulse + 1; - secs(pulse+1) = dummy; - fprintf('Waiting for dummy scan %d\n',pulse); - putLog(dummy,num2str(pulse)); - end - else - secs = GetSecs; - end - end - -%% Start the actual experiment - function runExperiment - for nTrial = 1:p.presentation.tTrial; % Enter the presentation loop - stimName = p_presentation_TrialList(nTrial); - itiDuration = p_presentation_itiDuration(nTrial); - CueDuration = p_presentation_CueDuration; - - if nTrial == 1 % Turn on the fixation cross for the first trial. These have to be done before the main for loop. - Screen('FillRect', p_ptb_w, p_stim_white, p.ptb.whiteFix1); - Screen('FillRect', p_ptb_w, p_stim_white, p.ptb.whiteFix2); - TimeCrossOn = Screen('Flip',p_ptb_w); % gets timing of event for putLog - putMark(p_com_lpt_ITIOnset); % Mark Fixation Cross Onset - putLog(TimeCrossOn, 'FirstITIOnset'); % Log the cross onset... - fprintf('=================\n=================\nFirst ITI, waiting for 5 seconds\n=================\n=================\n'); - while GetSecs < TimeCrossOn + 5 end - end - - fprintf('%d of %d, Stim: %d, CueDuration: %d, itiDuration: %d \n',nTrial,p.presentation.tTrial, stimName(1), CueDuration, itiDuration); - - p.log.scaleDefaultVAS1(nTrial,1) = randi([30,71]); - p.log.scaleDefaultVAS2(nTrial,1) = randi([30,71]); - p.log.scaleDefaultMood(nTrial,1) = randi([2,6]); - - Trial(itiDuration); - - end - - fprintf('=================\n=================\nWait for last scanner pulse of experiment!...\n'); - - mriEnd = KbTriggerWait(p_keys_trigger,p.ptb.device); - putLog(mriEnd, 'mriTrigger'); - putLog(GetSecs, 'ExpEnd'); - end - -%% Present affective Picture - function Trial(itiDuration) %Trial(stimID,stimName,stimStrlOnset,itiDuration,itiStrlOnset,jitter) - - %cue - if p_presentation_stimSequence == 2 && nTrial == 2 || p_presentation_stimSequence == 2 && nTrial == 7 ||... - p_presentation_stimSequence == 4 && nTrial == 1 || p_presentation_stimSequence == 4 && nTrial == 6 - DrawFormattedText(p_ptb_w, 'Im nächsten Durchgang bewerten Sie bitte', 'center',p_ptb_startY-100, p_stim_white); - DrawFormattedText(p_ptb_w, 'die Schmerzhaftigkeit WÄHREND des Hitzereizes!', 'center',p_ptb_startY-70, p_stim_white); - end - - Screen('FillRect', p_ptb_w, p_stim_red, p.ptb.whiteFix1); - Screen('FillRect', p_ptb_w, p_stim_red, p.ptb.whiteFix2); - TimeCueOn = Screen('Flip',p_ptb_w); - putLog(TimeCueOn, 'CueOnset'); - p.log.reactionTime(nTrial) = getRT(p_presentation_CueDuration,TimeCueOn); % check reaction time during cue - if nTrial > 1 - if isnan(p.log.reactionTime(end)) && isnan(p.log.reactionTime(end-1)) - warning(sprintf('\n***********\n***********\nNo RT for 2 Trials!\nPlease check participant!!!\n***********\n***********\n')); - end - end - - %Pain - %online rating scale - if p_presentation_stimSequence == 2 && nTrial == 2 || p_presentation_stimSequence == 2 && nTrial == 7 ||... - p_presentation_stimSequence == 4 && nTrial == 1 || p_presentation_stimSequence == 4 && nTrial == 6 - TimeHeatOn = GetSecs; - putMark(p_com_lpt_HeatOnset); - fprintf('Heat on\n'); - p.log.PainOnset(nTrial) = TimeHeatOn - p.log.mriExpStartTime; - p.log.PainOnsetScan(nTrial) = (TimeHeatOn - p.log.mriExpStartTime)/p_mri_tr; - putLog(TimeHeatOn, 'HeatOnset'); - [p.onrating.conRating,p.onrating.conTime,p.onrating.response] = onlineScale(p_ptb_w,p_ptb_rect,... - p_presentation_stimDuration,p_stim_backgr,p_ptb_startY,p.keys,p.presentation.starTime); % - putOnRatingLog(nTrial); - - else % only showing cross during pain - Screen('FillRect', p_ptb_w, p_stim_red, p.ptb.whiteFix1); % no treatment condition - Screen('FillRect', p_ptb_w, p_stim_red, p.ptb.whiteFix2); - TimeHeatOn = Screen('Flip',p_ptb_w); - putMark(p_com_lpt_HeatOnset); - putLog(TimeHeatOn, 'HeatOnset'); - p.log.PainOnset(nTrial) = TimeHeatOn - p.log.mriExpStartTime; - p.log.PainOnsetScan(nTrial) = (TimeHeatOn - p.log.mriExpStartTime)/p_mri_tr; - fprintf('Heat on\n'); - while GetSecs < TimeHeatOn + (p_presentation_stimDuration/2.5) end % = WaitSecs(p_presentation_stimDuration); - %Show star for rating - Screen('TextSize',p_ptb_w,p.text.fontsize+40); - Screen('FillRect', p_ptb_w, p_stim_red, p.ptb.whiteFix1); % no treatment condition - Screen('FillRect', p_ptb_w, p_stim_red, p.ptb.whiteFix2); - Screen('DrawText', p_ptb_w,'*',p_ptb_midpoint(1)-12,p.ptb.startY-60,p_stim_white); - TimeStarOn = Screen('Flip',p_ptb_w); - putLog(TimeStarOn, 'StarOnset'); - fprintf('Star on\n'); - while GetSecs < TimeStarOn + p.presentation.starTime end - Screen('FillRect', p_ptb_w, p_stim_red, p.ptb.whiteFix1); % no treatment condition - Screen('FillRect', p_ptb_w, p_stim_red, p.ptb.whiteFix2); - TimeHeatOn = Screen('Flip',p_ptb_w); - - while GetSecs < TimeStarOn + (p_presentation_stimDuration - (p_presentation_stimDuration/2.5)) end % = WaitSecs(p_presentation_stimDuration); - end - - %blank screen - TimeBlankOn = Screen('Flip',p_ptb_w); - while GetSecs < TimeBlankOn + p_presentation_blankDuration end % = WaitSecs(p_presentation_blankDuration); - putLog(TimeBlankOn, 'BlankOnset'); - - %VAS T2 - putLog(GetSecs, 'VAS1Onset'); - putMark(p_com_lpt_VASOnset); - fprintf('VAS_T2 on\n'); - - [p.rating1.finalRating,p.rating1.reactionTime,p.rating1.response] = vasScaleT2(p_ptb_w,p_ptb_rect,... - p_presentation_scaleDuration,p.log.scaleDefaultVAS1(nTrial,1),p_stim_backgr,p_ptb_startY,p.keys); % - putRating1Log(nTrial); - p.log.Rating1(nTrial) = p.rating1.finalRating; - - %blank screen - TimeBlankOn = Screen('Flip',p_ptb_w); - while GetSecs < TimeBlankOn + p_presentation_blankDuration end % = WaitSecs(p_presentation_blankDuration); - putLog(TimeBlankOn, 'BlankOnset'); - - %VAS T3 - putLog(GetSecs, 'VAS2Onset'); - putMark(p_com_lpt_VASOnset); - fprintf('VAS_T3 on\n'); - - [p.rating2.finalRating,p.rating2.reactionTime,p.rating2.response] = vasScaleT3(p_ptb_w,p_ptb_rect,... - p_presentation_scaleDuration-2,p.log.scaleDefaultVAS2(nTrial,1),p_stim_backgr,p_ptb_startY,p.keys,p.rating1.finalRating); % - putRating2Log(nTrial); - p.log.Rating2(nTrial) = p.rating2.finalRating; - - %blank screen - TimeBlankOn = Screen('Flip',p_ptb_w); - while GetSecs < TimeBlankOn + p_presentation_blankDuration end % = WaitSecs(p_presentation_blankDuration); - putLog(TimeBlankOn, 'BlankOnset'); - - %Mood - putLog(GetSecs, 'MoodOnset'); - fprintf('Mood on\n'); - - [p.mood.finalRating,p.mood.reactionTime,p.mood.response] = moodScale(p_ptb_w,p_ptb_rect,... - p_presentation_scaleDuration-4,p.log.scaleDefaultMood(nTrial,1),p_stim_backgr,p_ptb_startY,p.keys); %p.log.scaleDefaultVAS(nTrial,1) - putMoodLog(nTrial); - p.log.MoodRating(nTrial) = p.mood.finalRating; - if nTrial > 1 - if p.log.MoodRating(end)+2 <= p.log.MoodRating(end-1) - warning(sprintf('\n***********\n***********\nParticipant rated 2 points less!\nPlease check participant!!!\n***********\n***********\n')); - end - end - - %Breath - Screen('TextSize',p_ptb_w,p.text.fontsize); - p_monitor_ny = p.monitor.Yaxis/4; - [p_monitor_nx, p_monitor_ny, textbounds]=DrawFormattedText(p_ptb_w, 'Bitte atmen Sie ruhig und gleichmäßig', 'center', p_monitor_ny, p_stim_white); - [p_monitor_nx, p_monitor_ny, textbounds]=DrawFormattedText(p_ptb_w, 'durch die Nase.', 'center', p_monitor_ny+p_ptb_lineheight, p_stim_white); - - fprintf('Breath Reminder\n'); - TimeBreathOn = Screen('Flip',p_ptb_w); - putLog(TimeBreathOn, 'BreathOnset'); - while GetSecs < TimeBreathOn + p.presentation.BreathRem end - - %ITI - p.presentation.durVAS(nTrial) = p.mood.reactionTime+p.rating1.reactionTime+p.rating2.reactionTime+(2*p_presentation_blankDuration); - p.presentation.itiDurationReal(nTrial) = (itiDuration + p.presentation.lastITI) - p.presentation.durVAS(nTrial); - - % if p.presentation.itiDurationReal(nTrial) > 0 - Screen('FillRect', p_ptb_w, p_stim_white, p.ptb.whiteFix1); - Screen('FillRect', p_ptb_w, p_stim_white, p.ptb.whiteFix2); - TimeCrossOn = Screen('Flip',p_ptb_w); - putMark(p_com_lpt_ITIOnset); - putLog(TimeCrossOn, 'ITIOnset'); - fprintf(['Remaining ITI duration: ' num2str(p.presentation.itiDurationReal(nTrial)) '\n']); - while GetSecs < (TimeCrossOn + p.presentation.itiDurationReal(nTrial)) end - % else - % Screen('FillRect', p_ptb_w, p_stim_white, p.ptb.whiteFix1); - % Screen('FillRect', p_ptb_w, p_stim_white, p.ptb.whiteFix2); - % TimeCrossOn = Screen('Flip',p_ptb_w); - % putLog(TimeCrossOn, 'ITIOnset'); - % putMark(p_com_lpt_ITIOnset); - % while GetSecs < TimeCrossOn + 5 end - % % fprintf('adding seconds to ITI to show breathing reminder\n'); - % % p.presentation.itiDurationReal(nTrial) = p.presentation.itiDurationReal(nTrial) + abs(p.presentation.itiDurationReal(nTrial) - p.presentation.BreathRem); - % end - % - save(p.path.save ,'p'); - end - -%% Instruction Text - function ShowInstruction - if run == 1 - p_monitor_ny = p.monitor.Yaxis/8; - [p_monitor_nx, p_monitor_ny, textbounds]=DrawFormattedText(p_ptb_w, 'Gleich beginnt das Experiment.', 'center', p_monitor_ny, p_stim_white); - [p_monitor_nx, p_monitor_ny, textbounds]=DrawFormattedText(p_ptb_w, 'Bleiben Sie die ganze Zeit so ruhig wie möglich liegen!', 'center', p_monitor_ny+p_ptb_lineheight, p_stim_white); - [p_monitor_nx, p_monitor_ny, textbounds]=DrawFormattedText(p_ptb_w, 'Haben Sie noch Fragen?', 'center', p_monitor_ny+p_ptb_lineheight, p_stim_white); - [p_monitor_nx, p_monitor_ny, textbounds]=DrawFormattedText(p_ptb_w, 'Sonst geht es jetz los!', 'center', p_monitor_ny+p_ptb_lineheight, p_stim_white); - else - [p_monitor_nx, p_monitor_ny, textbounds]=DrawFormattedText(p_ptb_w, 'Es geht gleich los...', 'center', p.ptb.startY, p_stim_white); - end - - introTextTime = Screen('Flip',p_ptb_w); - putLog(introTextTime,'IntroTextOn'); - WaitSecs(1); - - while 1 - [keyIsDown, ~, keyCode] = KbCheck(); % Start waiting 1/2 TR before JitterOnset for next pulse (this avoids collecting Pulses before). - if keyIsDown - if find(keyCode) == p_keys_nextStep; - break; - end - end - end - - StartWaitTime = Screen('Flip',p_ptb_w); - putLog(StartWaitTime, 'WaitForExpStartOnset'); - - fprintf('=================\n=================\nAsk if subject is alright\nThen tell MTA to start scanner!!!!!!!!...\n'); - fprintf('=================\n=================\nWill wait %d volumes for dummy...\n',p.mri.dummyScan); - end - -%% End session Text - function ShowEndSessionText - Screen('TextSize',p_ptb_w,p.text.fontsize); - if run == 8 - [p_monitor_nx, p_monitor_ny, textbounds]=DrawFormattedText(p_ptb_w, 'Das Experiment ist beendet.', 'center', p.ptb.start, p_stim_white); - [p_monitor_nx, p_monitor_ny, textbounds]=DrawFormattedText(p_ptb_w, 'Vielen Dank!', 'center', p_monitor_ny+p_ptb_lineheight, p_stim_white); - else - [p_monitor_nx, p_monitor_ny, textbounds]=DrawFormattedText(p_ptb_w, 'Ende des Durchgangs.', 'center', p.ptb.startY, p_stim_white); - [p_monitor_nx, p_monitor_ny, textbounds]=DrawFormattedText(p_ptb_w, 'Es geht gleich weiter!', 'center', p_monitor_ny+p_ptb_lineheight, p_stim_white); - end - - endTextTime = Screen('Flip',p_ptb_w); - putLog(endTextTime,'EndTextOn'); - - WaitSecs(1); - - while 1 - [keyIsDown, ~, keyCode] = KbCheck(); % Start waiting 1/2 TR before JitterOnset for next pulse (this avoids collecting Pulses before). - if keyIsDown - if find(keyCode) == p_keys_nextStep; - break; - end - end - end - end - -%% get reaction time - function reactionTime = getRT(durCue,startTime) - response = 0; - numberOfSecondsRemaining = durCue; - while numberOfSecondsRemaining > 0 - - if response == 0 - - [ keyIsDown, secs, keyCode ] = KbCheck; % this checks the keyboard very, very briefly. - if keyIsDown % only if a key was pressed we check which key it was - response = 0; % predefine variable for confirmation button 'space' - if keyCode(p.keys.confirm) - response = 1; - reactionTime = secs - startTime; - disp(['Reaction Time: ' num2str(reactionTime)]); - flip_confKey = GetSecs; - SecondsRemaining = durCue-(flip_confKey-startTime); - WaitSecs(SecondsRemaining); - break; - end - end - end - numberOfSecondsElapsed = (GetSecs - startTime); - numberOfSecondsRemaining = durCue - numberOfSecondsElapsed; - end - - if response == 0 - warning(sprintf('\n***********\n***********\nNo Response!\nPlease check participant!!!\n***********\n***********\n')); - reactionTime = NaN; - end - - end -%% Set Marker for CED and BrainVision Recorder - function putMark(port) - % Send pulse to CED for SCR, thermode, digitimer - % [handle, errmsg] = IOPort('OpenSerialport',num2str(port)); - outp(p_com_lpt_CEDaddress,port); - WaitSecs(p_com_lpt_CEDduration); - outp(p_com_lpt_CEDaddress,0); - % IOPort('CloseAll'); - end - -%% Log all events - function putLog(ptb_time, event_info) - p.log.eventCount = p.log.eventCount + 1; - p.log.events(p.log.eventCount,1) = {p.log.eventCount}; - p.log.events(p.log.eventCount,2) = {ptb_time}; - p.log.events(p.log.eventCount,3) = {ptb_time-p.log.mriExpStartTime}; - p.log.events(p.log.eventCount,4) = {event_info}; - end - function putOnRatingLog(currentTrial) - p.log.onratingEventCount = p.log.onratingEventCount + 1; - p.log.onratings.conTrial(p.log.onratingEventCount,1) = {currentTrial}; - p.log.onratings.conRating(:,p.log.onratingEventCount) = {p.onrating.conRating}; - p.log.onratings.conTime(:,p.log.onratingEventCount) = {p.onrating.conTime}; - p.log.onratings.conRes(p.log.onratingEventCount,1) = {p.onrating.response}; - end - function putRating1Log(currentTrial) - p.log.rating1EventCount = p.log.rating1EventCount + 1; - p.log.ratings1(p.log.rating1EventCount,1) = currentTrial; - p.log.ratings1(p.log.rating1EventCount,2) = p.rating1.finalRating; - p.log.ratings1(p.log.rating1EventCount,3) = p.rating1.response; - p.log.ratings1(p.log.rating1EventCount,4) = p.rating1.reactionTime; - end - - function putRating2Log(currentTrial) - p.log.rating2EventCount = p.log.rating2EventCount + 1; - p.log.ratings2(p.log.rating2EventCount,1) = currentTrial; - p.log.ratings2(p.log.rating2EventCount,2) = p.rating2.finalRating; - p.log.ratings2(p.log.rating2EventCount,3) = p.rating2.response; - p.log.ratings2(p.log.rating2EventCount,4) = p.rating2.reactionTime; - end - - function putMoodLog(currentTrial) - p.log.moodEventCount = p.log.moodEventCount + 1; - p.log.mood(p.log.moodEventCount,1) = currentTrial; - p.log.mood(p.log.moodEventCount,2) = p.mood.finalRating; - p.log.mood(p.log.moodEventCount,3) = p.mood.response; - p.log.mood(p.log.moodEventCount,4) = p.mood.reactionTime; - end - - function [finalRating,reactionTime,response,VASon,VASoff] = moodScale(window,windowRect,durRating,defaultRating,backgroundColor,StartY,keys) - - %% key settings - KbName('UnifyKeyNames'); - lessKey = keys.left; % yellow button - moreKey = keys.right; % red button - confirmKey = keys.confirm; % green button - escapeKey = keys.esc; - - if isempty(window); error('Please provide window pointer for likertScale!'); end - if isempty(windowRect); error('Please provide window rect for likertScale!'); end - if isempty(durRating); error('Duration length of rating has to be specified!'); end - - %% Default values - nRatingSteps = 7; - scaleWidth = 700; - textSize = 20; - lineWidth = 6; - scaleColor = [255 255 255]; - activeColor = [255 0 0]; - ticTextGap = 8; - tickHeight = 20; - ratingLabels = {'-3','-2','-1','0','1','2','3'}; - if isempty(defaultRating); defaultRating = round(nRatingSteps/2); end - if isempty(backgroundColor); backgroundColor = 0; end - - - %% Calculate rects - activeAddon_width = 0.6; - activeAddon_height = 20; - [xCenter, yCenter] = RectCenter(windowRect); - yCenter = StartY; - axesRect = [xCenter - scaleWidth/2; yCenter - lineWidth/2; xCenter + scaleWidth/2; yCenter + lineWidth/2]; - - % for j = 1:nRatingSteps - % Label(j,:) = round([axesRect(1)+((j-1)*scaleWidth/(nRatingSteps-1)),yCenter-20,axesRect(1)+((j-1)*scaleWidth/(nRatingSteps-1))+6,yCenter+20]); - % end - ticPositions = linspace(xCenter - scaleWidth/2,xCenter + scaleWidth/2-lineWidth,nRatingSteps); - activeTicRects = [ticPositions-activeAddon_width;ones(1,nRatingSteps)*yCenter-activeAddon_height;ticPositions + lineWidth+activeAddon_width;ones(1,nRatingSteps)*yCenter+activeAddon_height]; - ticRects = [ticPositions;ones(1,nRatingSteps)*yCenter;ticPositions + lineWidth;ones(1,nRatingSteps)*yCenter+tickHeight]; - - Screen('TextSize',window,textSize); - Screen('TextColor',window,[255 255 255]); - Screen('TextFont', window, 'Arial'); - currentRating = defaultRating; - finalRating = currentRating; - reactionTime = 0; - response = 0; - first_flip = 1; - startTime = GetSecs; - numberOfSecondsRemaining = durRating; - nrbuttonpresses = 0; - - %%%%%%%%%%%%%%%%%%%%%%% loop while there is time %%%%%%%%%%%%%%%%%%%%% - % tic; % control if timing is as long as durRating - while numberOfSecondsRemaining > 0 - loopTime = GetSecs; - Screen('FillRect',window,backgroundColor); - Screen('FillRect',window,scaleColor,axesRect); - - Screen('FillRect',window,scaleColor,activeTicRects) - for j = 1:nRatingSteps - textRect = Screen('TextBounds',window,ratingLabels{j}); - Screen('DrawText',window,ratingLabels{j},round(ticRects(1,j)-textRect(3)/2)+2,ticRects(4,j) + ticTextGap,scaleColor); - end - Screen('FillRect',window,scaleColor,activeTicRects) - Screen('FillRect',window,activeColor,activeTicRects(:,currentRating)); - - DrawFormattedText(window, 'Wie fühlen Sie sich gerade?', 'center',yCenter-100, scaleColor); - - Screen('DrawText',window,'sehr',axesRect(1)-17,yCenter+50,scaleColor); - Screen('DrawText',window,'schlecht',axesRect(1)-30,yCenter+70,scaleColor); - - Screen('DrawText',window,'sehr',axesRect(3)-25,yCenter+50,scaleColor); - Screen('DrawText',window,'gut',axesRect(3)-20,yCenter+70,scaleColor); - - - if response == 0 - - % set time 0 (for reaction time) - if first_flip == 1 - secs0 = Screen('Flip', window); % output Flip -> starttime rating - first_flip = 0; - % after 1st flip -> just flips without setting secs0 to null - else - Screen('Flip', window); - end - - - [ keyIsDown, secs, keyCode ] = KbCheck; % this checks the keyboard very, very briefly. - if keyIsDown % only if a key was pressed we check which key it was - response = 0; % predefine variable for confirmation button 'space' - nrbuttonpresses = nrbuttonpresses + 1; - if keyCode(moreKey) % if it was the key we named key1 at the top then... - currentRating = currentRating + 1; - finalRating = currentRating; - response = 0; - % disp(num2str(currentRating)); - if currentRating > nRatingSteps - currentRating = nRatingSteps; - end - - elseif keyCode(lessKey) - currentRating = currentRating - 1; - finalRating = currentRating; - response = 0; - % disp(num2str(currentRating)); - if currentRating < 1 - currentRating = 1; - end - - elseif keyCode(escapeKey) - reactionTime = 99; % to differentiate between ESCAPE and timeout in logfile - VASoff = GetSecs-StartExp; - disp('***********'); - disp('Abgebrochen'); - disp('***********'); - break; - elseif keyCode(confirmKey) - finalRating = currentRating-4; - disp(['Mood Rating: ' num2str(finalRating)]); - if finalRating < 0 - warning(sprintf('\n***********\n***********\nParticipant does not feel good!\nPlease check participant!!!\n***********\n***********\n')); - end - response = 1; - reactionTime = secs - secs0; - - - Screen('FillRect', window, backgroundColor, windowRect); - Screen('Flip', window); - % flip_confKey = GetSecs; VASoff = GetSecs-StartExp; - % numberOfSecondsRemaining_sharp = durRating-(flip_confKey-startTime); - % WaitSecs(numberOfSecondsRemaining_sharp); - break; - end - WaitSecs(0.15); - disp(currentRating);disp(finalRating); - end - end - - numberOfSecondsElapsed = (GetSecs - startTime); - numberOfSecondsRemaining = durRating - numberOfSecondsElapsed; - - % if (GetSecs - loopTime) < 0.3 - % disp(GetSecs - loopTime); - % WaitSecs(0.3 - loopTime); - % end - end - if nrbuttonpresses ~= 0 && response == 0 - finalRating = currentRating - 4; - reactionTime = durRating; - disp(['Mood Rating: ' num2str(finalRating)]); - warning(sprintf('\n***********\n***********\nNo Confirmation!!!\n***********\n***********\n')); - elseif nrbuttonpresses == 0 - finalRating = NaN; - reactionTime = durRating; - disp(['Mood Rating: ' num2str(finalRating)]); - warning(sprintf('\n***********\n***********\nNo Response!\nPlease check participant!!!\n***********\n***********\n')); - end - end -%% T2 Rating - function [finalRating,reactionTime,response] = vasScaleT2(window,windowRect,durRating,defaultRating,backgroundColor,StartY,keys) - - % key settings - KbName('UnifyKeyNames'); - lessKey = keys.left; % yellow button - moreKey = keys.right; % red button - confirmKey = keys.confirm; % green button - escapeKey = keys.esc; - - if isempty(window); error('Please provide window pointer for likertScale!'); end - if isempty(windowRect); error('Please provide window rect for likertScale!'); end - if isempty(durRating); error('Duration length of rating has to be specified!'); end - - % Default values - nRatingSteps = 101; - scaleWidth = 700; - textSize = 20; - lineWidth = 6; - scaleColor = [255 255 255]; - activeColor = [255 0 0]; - - if isempty(defaultRating); defaultRating = round(nRatingSteps/2); end - if isempty(backgroundColor); backgroundColor = 0; end - - % if length(ratingLabels) ~= nRatingSteps - % error('Rating steps and label numbers do not match') - % end - - %% Calculate rects - activeAddon_width = 1.5; - activeAddon_height = 20; - [xCenter, yCenter] = RectCenter(windowRect); - yCenter = StartY; - axesRect = [xCenter - scaleWidth/2; yCenter - lineWidth/2; xCenter + scaleWidth/2; yCenter + lineWidth/2]; - lowLabelRect = [axesRect(1),yCenter-20,axesRect(1)+6,yCenter+20]; - highLabelRect = [axesRect(3)-6,yCenter-20,axesRect(3),yCenter+20]; - ticPositions = linspace(xCenter - scaleWidth/2,xCenter + scaleWidth/2-lineWidth,nRatingSteps); - % ticRects = [ticPositions;ones(1,nRatingSteps)*yCenter;ticPositions + lineWidth;ones(1,nRatingSteps)*yCenter+tickHeight]; - activeTicRects = [ticPositions-activeAddon_width;ones(1,nRatingSteps)*yCenter-activeAddon_height;ticPositions + lineWidth+activeAddon_width;ones(1,nRatingSteps)*yCenter+activeAddon_height]; - % keyboard - - - Screen('TextSize',window,textSize); - Screen('TextColor',window,[255 255 255]); - Screen('TextFont', window, 'Arial'); - currentRating = defaultRating; - finalRating = currentRating; - reactionTime = 0; - response = 0; - first_flip = 1; - startTime = GetSecs; - numberOfSecondsRemaining = durRating; - nrbuttonpresses = 0; - - - %%%%%%%%%%%%%%%%%%%%%%% loop while there is time %%%%%%%%%%%%%%%%%%%%% - % tic; % control if timing is as long as durRating - while numberOfSecondsRemaining > 0 - Screen('FillRect',window,backgroundColor); - Screen('FillRect',window,scaleColor,axesRect); - Screen('FillRect',window,scaleColor,lowLabelRect); - Screen('FillRect',window,scaleColor,highLabelRect); - Screen('FillRect',window,activeColor,activeTicRects(:,currentRating)); - - DrawFormattedText(window, 'Bitte bewerten Sie die Schmerzhaftigkeit', 'center',yCenter-100, scaleColor); - DrawFormattedText(window, ' VOR dem Sternchen', 'center',yCenter-70, scaleColor); - - Screen('DrawText',window,'kein',axesRect(1)-17,yCenter+25,scaleColor); - Screen('DrawText',window,'Schmerz',axesRect(1)-40,yCenter+45,scaleColor); - - Screen('DrawText',window,'unerträglicher',axesRect(3)-55,yCenter+25,scaleColor); - Screen('DrawText',window,'Schmerz',axesRect(3)-40,yCenter+45,scaleColor); - - - - % Remove this line if a continuous key press should result in a continuous change of the scale - % while KbCheck; end - - if response == 0 - - % set time 0 (for reaction time) - if first_flip == 1 - secs0 = Screen('Flip', window); % output Flip -> starttime rating - first_flip = 0; - % after 1st flip -> just flips without setting secs0 to null - else - Screen('Flip', window); - end - - [ keyIsDown, secs, keyCode ] = KbCheck; % this checks the keyboard very, very briefly. - if keyIsDown % only if a key was pressed we check which key it was - response = 0; % predefine variable for confirmation button 'space' - nrbuttonpresses = nrbuttonpresses + 1; - if keyCode(moreKey) % if it was the key we named key1 at the top then... - currentRating = currentRating + 1; - finalRating = currentRating; - response = 0; - if currentRating > nRatingSteps - currentRating = nRatingSteps; - end - elseif keyCode(lessKey) - currentRating = currentRating - 1; - finalRating = currentRating; - response = 0; - if currentRating < 1 - currentRating = 1; - end - elseif keyCode(escapeKey) - reactionTime = 99; % to differentiate between ESCAPE and timeout in logfile - VASoff = GetSecs-StartExp; - disp('***********'); - disp('Abgebrochen'); - disp('***********'); - break; - elseif keyCode(confirmKey) - finalRating = currentRating-1; - disp(['VAS Rating: ' num2str(finalRating)]); - response = 1; - reactionTime = secs - secs0; - break; - end - end - end - - numberOfSecondsElapsed = (GetSecs - startTime); - numberOfSecondsRemaining = durRating - numberOfSecondsElapsed; - - end - if nrbuttonpresses ~= 0 && response == 0 - finalRating = currentRating - 1; - reactionTime = durRating; - disp(['VAS Rating: ' num2str(finalRating)]); - warning(sprintf('\n***********\n***********\nNo Confirmation!!!\n***********\n***********\n')); - elseif nrbuttonpresses == 0 - finalRating = NaN; - reactionTime = durRating; - disp(['VAS Rating: ' num2str(finalRating)]); - warning(sprintf('\n***********\n***********\nNo Response!\nPlease check participant!!!\n***********\n***********\n')); - end - end -%%T3 Rating - function [finalRating,reactionTime,response] = vasScaleT3(window,windowRect,durRating,defaultRating,backgroundColor,StartY,keys,prevRating) - - %% key settings - KbName('UnifyKeyNames'); - lessKey = keys.left; % yellow button - moreKey = keys.right; % red button - confirmKey = keys.confirm; % green button - escapeKey = keys.esc; - - if isempty(window); error('Please provide window pointer for likertScale!'); end - if isempty(windowRect); error('Please provide window rect for likertScale!'); end - if isempty(durRating); error('Duration length of rating has to be specified!'); end - - %% Default values - nRatingSteps = 101; - scaleWidth = 700; - textSize = 20; - lineWidth = 6; - scaleColor = [255 255 255]; - prevColor = [255 128 128]; - activeColor = [255 0 0]; - if isempty(defaultRating); defaultRating = round(nRatingSteps/2); end - if isempty(backgroundColor); backgroundColor = 0; end - - % if length(ratingLabels) ~= nRatingSteps - % error('Rating steps and label numbers do not match') - % end - - %% Calculate rects - activeAddon_width = 1.5; - activeAddon_height = 20; - [xCenter, yCenter] = RectCenter(windowRect); - yCenter = StartY; - axesRect = [xCenter - scaleWidth/2; yCenter - lineWidth/2; xCenter + scaleWidth/2; yCenter + lineWidth/2]; - lowLabelRect = [axesRect(1),yCenter-20,axesRect(1)+6,yCenter+20]; - highLabelRect = [axesRect(3)-6,yCenter-20,axesRect(3),yCenter+20]; - ticPositions = linspace(xCenter - scaleWidth/2,xCenter + scaleWidth/2-lineWidth,nRatingSteps); - % ticRects = [ticPositions;ones(1,nRatingSteps)*yCenter;ticPositions + lineWidth;ones(1,nRatingSteps)*yCenter+tickHeight]; - activeTicRects = [ticPositions-activeAddon_width;ones(1,nRatingSteps)*yCenter-activeAddon_height;ticPositions + lineWidth+activeAddon_width;ones(1,nRatingSteps)*yCenter+activeAddon_height]; - % keyboard - - if isnan(prevRating) - prevRating = 0; - end - - Screen('TextSize',window,textSize); - Screen('TextColor',window,[255 255 255]); - Screen('TextFont', window, 'Arial'); - currentRating = defaultRating; - finalRating = currentRating; - reactionTime = 0; - response = 0; - first_flip = 1; - startTime = GetSecs; - numberOfSecondsRemaining = durRating; - nrbuttonpresses = 0; - - %%%%%%%%%%%%%%%%%%%%%%% loop while there is time %%%%%%%%%%%%%%%%%%%%% - % tic; % control if timing is as long as durRating - while numberOfSecondsRemaining > 0 - Screen('FillRect',window,backgroundColor); - Screen('FillRect',window,scaleColor,axesRect); - Screen('FillRect',window,scaleColor,lowLabelRect); - Screen('FillRect',window,scaleColor,highLabelRect); - Screen('FillRect',window,prevColor,activeTicRects(:,prevRating+1)); - Screen('FillRect',window,activeColor,activeTicRects(:,currentRating)); - - DrawFormattedText(window, 'Bitte bewerten Sie die Schmerzhaftigkeit', 'center',yCenter-100, scaleColor); - DrawFormattedText(window, 'NACH dem Sternchen', 'center',yCenter-70, scaleColor); - - Screen('DrawText',window,'kein',axesRect(1)-17,yCenter+25,scaleColor); - Screen('DrawText',window,'Schmerz',axesRect(1)-40,yCenter+45,scaleColor); - - Screen('DrawText',window,'unerträglicher',axesRect(3)-55,yCenter+25,scaleColor); - Screen('DrawText',window,'Schmerz',axesRect(3)-40,yCenter+45,scaleColor); - - - - % Remove this line if a continuous key press should result in a continuous change of the scale - % while KbCheck; end - - if response == 0 - - % set time 0 (for reaction time) - if first_flip == 1 - secs0 = Screen('Flip', window); % output Flip -> starttime rating - first_flip = 0; - % after 1st flip -> just flips without setting secs0 to null - else - Screen('Flip', window); - end - - [ keyIsDown, secs, keyCode ] = KbCheck; % this checks the keyboard very, very briefly. - if keyIsDown % only if a key was pressed we check which key it was - response = 0; % predefine variable for confirmation button 'space' - nrbuttonpresses = nrbuttonpresses + 1; - if keyCode(moreKey) % if it was the key we named key1 at the top then... - currentRating = currentRating + 1; - finalRating = currentRating; - response = 0; - if currentRating > nRatingSteps - currentRating = nRatingSteps; - end - elseif keyCode(lessKey) - currentRating = currentRating - 1; - finalRating = currentRating; - response = 0; - if currentRating < 1 - currentRating = 1; - end - elseif keyCode(escapeKey) - reactionTime = 99; % to differentiate between ESCAPE and timeout in logfile - VASoff = GetSecs-StartExp; - disp('***********'); - disp('Abgebrochen'); - disp('***********'); - break; - elseif keyCode(confirmKey) - finalRating = currentRating-1; - disp(['VAS Rating: ' num2str(finalRating)]); - response = 1; - reactionTime = secs - secs0; - break; - end - end - end - - numberOfSecondsElapsed = (GetSecs - startTime); - numberOfSecondsRemaining = durRating - numberOfSecondsElapsed; - - end - % WaitSecs(0.3); - if nrbuttonpresses ~= 0 && response == 0 - finalRating = currentRating - 1; - reactionTime = durRating; - disp(['VAS Rating: ' num2str(finalRating)]); - warning(sprintf('\n***********\n***********\nNo Confirmation!!!\n***********\n***********\n')); - elseif nrbuttonpresses == 0 - finalRating = NaN; - reactionTime = durRating; - disp(['VAS Rating: ' num2str(finalRating)]); - warning(sprintf('\n***********\n***********\nNo Response!\nPlease check participant!!!\n***********\n***********\n')); - end - end -%%online rating - function [conRating,conTime,response] = onlineScale(window,windowRect,durRating,backgroundColor,StartY,keys,starTime) - - %% key settings - KbName('UnifyKeyNames'); - lessKey = keys.left; % yellow button - moreKey = keys.right; % red button - escapeKey = keys.nextStep; - - if isempty(window); error('Please provide window pointer for likertScale!'); end - if isempty(windowRect); error('Please provide window rect for likertScale!'); end - if isempty(durRating); error('Duration length of rating has to be specified!'); end - - %% Default values - nRatingSteps = 101; - scaleWidth = 700; - textSize = 20; - lineWidth = 6; - scaleColor = [255 255 255]; - activeColor = [255 0 0]; - defaultRating = 1; - if isempty(backgroundColor); backgroundColor = 0; end - if isempty(starTime); starTime = 0; end - - % if length(ratingLabels) ~= nRatingSteps - % error('Rating steps and label numbers do not match') - % end - - %% Calculate rects - activeAddon_width = 1.5; - activeAddon_height = 20; - [xCenter, yCenter] = RectCenter(windowRect); - yCenter = StartY; - axesRect = [xCenter - scaleWidth/2; yCenter - lineWidth/2; xCenter + scaleWidth/2; yCenter + lineWidth/2]; - lowLabelRect = [axesRect(1),yCenter-20,axesRect(1)+6,yCenter+20]; - highLabelRect = [axesRect(3)-6,yCenter-20,axesRect(3),yCenter+20]; - midLabelRect = [xCenter-3,yCenter-20,xCenter+3,yCenter+20]; - midlLabelRect = [xCenter-3-scaleWidth/4,yCenter-20,xCenter+3-scaleWidth/4,yCenter+20]; - midhLabelRect = [xCenter-3+ scaleWidth/4,yCenter-20,xCenter+3+scaleWidth/4,yCenter+20]; - ticPositions = linspace(xCenter - scaleWidth/2,xCenter + scaleWidth/2-lineWidth,nRatingSteps); - activeTicRects = [ticPositions-activeAddon_width;ones(1,nRatingSteps)*yCenter-activeAddon_height;ticPositions + lineWidth+activeAddon_width;ones(1,nRatingSteps)*yCenter+activeAddon_height]; - - Screen('TextSize',window,textSize); - Screen('TextColor',window,[255 255 255]); - Screen('TextFont', window, 'Arial'); - currentRating = defaultRating; - finalRating = currentRating; - response = 0; - - numberOfSecondsRemaining = durRating; - conRating = 0; - conTime = 0; - - - %%%%%%%%%%%%%%%%%%%%%%% loop while there is time %%%%%%%%%%%%%%%%%%%%% - % tic; % control if timing is as long as durRating - - startTime = GetSecs; - while numberOfSecondsRemaining > 0 - - Screen('FillRect',window,backgroundColor); - Screen('FillRect',window,activeColor,[activeTicRects(1,1)+3 activeTicRects(2,1)+ 5 activeTicRects(3,currentRating)-3 activeTicRects(4,1)-5]); - Screen('FillRect',window,scaleColor,lowLabelRect); - Screen('FillRect',window,scaleColor,highLabelRect); - Screen('FillRect',window,scaleColor,midLabelRect); - Screen('FillRect',window,scaleColor,midlLabelRect); - Screen('FillRect',window,scaleColor,midhLabelRect); - - % DrawFormattedText(window, 'Bitte bewerten Sie die Schmerzhaftigkeit', 'center',yCenter-100, scaleColor); - % DrawFormattedText(window, 'des Hitzereizes', 'center',yCenter-70, scaleColor); - - Screen('DrawText',window,'kein',axesRect(1)-17,yCenter+25,scaleColor); - Screen('DrawText',window,'Schmerz',axesRect(1)-40,yCenter+45,scaleColor); - - Screen('DrawText',window,'unerträglicher',axesRect(3)-55,yCenter+25,scaleColor); - Screen('DrawText',window,'Schmerz',axesRect(3)-40,yCenter+45,scaleColor); - - if (numberOfSecondsRemaining <= (durRating - (durRating/2.5) + 0.01)) && (numberOfSecondsRemaining >= (durRating - (durRating/2.5)- starTime - 0.01)) - % disp(GetSecs-startTime); - Screen('TextSize',window,70); - Screen('DrawText',window,'*',xCenter-12,yCenter-70,scaleColor); - end - Screen('Flip', window); - Screen('TextSize',window,textSize); - - [keyIsDown,secs,keyCode] = KbCheck; % this checks the keyboard very, very briefly. - - if keyIsDown % only if a key was pressed we check which key it was - response = 1; - if keyCode(moreKey) % if it was the key we named key1 at the top then... - currentRating = currentRating + 1; - if currentRating > nRatingSteps - currentRating = nRatingSteps; - end - finalRating = currentRating - 1; - conRating(end+1) = finalRating; - conTime(end+1) = GetSecs - startTime; - elseif keyCode(lessKey) - currentRating = currentRating - 1; - if currentRating < 1 - currentRating = 1; - end - finalRating = currentRating - 1; - conRating(end+1) = finalRating; - conTime(end+1) = GetSecs - startTime; - % elseif keyCode(escapeKey) - % disp(['Middle Pain: ' num2str(GetSecs - startTime)]); - end - end - - conRating(end+1) = finalRating; - conTime(end+1) = GetSecs - startTime; - - numberOfSecondsElapsed = (GetSecs - startTime); - numberOfSecondsRemaining = durRating - numberOfSecondsElapsed; - - end - % figure;plot(conTime,conRating); - - end -%% After experiment is over clean everything and close drivers - function cleanup - sca; % Close window: - commandwindow; - ListenChar(0); % Use keys again - %KbQueueRelease(p_ptb_device); - save(p.path.save ,'p'); - if run == 4 - diary off; - end - end - - -end - - - - - diff --git a/retino_ring_sequence.mat b/retino_ring_sequence.mat new file mode 100644 index 0000000..254c360 Binary files /dev/null and b/retino_ring_sequence.mat differ diff --git a/retino_sequence.mat b/retino_sequence.mat new file mode 100644 index 0000000..2c160b3 Binary files /dev/null and b/retino_sequence.mat differ diff --git a/sample_lumiances.fig b/sample_lumiances.fig new file mode 100644 index 0000000..31788d1 Binary files /dev/null and b/sample_lumiances.fig differ diff --git a/sample_luminances.mat b/sample_luminances.mat new file mode 100644 index 0000000..d9765f2 Binary files /dev/null and b/sample_luminances.mat differ diff --git a/sample_test.edf b/sample_test.edf new file mode 100644 index 0000000..60573e3 Binary files /dev/null and b/sample_test.edf differ diff --git a/seq_BalancedDist.m b/seq_BalancedDist.m deleted file mode 100644 index 00941f6..0000000 --- a/seq_BalancedDist.m +++ /dev/null @@ -1,64 +0,0 @@ -function [final]=seq_BalancedDist(stim_seq , Categories) -%Distributes values in CATEGORIES, in -%a balanced way to the stimulus sequence so that levels given in -%CATEGORIES are distributed in such a way that they are equally -%present in stimulus vector. -%CATEGORY is the thing that we want to distribute to the stimulus -%sequence in a balanced way. For example cross positions - - -tCategory = length(Categories);%number of categories to be distributed -tSample = length(stim_seq);%number of total trials -tcond = length(unique(stim_seq));%number of stimulus conditions -% -%Category_index = Shuffle(1:tCategory,tCategory)'; -% |-----tRepet----| * tCond -%[1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 ...]%stimulus id (STIM_SEQ) -%[A A A B B B C C C A A A B B B C C C ...]%categories (SEQ2) -% |----SEQ--------| * tCategory - -%Get SEQ -seq2 = []; -for cond = unique(stim_seq) - %number of times each condition is repeated. - tRepet = sum(stim_seq == cond); - seq = []; - for categorie = Categories - seq = [ seq repmat(categorie, 1, floor(tRepet./tCategory)) ]; - end - - %will add NaN's to the unbalanceable indices. - if rem(tRepet,tCategory) ~= 0 - fprintf('Cannot deal perfectly, will try best...\n'); - fillup = tRepet - length(seq); - seq = [ seq NaN(1,fillup) ]; - end - % - seq2 = [seq2 Shuffle(seq)]; -end - -%randomly fill the unbalancable trials. Would be just the perfect location -%to make a recursive function here. -if sum(isnan(seq2)) ~= 0; - nani = find(isnan(seq2)); - seq2(nani) = randsample(Categories,length(nani),true); -end -% -%order the stimulus and -[~, i] = sort(stim_seq); -%use the ordering index to align the SEQ variable -final = []; -final(i) = seq2; - - function shuffled = Shuffle(vector,N) - %takes first N from the SHUFFLED before outputting. This function - %could be used as a replacement for randsample - if nargin < 2;N = length(vector);end - [dummy, idx] = sort(rand([1 length(vector)])); - shuffled = vector(idx(1:N)); - shuffled = shuffled(:)'; - end -end - - - diff --git a/seq_FirstOrderBalanced.m b/seq_FirstOrderBalanced.m deleted file mode 100644 index e1dc45d..0000000 --- a/seq_FirstOrderBalanced.m +++ /dev/null @@ -1,15 +0,0 @@ -function s = seq_FirstOrderBalanced(ttrial, p) -%s = seq_FirstOrderBalanced(p) -% -% Generates a random sequence which follows the probability of occurances -% in P. P can be of any size. P must sum to 1. - -if sum(p) ~= 1 - - p = round(p*100); - -else - fprintf('P must sum to one, now it is %g.\n', sum(p)); - -end - diff --git a/seq_RunDesignEfficiency.m b/seq_RunDesignEfficiency.m deleted file mode 100755 index 582f484..0000000 --- a/seq_RunDesignEfficiency.m +++ /dev/null @@ -1,89 +0,0 @@ -function [E,power]=seq_RunDesignEfficiency -%[E,power]=seq_RunDesignEfficiency -% -% -% Tests the efficiency of different experimental designs made of different -% presentation possibilites. Uses spm machinery to generate, convolve and -% produce design matrices. Works with spm_hrf, so not yet adapted to irf -% of other modalities such as scr. POWER is the average power spectra of -% different methods specified in INPUTS. -% -% Dependency: seq_feargen_eyelab, spm_Volterra, spm_get_bf, -% spm_get_onsets. -tseq = 10;%how many to test -sampling_rate = 2; -% IRF -TR = sampling_rate;%in seconds -fMRI_T = 16;%spm_get_defaults('stats.fmri_t'); -fMRI_T0 = 1;%spm_get_defaults('stats.fmri.t0');in spm8 it was 1, so I am keeping it here -xBF.T = fMRI_T; -xBF.T0 = fMRI_T0; -xBF.dt = TR/xBF.T; -xBF.UNITS = 'scans'; -xBF.Volterra = 1; -xBF.name = 'hrf'; -xBF = spm_get_bf(xBF); -%% IRF power -%% fft -fft_N = 2048*4; -power.freq = 1/fft_N*[1:fft_N/2-1]; -irf_f = fft(xBF.bf,fft_N); -irf_f = abs(irf_f).^2; -ind = 2:ceil(1+length(irf_f)/2)-1; -power.irf = irf_f(ind); -%% function to test -dummy = {}; -seq_gen = @(dummy) seq_feargen_eyelab(dummy{:});%function to generate sequences -%inputs to the sequencer -inputs = {{'b' 1 'quasiuniform' [2 3 4 5]} {'b' 1 'random' [2 3 4 5] } {'b' 1 'exponential' [2 3 4 5]} ... - {'b' 1 'quasiuniform' [2 4 6] } {'b' 1 'random' [2 4 6]} {'b' 1 'exponential' [2 4 6]}}; -t_input = length(inputs); -E = nan(tseq,t_input); -%% make the simulation -c_input = 0; -for input = inputs; - c_input = c_input + 1; - dummy = seq_gen(input{1});%a dummy sequence - cums = cumsum(dummy.isi); - %% The constant part for the spm_function that will generate the DM - Sess = []; - for nt = 1:length(unique(dummy.cond_id)); - Sess.U(nt).dt = xBF.dt;%- time bin (seconds) - Sess.U(nt).name = {sprintf('%02d',nt)};%- cell of names for each input or cause - %no parametric modulation here - Sess.U(nt).dur = 0;%- durations (in SPM.xBF.UNITS) - Sess.U(nt).P.name = 'none'; - Sess.U(nt).P.P = 'none'; - Sess.U(nt).P.h = 0;%- order of polynomial expansion - Sess.U(nt).P.i = 1;%- sub-indices of u pertaining to P - end - SPM.xBF = xBF; - SPM.nscan = max(cums)+5; - SPM.Sess = Sess; - %% load the sequences - nseq = 0; - dummy = zeros(length(ind),1); - while nseq <= tseq - fprintf('\tRUN: %03d, SEQUENCE %03d of %03d...\n',c_input,nseq,tseq); - nseq = nseq + 1; - seq = seq_gen(input{1}); - cums = cumsum(seq.isi); - %% get the onsets - for i = 1:length(unique(seq.cond_id));%one regressor for each condition - SPM.Sess.U(i).ons = cums( seq.cond_id == i );%- onsets (in SPM.xBF.UNITS) - end - SPM.Sess.U = spm_get_ons(SPM,1); - %% - % Convolve stimulus functions with basis functions - [X,~,~] = spm_Volterra(SPM.Sess.U,SPM.xBF.bf,SPM.xBF.Volterra); - % Resample regressors at acquisition times (32 bin offset) - X = X((0:(SPM.nscan - 1))*fMRI_T + fMRI_T0 + 32,:); - X = reshape(zscore(X(:)),size(X)); - % efficiency(nseq) =1./trace(Con*inv(X'*X)*Con'); - E(nseq,c_input) = 1./trace(inv(X'*X)); - %% Compute also the power spectrum of the X*[1..1]' - Xf = 2*abs(fft(mean(X,2),fft_N).^2); - dummy = dummy + Xf(ind)./tseq; - end - power.y(:,c_input) = dummy; -end diff --git a/seq_SecondOrderBalancedSequence.m b/seq_SecondOrderBalancedSequence.m deleted file mode 100755 index 961cacd..0000000 --- a/seq_SecondOrderBalancedSequence.m +++ /dev/null @@ -1,160 +0,0 @@ -function [S,i]=SecondOrderBalancedSequence(repetition,start_condition) -%[S,i]=SecondOrderBalancedSequence(tItem,repetition,start_condition) -% -% Generates a so-called t1r1 sequence, see Aguirre for fMRI applications. -% These sequences are balanced for second-order transitions. -% The length of repetition determines the number of conditions, and each -% value in the repetition vector determines how many times a given -% transition occurs. For example, a vector [5 5 5 1] means that the -% sequence contains 5 transitions between conditions 1 to 3 and only 1 -% transition to the 4th condition. -% -% Note that the total number of elements in the sequence will be -% TITEM*REPETITION+1, the +1 is needed to make all transitions -% possible. This additional trial can be used as a dummy trial. -% START_CONDITION indicates the starting condition of the -% sequence. -% -% If REPETITION is a matrix, it is considered as a transition matrix as -% such. Thus arbitrary shaped transition matrices can be used, please -% note that not all transition matrices will converge to a solution. -% -% I returns the position of a given transition in the sequence S. For -% example squeeze(i(1,1,:)) would return the position of the 1 to 1 -% transition in S. The index is for the first element of the transition. -% -% Example Usage: -% as a vector: -% [S,i]=SecondOrderBalancedSequence(ones(1,8)*34,1) -% as a matrice: -% m = [1 2 1 2 1;2 1 2 1 2;1 2 1 2 1; 2 1 2 1 2;1 2 1 2 1];; -% [S,i]=SecondOrderBalancedSequence(m,1); -% - -%% -%T=ones(tItem,tItem) .* repetition;%the old way, equal number of trials -%for each condition... -%new way: -if isvector(repetition); - c = 0; - T = []; - repetition = repetition(:)'; - for x_ = repetition(end:-1:1) - c = c+1; - T(1:length(repetition)-c+1,1:length(repetition)-c+1) = x_; - end -else - fprintf('Matrix given, will treat the 2nd argument as count matrix.\n'); - T = repetition; -end -%% check whether the count matrix is valid. - if sum(sum(abs(T - round(T)) == 0)) ~= length(T(:)) - S=[]; - fprintf('The repetition vector should consists of integers\n'); - return - end -Tori = T; -%% -success = 0; -while ~success%when T sums to 0 - % - T = Tori; - row = ceil(start_condition);%the first stimulus. - col = randsample(find(T(row,:)),1);%ceil(rand*tItem);%the second stimulus. - S = [row col]; - ok = 1; - counter = 0; - while ok%it is OK when next stim is correctly selected - %store the location of the transition on the sequence - counter = counter + 1; - i(row,col,T(row,col)) = counter; - - %decrement this value - T(row,col)=T(row,col)-1; - - row=col;%second stimulus becomes the first - col=[];%we have to select the new second one now - col_pool=find(T(row,:)); - if isempty(col_pool)%no more transition possible - ok=0; - else - %pick one of the possible transitions - %This is the old way, this generates problems when one of the - %conditions has significantly less repetitions, it results in - %those conditions with too few repetitions to cluster at the - %very beginning of the stimulus sequence: - %next_stim = ceil(rand*length(col_pool)); - %the new methods weights the selection process accroding to the - %proportion of time a condition is repeated. - %T(row,col_pool) represents the probabilities - next_stim = SyntFix_Core(Tori(row,col_pool),1); - col = col_pool(next_stim); - S = [S col]; - end - - end - - if sum(T(:))==0 - success=1; - %remove the zeros due to unequal transition numbers - i(i == 0) =NaN; - end -end - - - -% % -% % fprintf('Checking balancing...\n') -% % [n c] = hist3([S(1:end-1) ;S(2:end)]',{1:tItem 1:tItem}); -% % imagesc(n);colorbar;drawnow; -% % for i = 1:tItem;co(i) = sum(S == i);end; -% % if ~(sum(n(:) == repetition) == tItem.^2); -% % fprintf('Sequence unbalanced!!!...\n') -% % keyboard -% % % S = []; -% % else -% % fprintf('Sequence is balanced...\n') -% % end -% % fprintf('first order histogram:\n') -% % mat2str(co) -% % fprintf('second order balancing:\n'); -% % display(n) - - function [i] = SyntFix_Core(saliency,tfix); - %[i] = SyntFix_Core(s,tfix); - % - %Given a matrix SALIENCY representing a topographic saliency, this function - %simulates fixation locations of TFIX fixations. SALIENCY may be a fixation - %map, a data-driven saliency map or a click map or any other matrix of 2D. - % - % - %Selim, 31-Jan-2008 20:09:22 - - - - %fixation init - i = zeros(tfix,1); - %%!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - %%the reason for 0.66: it makes the (oddball + ucs) probabilities - %across time as flat as possible over time; - %!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - s = cumsum(saliency(:).^(0.66)); - s = [ 0 ; s]; - %we need to add one zero entry to the cumulatif sum, otherwise there is no - %possibility that the first pixel is ever selected whatever its saliency - %is. another intuitive reason is that cumsum eats one of the entries - %therefore possible fixatable position decreases by one. - % - %random points. - r = rand(1,tfix)*max(s); - %for each of the random points now we find the spatial location it - %corresponds to... - for nf = 1:tfix - % - i(nf,1) = find( s-r(nf)<=0,1,'last'); - % - %we will take the last negative or zero entry in DUMMY; The index of - %this entry will be the location that is fixated... - end - end -end \ No newline at end of file diff --git a/seq_SecondOrderBalancedSequenceRunner.m b/seq_SecondOrderBalancedSequenceRunner.m deleted file mode 100755 index cc1a54d..0000000 --- a/seq_SecondOrderBalancedSequenceRunner.m +++ /dev/null @@ -1,28 +0,0 @@ -function [out]=SecondOrderBalancedSequenceRunner(total,repeatvector) -%[out]=SecondOrderBalancedSequenceRunner(total,repeatvector) -% -% will return TOTAL amount of second order balanced stimulus sequences/ -% Use these possibilities for RepetVector = {[4 4 4 4 4 4 4 4 1 1] [28 28 -% 2]} for test and conditioning phases. -% -% Selim Onat, 26-Apr-2013 12:47:55 - -%% -rng('shuffle');%shuffle the random generator to a different state. - -I = single(zeros(10,10,4,total)); -S = uint8(zeros(293,total)); - -matlabpool local 6; - -parfor ncount = 1:total - fprintf('%06d\n',ncount); - [s,i] = SecondOrderBalancedSequence( 10, repeatvector, randsample(1:8,1) ); - S(:,ncount) = uint8(s(:)); - I(:,:,:,ncount) = single(i); -end -% -out.S = S; -out.I = I; -out.repeatvector = repeatvector; -save(['~/tmp/BigPool_' GetHostName '.mat'],'out'); \ No newline at end of file diff --git a/seq_analysis.m b/seq_analysis.m deleted file mode 100644 index 6d1483e..0000000 --- a/seq_analysis.m +++ /dev/null @@ -1,66 +0,0 @@ -function seq_analysis(seq_index) -Q = 10;%number of conditions -max_ent = log2(Q+1); -orders = [1 2 3 4 5]; -rr = 0.5;%reiforcement rating -rep_vec = [ones(1,9)*2 1 1]; -ms = seq_SecondOrderBalancedSequence(rep_vec,1); -ttrial = length(ms); - -switch seq_index - case 1 - %% simple random sequence - ms = seq_SecondOrderBalancedSequence(rep_vec,1); - ms = Shuffle(ms-1); - %adapt to the paradigm - case 2 - %% msequence - ms = []; - for r = randsample(1:18,18); - [ms]=[ms ; mseq2(11,2,[],r)]; - end - ms = ms(1:ttrial); - ms(setdiff(find(ms == 10),randsample(find(ms == 10),1))) = []; - nucs = sum(ms == 4)*(rr./(1-rr)); - tucs = sum(ms == 9); - ms(randsample(find(ms == 9),tucs-nucs)) = []; - case 3 - %% What we planned for Lea's fear cloud exp (with null events as ISIs) - [seq] = seq_feargen_eyelab('tshort','constant',1); - ms = seq.cond_id; - case 4 - %% Kao's sequence - a = load('/Users/onat/Documents/Code/Matlab/ER-fMRI_toolbox_KaoMH/MO_design_562015-012.mat'); - ms = a.Out.bestList; - case 5 - %% optseq - [~,ms] = seq_optseq22dm('/Users/onat/Desktop/optseq/selim-001.par'); - ms = ms - 1; -end -plotit; - - function plotit - figure; - set(gcf,'position',[0 0 200 600]); - subplot(3,1,1) - plot(ms,'o-');title('sequence') - ent = []; - for order = orders; - [ent(order) ent0 entmax] = calcent(ms,order); - end - subplot(3,1,2) - bar([0 orders],2.^[ent0 ent]);hold on - plot(xlim,2.^[entmax entmax]);hold off; - title('entropies') - %% - e =[]; -% [e d] = calc_meffdet(ms,20); - [e d] = calc_meffdet(ms,10,max(ms)-1,3); - [tdetmat,teffmat,tmaxdet,tmaxeff] = tcurve(Q,10,length(ms)); - subplot(3,1,3) - bar(e(1));hold on; - plot(xlim,[tmaxeff tmaxeff]);hold off; - title(sprintf('efficiency: %03d',round(e(1)./tmaxeff*100))) - drawnow; - end -end \ No newline at end of file diff --git a/seq_fearamy.m b/seq_fearamy.m deleted file mode 100644 index 3321ae4..0000000 --- a/seq_fearamy.m +++ /dev/null @@ -1,132 +0,0 @@ -%we have three types of mesoblocks (3 microblocks) depending on where the -%UCS is occuring: in the first, second or third microblocks of a mesoblock. -% -%The matrix below indicates the distance between UCS microblocks for all -%possible transitions of mesoblocks. so for example the transition from -%mesoblock 3 to 1 results in two successive microblocks. -% t = [ 2 3 4;... -% 1 2 3;... -% 0 1 2]; -t = [ 3 4 5 6; 2 3 4 5; 1 2 3 4; 0 1 2 3] -%%now we will go select elements from this matrix in such a way to obtain a -%%sequence of mesoblocks which will be balanced in terms of transitions. -T = t; -store = []; -dstore = []; -n = 0; -ok = 1000; -tseq = 20; -% -while ok - % - %build a sequence by randomly walking on this matrix and cancelling the - %past steps so that they are not again stepped in - now = 4;%start with a mesoblock where UCS is last one; - seq = now; - distz = []; - for nseq = 1:tseq - T = t;%transition matrix that will be reduced again and again. - while any(~isnan(T(now,:))) - next = find(~isnan(T(now,:)));%next posibilities - next = RandSample(next,[1 1]);%select one - distanz = T(now,next); - T (T == distanz) = NaN;%cancel all transitions with this distance - seq = [seq next]; - distz = [distz distanz]; - now = next; - end - end - % - %well if the sequence has the proper length, this means we have - %succeeded without entering into an impasse. - if length(seq) == length(unique(t(:)))*tseq+1 - %if this is the first time a sequence is found - if isempty(store) - store = seq; - dstore = distz; - end - %don't store this sequence if we had it already. - if ~any(ismember(store,seq,'rows')) - ok = ok - 1; - store = [store ;seq]; - dstore = [dstore ;distz]; - fprintf('Found already %d sequences.\n',size(store,1)); - end - end -end -%% much simpler approach - -for nsub = 1:100; - for csp = 1:8; - cond_id = []; - mblock = []; - n_micro = 1; - n_meso = 0; - n_micro_ucs = 0; - n_micro_odd = 0; - - condpool = 0:8; - % - %all mesoblocks where second microblock is of type 1 and 18th microblock of type 4... - %these will be later set to oddball... - meso_i = find(store(:,2) == 1 & store(:,18) == 4,1); - meso_sequence = [store(meso_i,:)];%all experiments will be based on this meso_sequence, so that UCS events are delivered with the same pace to all subjects. - - [meso_sequence;[NaN dstore(meso_i,:)]] - % - isi = []; - % - for n_meso = 1:16;%8 mesoblock balances all UCS to UCS distances. 16 too. - %16x9=144 microblocks = 576 trials - fprintf('mesosequence: %g\n',n_meso) - trials = [];%reset it... - for n = 1:4;%expand the current mesoblock to 4 microblocks. - n_micro = n_micro + 1;%global microblock counter - if n == meso_sequence(1,n_meso)%this is a UCS microblock - micro = [csp Shuffle(setdiff(condpool,csp))]; - micro(1) = 9; - else - micro = Shuffle(condpool); - end - trials = [trials micro]; - mblock = [mblock repmat(n_micro,1,9)];%this will count from 2 on, but the 1st microblocks will be aded later - end - cond_id = [cond_id trials]; - isi = [isi seq_BalancedDist(trials,[3 4 5 6])]; - end - % - cond_id = [Shuffle(condpool) cond_id];%add one more microblock for the baseline - isi = [seq_BalancedDist(condpool,[3 4 5 6]) isi];%assign ISI for these - mblock = [repmat(1,1,9) mblock];%and increment the micro_block index - %assign oddballs - cond_id(find(cond_id == 9,1,'last')) = 10;%last UCS turned to ODD - cond_id(max(find(cond_id == 9,2,'first'))) = 10;%second UCS turned to ODD - for n = 0:10;fprintf('%g: %g\n',n,sum(cond_id== n));end - fprintf('seq is %g minutes long and has %g trials...\n',length(cond_id)*4.5/60,length(cond_id)); - fprintf('There are a total %g microblocks and %g UCS microblocks\n',length(cond_id)./9,sum(cond_id == 9)) - seq_information(cond_id,isi) - % put the data to format usable by the presentation script. - seq2 = []; - seq2.cond_id = cond_id; - seq2.mblock = mblock - seq2.isi = isi; - seq2.ucs = cond_id == 9; - seq2.oddball = cond_id == 10; - seq2.stim_id = seq2.cond_id; - seq2.stim_id(seq2.ucs) = csp; - seq2.stim_id(seq2.oddball) = 9; - seq2.tTrial = length(seq2.cond_id); - seq2.dist = MinimumAngle((seq2.stim_id-1)*45,(csp-1)*45); - seq2.dist(seq2.cond_id==0)=NaN; - %oddball=1000 - seq2.dist(seq2.cond_id==max(seq2.cond_id))=1000; - %ucs=500 - seq2.dist(seq2.cond_id==max(seq2.cond_id)-1)=500; - seq2.CrossPosition = ones(1,seq2.tTrial); - % - seq(nsub,csp) = seq2; - end -end -%% - -save([fileparts(which('exp_FearAmy.m')) '/bin/fearamy_seq.mat'],'seq'); \ No newline at end of file diff --git a/seq_feargen_FirstOrderBalanced.m b/seq_feargen_FirstOrderBalanced.m deleted file mode 100644 index bdb87e0..0000000 --- a/seq_feargen_FirstOrderBalanced.m +++ /dev/null @@ -1,23 +0,0 @@ -function [s] = seq_feargen_FirstOrderBalanced(ttrial,rr,ro) -%s = seq_feargen_FirstOrderBalanced(ttrial, rr,ro); -% -% Generates a random sequence of conditions which follows the probability -% of occurances in P, The sequence has a length of TTRIAL. P can be of -% any size. P must sum to 1. RR and RO are reinforcement and oddball -% rates, respectively. Due to rounding off errors the required TTRIAL. -% -% See also: seq_SecondOrderBalanced - - - -%% get probability vector -p = seq_feargen_getprobability(rr,ro); -ntrial = round(p*ttrial); -fprintf('Total number of trials: %g (wanted %g) \n',sum(ntrial),ttrial); - -%% now create a block vector for all conditions and finally randomize it... -s = []; -for ncond = 1:length(p) - s = [s;repmat(ncond-1,ntrial(ncond),1)];%-1 because of null trial; -end -s = Shuffle(s); \ No newline at end of file diff --git a/seq_feargen_SelectSequence.m b/seq_feargen_SelectSequence.m deleted file mode 100755 index 780c149..0000000 --- a/seq_feargen_SelectSequence.m +++ /dev/null @@ -1,257 +0,0 @@ -function [seq]=SelectFearGenSequence(out) -%[seq]=SelectFearGenSequence(out) -% -% Create a sequence file that is used by the Feargen stimulus presentation -% function. -% -% -% Selim Onat, 27-Apr-2013 12:16:01 - - - - -total_sequence = 10;%it will return a total of 10 sequences for each face -isis = [1 2 3];%in units of TRs -tisis = length(isis); -% -%contains the pool of possible sequences (see SecondOrderBalancedSequence -%script); -pool = out.S; -%contains the location of transitions -order = []; -%load -tFace = 8; -tCond = length(unique(pool(:,1))); -tTrial = size(pool,1); -tTrainTrial = 9;%number of training trials. -% -randgen_uniform = @(n,mini,range) rand(1,n).*range+mini; -prestim = 0.5;%This is not being used anymore. -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%this is the matrix where for each transition possible ISIs are presented. -for c = 1:10 - unbalanced(:,c) = circshift( [1 2 3 1 2 3 1 2 ]',[c-1 0]); -end -isi_mat = []; -isi_mat = cat(3, unbalanced, ones(8,10), ones(8,10)*2, ones(8,10)*3); -%now add the transitions from the shock -isi_mat = [isi_mat ; cat(3,repmat(3,[2 10]), nan(2,10,3)) ]; -isi_mat(:,9:10,2:end) = NaN; -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%run across all possible sequences. -counter_condition = zeros(1,8);%will iterate with each acceptance. -counter = 0; -for ns = 1:size(pool,2); - % - stim_id = pool(:,ns); - ucs = stim_id == 9; - oddball = stim_id == 10; - % - if EqualHalfBalancing(ucs) && Consecutiveness(ucs,3) && ExcludeEvent(ucs,0.9) && RateControl(ucs,3,30) && ClosestTrial(oddball,10) && SlopeCheck(ucs+oddball) - % - %get the cs_plus face, this depends on the rank of the sequence - counter = counter + 1; - cs_plus = mod(counter-1,tFace)+1; - cs_neg = mod( cs_plus + tFace/2-1, tFace)+1;%the opposite face - % - counter_condition(cs_plus) = counter_condition(cs_plus) + 1; - nseq = counter_condition(cs_plus); - % - tTrial = length(stim_id); - % - fprintf('Sequence %05d: ',ns );fprintf('+\n'); - order = out.I(:,:,:,ns); - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %Now prepare the ISIs - isi = []; - for x = 1:tCond - for y = 1:tCond - loc = Shuffle( squeeze(order(y,x,:))); - loc(isnan(loc)) = []; - dummy = isi_mat(y,x,:); - dummy(isnan(dummy)) = []; - isi(loc) = Shuffle(dummy); - end - end - isi(end+1) = NaN; - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - prestim_duration = randgen_uniform( tTrial, prestim, prestim); - cross_position = ones(1,length(stim_id)).*2; - %oddball identities, same in baseline and test, so it is not - %updated in the for loop below. - oddball_id = randsample(setdiff(1:8,[cs_plus cs_neg]),sum(oddball),1); - %baseline phase; - for nphase = [2 4] - seq(nseq,cs_plus).phase(nphase).presentation.cond_id = double(stim_id(:));%will (not yet) contain all the original condition indices - seq(nseq,cs_plus).phase(nphase).presentation.stim_id = double(stim_id(:));%will contain the condition indices - seq(nseq,cs_plus).phase(nphase).presentation.isi = double(isi(:)); - seq(nseq,cs_plus).phase(nphase).presentation.prestim_duration = double(prestim_duration(:)); - seq(nseq,cs_plus).phase(nphase).presentation.ucs = double(ucs(:)); - seq(nseq,cs_plus).phase(nphase).presentation.cross_position = double(cross_position(:)); - seq(nseq,cs_plus).cs_plus = double(cs_plus(:)); - seq(nseq,cs_plus).cs_neg = double(cs_neg(:)); - seq(nseq,cs_plus).phase(nphase).presentation.oddball = double(oddball(:)); - % - %now we need to replace the odd trials with face identities. - %Here we exclude the UCS trials, so oddball trial cannot contain - %the CS+ face. - seq(nseq,cs_plus).phase(nphase).presentation.stim_id(find(oddball)) = oddball_id(:); - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %we are done iwth the baseline now find out the conditioning - %sequence. - ok = 1; - while ok - [stim_id order] = GetStim_Sequence; - - oddball = stim_id == 10; - csplus_i = find(stim_id == cs_plus); - %kill half of the trials - csplus_i = randsample( csplus_i , round(length(csplus_i)./2)); - stim_id(csplus_i) = 9; - ucs = stim_id == 9; - tTrial = length(stim_id); - - if EqualHalfBalancing(ucs) & Consecutiveness(ucs,3) & IncludeEvent(ucs,0.9) & Consecutiveness(oddball,3) & EqualHalfBalancing(oddball) & LongestNoEventDistance(oddball+ucs,12) - ok = 0; - - prestim_duration = randgen_uniform( tTrial, prestim, prestim); - cross_position = ones(1,tTrial).*2; - % - isi = []; - for x = 1:3%tCond - for y = 1:3%tCond - loc = Shuffle(squeeze(order(y,x,:))); - loc(isnan(loc)) = []; - tloc = length(loc); - isi(loc) = randsample(isis,tloc,true); - end - end - % - isi(end+1) = NaN; - % - seq(nseq,cs_plus).phase(3).presentation.cond_id = double(stim_id(:));%will (not yet) contain all the original condition indices - seq(nseq,cs_plus).phase(3).presentation.stim_id = double(stim_id(:));%will contain the condition indices - seq(nseq,cs_plus).phase(3).presentation.isi = double(isi(:)); - seq(nseq,cs_plus).phase(3).presentation.prestim_duration = double(prestim_duration(:)); - seq(nseq,cs_plus).phase(3).presentation.ucs = double(ucs(:)); - seq(nseq,cs_plus).phase(3).presentation.cross_position = double(cross_position(:)); - seq(nseq,cs_plus).cs_plus = double(cs_plus(:)); - seq(nseq,cs_plus).cs_neg = double(cs_neg(:)); - seq(nseq,cs_plus).phase(3).presentation.oddball = double(oddball(:)); - - oddball_id = randsample(setdiff(1:8,[cs_plus cs_neg]),sum(oddball),1); - seq(nseq,cs_plus).phase(3).presentation.stim_id(find(oddball)) = oddball_id(:); - %for the conditioning and test phases we replace 9 with the cs+ - %index - for tobereplaced = [3 4] - ucs_i = seq(nseq,cs_plus).phase(tobereplaced).presentation.stim_id == 9; - seq(nseq,cs_plus).phase(tobereplaced).presentation.stim_id(ucs_i) = cs_plus; - end - % - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %and finally prepare the training sequence - seq(nseq,cs_plus).phase(1).presentation.stim_id = double(randsample(setdiff(1:8,cs_plus),tTrainTrial,1)); - seq(nseq,cs_plus).phase(1).presentation.isi = double(ones(1,tTrainTrial));%make same isis all over - seq(nseq,cs_plus).phase(1).presentation.prestim_duration = double(randgen_uniform( tTrainTrial, prestim, prestim)); - seq(nseq,cs_plus).phase(1).presentation.ucs = double(zeros(1,tTrainTrial)); - seq(nseq,cs_plus).phase(1).presentation.cross_position = double(ones(1,tTrainTrial)*2); - seq(nseq,cs_plus).phase(1).presentation.oddball = double(zeros(1,tTrainTrial)); - seq(nseq,cs_plus).phase(1).presentation.oddball([4 6]) = double(1); - end - end - end - %stop if the ziel ist reached. - if sum(counter_condition == total_sequence) == length(counter_condition) - return - end -end - - -% - - - - - function [out]=EqualHalfBalancing(seq) - %are UCSs equally balanced between first and second halves? - out = sum(find(seq) <= ceil(length(seq)./2) ) == round( sum(seq)/2); - end - - function [out]=Consecutiveness(seq,rep) - %Checks consecutiveness in a sequence, out is 0 if event occurs - %more than or equal to REP times consecutively. - out = sum(conv(double(seq),ones(1,rep)) == rep) == 0; - end - - function [out]=IncludeEvent(seq,part) - %returns TRUE if there is an event on the last percentage of the - %sequence. - [out]=sum(find(seq) >= part*length(seq)) ~= 0; - end - - function [out]=ExcludeEvent(seq,part) - %returns TRUE if there is no event on the last percentage of the - %sequence. - [out]=sum(find(seq) >= part*length(seq)) == 0; - end - - function [out]=RateControl(seq,E,N) - %No more E events in N events - out = sum(conv(double(ucs),ones(1,N),'same') > E) == 0; - end - - function [out]=ClosestTrial(seq,closestdistance) - %the closest distance (excluding the one case - %where two events always follow each other) is ClosestDistance. So - %nothing should happen within the ClosestDistance trials. - x = sort(diff(find(seq))); - out = x(2) >= closestdistance; - end - - function [out]=LongestNoEventDistance(seq,distance) - %the longest distance where nothing happens. - out = max(sort(diff(find(seq)))) < distance; - - - end - - function [out]=SlopeCheck(seq) - out = false; - rate = conv(double(seq),ones(1,30),'valid'); - if sum(rate > 4) == 0 - X = [[1:length(rate)]' ones(length(rate),1)]; - [b bint] = regress( rate(:), X ); - if bint(1) <=0 && bint(1,2)>=0 - out = true; - end - end - end - - function [stim_id order]=GetStim_Sequence - - %first and last stimulus should not be the CS+ stimulus... - %This is 1/ not nice 2/ UCS's cannot be balanced with - %respect to the following stimulus identity%furthermore it - %is stupied to start with null trials. We deal with these - %constrainst with setdiff and ignoring the last conditions. - %tCond(nphase)-1: we don't want to start with null trials - - %We want to select with which condition we start the - %experiment. This must exclude CS_PLUS, - %NULL, UCS and ODDBALL trials. - % - valid_conditions = [ cs_plus cs_neg 10]; - [stim_id order] = SecondOrderBalancedSequence( 3, [28 28 2], 2);%start condition always two - %get the real condition index. - stim_id = valid_conditions(stim_id); - - end - - - - - -end \ No newline at end of file diff --git a/seq_feargen_Sequencer.m b/seq_feargen_Sequencer.m deleted file mode 100755 index 02dc434..0000000 --- a/seq_feargen_Sequencer.m +++ /dev/null @@ -1,392 +0,0 @@ -function [seq]= FeargenSequencer(force,varargin) -%seq = FeargenSequencer(force,varargin); -% -% -%possible ISIs -%isis = [1 2 3 4];%in terms of TRs. -isis = [1 2 3];%in terms of TRs. -% -%RepeatVector = {[repmat(4,1,8) 1 1] [28 28 2]};%perfectly balanced when -%there are 4 different ISIs -*RepeatVector = {[repmat(3,1,8) 1 1] [30 30 3]};%perfectly -%balanced for 3 different ISIs (depending on the isis anyway). -% -%Example usage: FeargenSequencer(1,'isis',[1 2 3],'repeatvector',{[repmat(4,1,8) 1 1] [28 28 2]},'filenamesuffix','NonBalanced4') - -%% -if rem(length(varargin),2) == 0 - name = ''; - for v = 1:2:length(varargin) - - if strcmpi(varargin{v},'isis'); - isis = varargin{v+1}; - elseif strcmpi(varargin{v},'repeatvector'); - RepeatVector = varargin{v+1}; - elseif strcmpi(varargin{v},'filenamesuffix'); - %just something to add to the file name so that we know later - %what it is what - name = varargin{v+1}; - end - end -end -%% -[~, b] = system('hostname'); -% -if strcmp(deblank(b),'triostim1') - p.path.baselocation = 'C:\USER\onat\Experiments\'; - p.path.experiment = [p.path.baselocation 'FearGeneralization_Scanner\Sequences\']; -elseif strcmp(deblank(b),'kosmos.fritz.box') - p.path.baselocation = '~/LabComputer/onat/Documents/Experiments/' - p.path.experiment = [p.path.baselocation 'FearGeneralization_Scanner/Sequences/']; -else - p.path.baselocation = '~/Documents/Experiments/'; - p.path.experiment = [p.path.baselocation 'FearGeneralization_Scanner/Sequences/']; -end -%% -out = []; -if force - %load ~/LabComputer/onat/Documents/Experiments/FearGeneralization_Scanner/BigPool.mat - %total number of subjects, should be a multiple of the number of faces - tSub = 10; - tFile = 8;%we have 8 stimuli + null trial + oddball + ucs = 11 conditions. - % - tisis = length(isis); - prestim = 0.5;%This is not being used anymore. - % - tTrainTrial = 9;%number of training trials. - % - randgen_uniform = @(n,mini,range) rand(1,n).*range+mini; - % - counter = 0; - for cs_plus = 1:8; - tic; - %follows subject index, it is simpler to memorize - cs_neg = mod( cs_plus + tFile/2-1, tFile)+1;%the opposite face - % - %10 represents for the moment the oddball trials - %and 9 the UCS trials. - map{1} = [ 1:8 9 10 ]; - map{3} = [ 1:8 9 10 ]; - map{2} = [ cs_plus cs_neg 10];%mapping for the conditioning phase is dynamic. - % - for nphase = [1 2]%phase 3 is the same as 1. - fprintf('=======================================\nCSP %d, phase %d\n',cs_plus,nphase); - %init - ucs = []; - stim_id = []; - oddball = []; - order = []; - tCond = length(map{nphase});%with ucs condition and oddball it is 10 - - %Get the sequence - fprintf('Searching UCS, Oddball and Stim Sequence...\n'); - - if nphase == 2 - while ~(oddball_check & ucs_check & common_check) - %[ucs_check oddball_check common_check] - %stimulus id sequence - GetStim_Sequence; - tTrial = length(stim_id); - % - if nphase == 2 - %detect manually the UCS trials, these are taken from - %the CS+ condition, half of them is transformed to UCS - %trials - csplus_i = find(stim_id == cs_plus); - %kill half of the trials - csplus_i = randsample( csplus_i , round(length(csplus_i)./2)); - stim_id(csplus_i) = 9; - % - end - ucs = stim_id == 9; - oddball = stim_id == 10; - end - figure(1); - plot(ucs,'ro-'); - hold on - plot(oddball); - hold off - %pause; - end - - % - if nphase == 1 - while ~(oddball_check & ucs_check & common_check) - %fprintf('====\n'); - counter = counter+1; - [ucs_check oddball_check common_check] - %stimulus id sequence - GetStim_Sequence; - % - tTrial = length(stim_id); - % - if nphase == 2 - %detect manually the UCS trials, these are taken from - %the CS+ condition, half of them is transformed to UCS - %trials - csplus_i = find(stim_id == cs_plus); - %kill half of the trials - csplus_i = randsample( csplus_i , round(length(csplus_i)./2)); - stim_id(csplus_i) = 9; - % - end - ucs = stim_id == 9; - oddball = stim_id == 10; - end - - figure(2) - plot(X*b,'r'); - hold on; - plot(rate,'ko-'); - title(mat2str(bint(1,:),3)); - hold off; - figure(3) - plot(ucs,'ro-') - hold on - plot(oddball,'bo-'); - hold off - - end - - fprintf('UCS, Oddball, Stim Sequence sequence found...\n'); - - %Distribute the ISIs - %We will not do this like this anymore. - %isi = BalancedDist(stim_id(1:end-1),isis); - isi = []; - for x = 1:tCond - for y = 1:tCond - keyboard - loc = Shuffle(squeeze(order(y,x,:))); - loc(isnan(loc)) = []; - tloc = length(loc); - if rem(tloc,tisis) == 0%so if we have 4 different ISIs we distribute this to 4 different transitions randomly - isi(loc) = BalancedDist(ones(1,tloc),isis); - else%some transition occur not as many as the number of ISIs - isi(loc) = randsample(isis,tloc,true); - end - end - end - isi(end+1) = NaN; - - %prestim duration: this is the period where the fixation cross is - %on but the stim is off. - prestim_duration = randgen_uniform( tTrial, prestim, prestim); - % - cross_position = ones(1,length(stim_id)).*2; - %deal all - seq(nseq).phase(nphase+1).presentation.cond_id = stim_id ;%will (not yet) contain all the original condition indices - seq(nseq).phase(nphase+1).presentation.stim_id = stim_id ;%will contain the condition indices - seq(nseq).phase(nphase+1).presentation.isi = isi; - seq(nseq).phase(nphase+1).presentation.prestim_duration = prestim_duration; - seq(nseq).phase(nphase+1).presentation.ucs = ucs; - seq(nseq).phase(nphase+1).presentation.cross_position = cross_position; - seq(nseq).cs_plus = cs_plus; - seq(nseq).cs_neg = cs_neg; - seq(nseq).phase(nphase+1).presentation.oddball = oddball; - % - %now we need to replace the odd trials with face identities. - %Here we exclude the UCS trials, so oddball trial can contain - %the CS+ face. - oddball_i = find( oddball ); - seq(nseq).phase(nphase+1).presentation.stim_id(oddball_i) = randsample(setdiff(1:8,[cs_plus cs_neg]),length(oddball_i),1); - - end - % - %add the pre-experiment training trials - fprintf('Dealing with the training sequence\n'); - seq(nseq).phase(1).presentation.stim_id = randsample(setdiff(1:8,cs_plus),tTrainTrial,1); - seq(nseq).phase(1).presentation.isi = ones(1,tTrainTrial);%make same isis all over - seq(nseq).phase(1).presentation.prestim_duration = randgen_uniform( tTrainTrial, prestim, prestim); - seq(nseq).phase(1).presentation.ucs = zeros(1,tTrainTrial); - seq(nseq).phase(1).presentation.cross_position = ones(1,tTrainTrial)*2; - seq(nseq).phase(1).presentation.oddball = zeros(1,tTrainTrial); - seq(nseq).phase(1).presentation.oddball([4 6]) = 1; - % - % - %the test phase is EXACTLY THE SAME as the baseline phase - seq(nseq).phase(4).presentation.stim_id = seq(nseq).phase(2).presentation.stim_id; - seq(nseq).phase(4).presentation.cond_id = seq(nseq).phase(2).presentation.cond_id; - seq(nseq).phase(4).presentation.isi = seq(nseq).phase(2).presentation.isi; - seq(nseq).phase(4).presentation.prestim_duration = seq(nseq).phase(2).presentation.prestim_duration; - seq(nseq).phase(4).presentation.ucs = seq(nseq).phase(2).presentation.ucs; - seq(nseq).phase(4).presentation.cross_position = seq(nseq).phase(2).presentation.cross_position; - seq(nseq).phase(4).presentation.oddball = seq(nseq).phase(2).presentation.oddball; - - %for the conditioning and test phases we replace 9 with the cs+ - %index - for tobereplaced = [3 4] - ucs_i = seq(nseq).phase(tobereplaced).presentation.stim_id == 9; - seq(nseq).phase(tobereplaced).presentation.stim_id(ucs_i) = cs_plus; - end - save([p.path.experiment mfilename '_' datestr(now,'yymmdd_HHMM') '_' name],'seq'); - fprintf('This subject (%d) finished in %0.2g minutes\n',nseq,toc./60); - end - save([p.path.experiment mfilename '_' datestr(now,'yymmdd_HHMM') '_' name],'seq'); -else - d = dir([p.path.experiment '*.mat']); - load([p.path.experiment d(end).name]); -end -% B/T C -%================================================================== -% no UCS in a row of 3 : + + -% no Oddball in a row of 3 : + + -% Exactly 1 ucs at the last 10% : + - -% Exactly 1 ucs at the first 10% : + - -% UCS occurs before CS+ : + + -% equally balancing between 1st and 2nd halves : - + -% UCS doesn occur closer than 9 trials : + - -% oddball doesnt occur closer than 9 trials : + - -% oddballs and UCS doesnt occur closer than 4 trials : + - -% something must happend in the next 30 trials : + - -% something must happend in the next 12 trials : + + - - function out = ucs_check - %returns one if the conditions is met - out=false; - if ~isempty(ucs); - %CONDITIONING -% % % % -% % % % if nphase == 2 -% % % % %are UCSs equally balanced between first and second halves -% % % % if sum(find(ucs) <= ceil(tTrial./2)) == round(sum(ucs)/2); -% % % % %fprintf('UCS+\n') -% % % % %no ucs in a row of 3 -% % % % if sum(conv(double(ucs),[1 1 1]) == 3) == 0; -% % % % %fprintf('UCS++\n') -% % % % if sum(find(ucs) >= 0.9*tTrial) ~= 0 -% % % % %first occurence of the dangerous face must be -% % % % %shocked -% % % % %if find(stim_id == cs_plus,1) > find(stim_id == 9,1); -% % % % % fprintf('UCS+++\n') -% % % % out = true; -% % % % end -% % % % end -% % % % end - - %BASELINE AND TEST -% % % % % elseif nphase == 1 -% % % % % %no 3 UCSs in a serie -% % % % % if sum(conv(double(ucs),[1 1 1],'same') == 3) == 0; -% % % % % fprintf('UCS+\n') -% % % % % %Exactly zero UCS at the last part -% % % % % if sum(find(ucs) >= 0.9*tTrial) == 0 -% % % % % fprintf('UCS++\n') -% % % % % %no more than 2 ucs per 10 trials -% % % % % if sum(conv(double(ucs),ones(1,30),'same') > 3) == 0; -% % % % % % %are UCSs equally balanced between first and second halves -% % % % % if sum(find(ucs) <= ceil(tTrial./2)) == round(sum(ucs)/2); -% % % % % fprintf('UCS++++\n') -% % % % % out = true; -% % % % % end -% % % % % end -% % % % % end -% % % % % end -% % % % % end - %i dont really know what at the conditioning phase there should - %be no trials at the end of the phase? if at all, may be this - %is more relevant for the Baseline and Test Phases - %%no UCS at the last 90% trials - %RIGHT NOW THIS IS OFF, It has to be discussed? - end - % out = true; - end - function [out]=oddball_check - out=false; - %returns one if the condition is met - if ~isempty(oddball); - if nphase == 2 - -% % % %fprintf('oddball+\n') -% % % %are oddballs equally balanced between first and second halves -% % % if sum(find(oddball) <= ceil(tTrial./2)) == round(sum(oddball)/2); -% % % %fprintf('oddball++\n') -% % % %no oddballs in a series of 3 -% % % if sum(conv(double(oddball),[1 1 1]) == 3) == 0; -% % % %fprintf('oddball+++\n') -% % % %if sum(find(ucs) >= 0.9*tTrial) == 0 -% % % out = true; -% % % %end -% % % end -% % % end - - elseif nphase == 1 - -% % % % %the closest distance (excluding the one case -% % % % %where two ucs's follow each other) is 9 trials -% % % % x = sort(diff(find(oddball))); -% % % % if x(2) >= 10 -% % % % %fprintf('oddball+\n') -% % % % out = true; -% % % % end - - end - end - end - function [out]=common_check - out=false; - %returns one if the condition is met - if ~isempty(oddball) && ~isempty(ucs) - new = oddball+ucs; - if nphase == 2 - x = sort(diff(find(new))); - %that is something has to happen within the next 12 - %trials... - if max(x) < 12 - %fprintf('common+\n') - out = true; - end - - elseif nphase == 1%only for the baseline condition -% % % % -% % % % rate = conv(double(new),ones(1,30),'valid'); -% % % % X = [[1:length(rate)]' ones(length(rate),1)]; -% % % % [b bint] = regress( rate(:), X ); -% % % % if sum(rate > 4) == 0 -% % % % if bint(1)<=0 && bint(1,2)>=0 -% % % % out = true; -% % % % end -% % % % end - end - end - end - - function GetStim_Sequence - - %first and last stimulus should not be the CS+ stimulus... - %This is 1/ not nice 2/ UCS's cannot be balanced with - %respect to the following stimulus identity%furthermore it - %is stupied to start with null trials. We deal with these - %constrainst with setdiff and ignoring the last conditions. - %tCond(nphase)-1: we don't want to start with null trials - - %We want to select with which condition we start the - %experiment. This must exclude CS_PLUS, - %NULL, UCS and ODDBALL trials. - % - valid_conditions = map{nphase}(map{nphase} <= 8); - firstlast = Shuffle(setdiff(valid_conditions,cs_plus),1);%this is now in the face space; - %bring it back to the index space that the SOBS function - %understands. - firstlast = find(map{nphase} == firstlast); - [stim_id order] = SecondOrderBalancedSequence( tCond, RepeatVector{nphase}, firstlast); - %get the real condition index. - stim_id = map{nphase}(stim_id); - - end -% - function [oddball]=SelectOddTrials(stim_seq,tOddball) - %selects oddball trials in a balanced manner so that all possible - %conditions in STIM_SEQ are selected equally likely as oddball. - tt = map{nphase}(1:end-1); - for i = tt - ind(i,:) = Shuffle(find(stim_seq == i)); - end - oddball = zeros(1,length(stim_seq)); - oddball(ind(tt,1:tOddball)) = 1; - end - -d = dir([p.path.experiment '*.mat']); -load([p.path.experiment d(end).name]); - -end diff --git a/seq_feargen_analysis.m b/seq_feargen_analysis.m deleted file mode 100644 index 66f5c1a..0000000 --- a/seq_feargen_analysis.m +++ /dev/null @@ -1,137 +0,0 @@ -%so an initial guess for duration would be 900 seconds at an ISI of 3. This -%corresponds to ~ 300 trials and 15 minutes. RR is 0.25 and RO 0.01-0.03, -%there shouldn't be more than 3 oddballs, I think 2 is a good choice. - -%% test how duration influences efficiency on a random sequence. -clear i; -for t = 50:10:1000; - s = seq_feargen_FirstOrderBalanced(t,.5,.5);%create a sequence - i(t/10-1)=seq_feargen_information(s);%get the efficiency. -end -figure(1001); -plot(50:10:1000,[i(:).eff_norm],'o-') -xlabel('#trial') -ylabel('normalized efficiency') -% Conclusion: Efficiency increases initially very fast but then slows -% downs. This is expected given that long sequences are more likely to -% reduce orthogonality. we should not present less then 300-350 trials. -% This speaks against having a sequence of [ones(1,9)*3 1 1] but rather -% [ones(1,9)*4 1 1] (see the difference of 3 vs. 4?). - -%% TEST EFFICIENCY OF DIFFERENT SEQUENCES CREATED WITH DIFFERENT FLAVOURS -clear info -%set the repvec -rep_vec = [ones(1,9)*3 1 1]; -%create a dummy seq to get the number of trials, that will be used to -%create a random signal with the same number of trials. -dummy_seq = seq_SecondOrderBalancedSequence(rep_vec,1)-1; -ttrial = length(dummy_seq); -n = 1; -while n <= 100 - s = seq_feargen_FirstOrderBalanced(ttrial,pr,po); - info(1,n) = seq_feargen_information(s,[0 0]);%[0 0] no visuals, no verbose - % - s = seq_SecondOrderBalancedSequence(rep_vec,1)-1; - info(2,n) = seq_feargen_information(s,[0 0]); - % - n = n + 1; -end -% concat all -e = [info(1,:).eff_norm ;info(2,:).eff_norm]'; -figure(2001);subplot(1,2,1);hist(e,20);subplot(1,2,2);boxplot(e); -% random sequence of length 365 is a bit more efficient than its comparable -% secondorder balanced sequences generated with [ones(1,9)*4 1 1]. (shit! haha). -% ~365 is relatively long, so testing it with a sequence of 280 trials -% ([ones(1,9)*3 1 1]) gives the opposite result. This means that second -% order balancing helps when the sequence length is short. For longer -% sequences it doesn't matter sooouu much. -%% What about a pruned mseq with comparable event probability? -% For this I generate an mseq of base 11, with power of 2 to get a seq of -% 120 and I concat it to get 240 or 360. -%the following shows that non-pruned m-seq is quiet efficient. -s = []; -for n = 1:3 - s = [s; mseq2(11,2,0,randsample(1:18,1))]; -end -seq_feargen_information([s]); -%prune -pr = .25; -po = .01; -[s] = seq_feargen_prune(s,pr,po); -seq_feargen_information([s]); -%% so now do the same efficiency test but include also mseq pruned. -% -% second order sequence can be either 285 or 365 trial long. mseq after -% pruning is about 305. So when length is considered m-seq will be most -% handicapped. -clear info -%set the repvec -rep_vec = [ones(1,9)*4 1 1]; -%create a dummy seq to get the number of trials, that will be used to -%create a random signal with the same number of trials. -dummy_seq = seq_SecondOrderBalancedSequence(rep_vec,1)-1; -ttrial = length(dummy_seq); -pr = .25; -po = .0033; -n = 1; -while n <= 500 - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % 1st order - s = seq_feargen_FirstOrderBalanced(ttrial,pr,po); - info(1,n) = seq_feargen_information(s,[0 0]); - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % 2nd order - s = seq_SecondOrderBalancedSequence(rep_vec,1)-1; - info(2,n) = seq_feargen_information(s,[0 0]); - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % pruned mseq (power = 2) - s = []; - for N = 1:3 - s = [s; 0; mseq2(11,2,0,randsample(1:18,1))]; - end - [s]=seq_feargen_prune(s,pr,po);%here the null trials are very predictable somehow :( - info(3,n) = seq_feargen_information(s,[0 0]); - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % pruned mseq higher power (power = 3) - s = [mseq2(11,3,0,randsample(1:18,1))]; - start = randsample(length(s) - 363,1);%363 is the sequence before pruning, that will result in ~300 thereafter. - s = s(start:start+trial-1);%start of a random chunk - [s] = seq_feargen_prune(s,pr,po); - info(4,n) = seq_feargen_information(s,[0 0]); - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - n = n + 1 -end -%% concat all the efficiencies -e = [info(1,:).eff_norm ;info(2,:).eff_norm ;info(3,:).eff_norm;info(4,:).eff_norm]'; -figure(2001);subplot(1,2,1);hist(e,20);subplot(1,2,2);boxplot(e); -%good!!! we are getting there, the pruned mseq is better than both of the -%sequences in terms of their efficiency. Interestingly the pruned m-seq of -%power 3 doesn't perform so well. -%% ok now let's look at the Kao's toolbox. - -%% and finally we look at the optseq2 program -clear info -basepath = '/Users/onat/Desktop/optseq/'; -suffix = 'fg-*'; -files = ListFiles(sprintf('%s%s*',basepath,suffix))'; -n = 0; -for f = files - n = n + 1; - s = seq_feargen_FirstOrderBalanced(298,pr,po);%298 is same length as optseq - info(1,n) = seq_feargen_information(s,[0 0]); - % - [s] = seq_optseq22s(sprintf('%s%s',basepath,f{1})); - info(2,n) = seq_feargen_information(s,[0 0]); -end -e = [info(1,:).eff_norm ;info(2,:).eff_norm]'; -hist(e) -%well this graph shows us that the optseq performs about 70-75% level, -%sofar the worst choice. Sadly for optseq it performs worst than balanced -%random. - - - - - - - diff --git a/seq_feargen_cloudseq.m b/seq_feargen_cloudseq.m deleted file mode 100644 index cecac0d..0000000 --- a/seq_feargen_cloudseq.m +++ /dev/null @@ -1,92 +0,0 @@ -function [s] = seq_feargen_cloudseq(csp,phase) -%SEQ_FEARGEN_SEQ2FACES -%takes a pruned mseq (seq_feargen_mseq_pruned) and adds the remaining -%needed information -ok=0; -while ~ok -%create sequence until one passes the constraint-test -%method 2= baseline&test, 22 = conditioning -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5fprintf('Starting Constraint Check....\n') -if strcmp(phase,'baseline') - [s0]=seq_feargen_mseq_pruned(2,0.3,0.01); -elseif strcmp(phase,'cond') - [s0]=seq_feargen_mseq_pruned(22,0.3,0.01); -elseif strcmp(phase,'test') - s0=[]; - for n=1:2 - [s0]=[s0; seq_feargen_mseq_pruned(2,0.3,0.01)]; - end -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%fprintf('Found appropriate sequence....\n') -%s has conditions only, so now we set up the whole seq structure as we had -%it in all versions -s.cond_id = s0; -%assign ucs seq -s.ucs = (s.cond_id==(max(s.cond_id)-1)); -%assign oddball seq -s.oddball = (s.cond_id==max(s.cond_id)); -%got a sequence, see if it holds. -ok=seq_feargen_constraints(s,1,1,1,1,1); -end - -%assign isis (uniform so far) -s.isi = ones(length(s.cond_id),1)*3; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%phase specific cond2stim assignments -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -s.stim_id = s.cond_id; -%ucs condition is csp face (cond+test) -if ~strcmp(phase,'baseline') -s.stim_id(s.cond_id==(max(s.cond_id)-1))=csp; -end -%cond 2 means csn in conditioning, 1 and 3 csp -if strcmp(phase,'cond') - s.stim_id(s.cond_id==2)=mod( csp + 8/2-1, 8)+1; - s.stim_id(s.cond_id==1)=csp; - s.stim_id(s.cond_id==4)=10; -end - - -s.tTrial = length(s.cond_id); -s.tFacetrial = sum(s.stim_id~=0); - -%we want an index that gives us the distance from the csp face, e.g. for -%plotting it later -s.dist = MinimumAngle((s.stim_id-1)*45,(csp-1)*45); -s.dist(s.cond_id==0)=NaN; -%oddball=1000 -s.dist(s.cond_id==max(s.cond_id))=1000; -%ucs=500 -s.dist(s.cond_id==max(s.cond_id)-1)=500; - -%get fixation crosses from that function -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%fprintf('Balancing fixation cross positions....\n') -s.CrossPosition = seq_feargen_fixcross(s); - - - - - function [a]=MinimumAngle(y,x) - %[a]=MinimumAngle(x,y); - % - %finds the minimum angle between two angles given in degrees, the answer is - %also in degrees. The clockwise distances from Y to X are considered as - %positive. Opposite angles are considered as positive 180. - - x = deg2rad(x); - y = deg2rad(y); - - a = atan2(sin(x-y), cos(x-y)); - - a = -round(rad2deg(a)); - - if any(abs(a) == 180); - a(abs(a) == 180) = 180; - end - end - - -end - diff --git a/seq_feargen_constraints.m b/seq_feargen_constraints.m deleted file mode 100644 index a047816..0000000 --- a/seq_feargen_constraints.m +++ /dev/null @@ -1,65 +0,0 @@ -function [ok]=seq_feargen_constraints(seq,ucsafter,oddafter,oddbefore,slopeucs,toofarucs) -cons=NaN(5,1); -if ucsafter -cons(1)=IsEventAfter(seq.ucs,0.95); -else -end -if oddafter -cons(2)=IsEventAfter(seq.oddball,0.95); -end - -if oddbefore -cons(3)=IsEventBefore(seq.oddball,0.1); -end - -if slopeucs -cons(4)=SlopeCheck(seq.ucs); -end - -if toofarucs -cons(5)=IsEventTooFar(seq.ucs,40); -end - -if any(cons)==true - ok=0; -else - ok=1; -end - - - function [out]=IsEventAfter(seq,part) - %returns TRUE if there is any events after PART percentile of - %trials - out = sum(find(seq) > part*length(seq)) ~= 0; - end - - function [out]=IsEventBefore(seq,part) - %returns TRUE if there is any events before PART percentile of - %trials - out = sum(find(seq) < part*length(seq)) ~= 0; - end - - function [out]=IsEventTooFar(seq,distance) - %the longest distance where nothing happens. - out = max(sort(diff(find(seq)))) > distance; - if isempty(out) - keyboard - out=0; - end - end - - function [out]=SlopeCheck(seq) - - rate = conv(double(seq),ones(1,30),'valid'); - X = [(1:length(rate))' ones(length(rate),1)]; - [b bint] = regress( rate(:), X ); - if bint(1) <=0 && bint(1,2)>=0 - out = false; - else - out=true; - end - - end -end - - \ No newline at end of file diff --git a/seq_feargen_eyelab.m b/seq_feargen_eyelab.m deleted file mode 100644 index 1a3632d..0000000 --- a/seq_feargen_eyelab.m +++ /dev/null @@ -1,209 +0,0 @@ -function [seq]=seq_feargen_eyelab(condition,balancing,isis) -% FEARGENSEQUENCE_ET -% for 1 Circle! -% -% -% creates a sequence for all the given faces, plus ucs and oddball. -% The sequence is 2ndOrderBalanced regarding Face Transitions, ISI and -% Fixation Crosses (balanced only left/right, not real angle). -% CSP (in face Number) contains the CSplus face. -% -% condition='b' for Baseline, 't' for Test, and 'c' for Conditioning. -% isis=[2 3 4 5]; could be anything -% balancing: 'quasiuniform' 'random' 'uniform' 'exponential' -% -% Example: seq=seq_feargen_eyelab('tshort',1,'constant',[3]); -% -% The CSP related information has to be inserted to the sequence, that is -% cond_ind -> stim_id transformation has to be computed separately. - -trialduration = .75; -% minimum ISI -mini_isi = 3; -% minimum pre stimulus -mini_ps = 0.4; -%% SEQ is between 1:tCond ==> 1 2 3 3 1 2 1 2 1 3 3 4 -%% Decide on how to call SecondOrderBalanced function -null_events=0; -if strcmp(condition,'c') - rep_vec = [30 18 4 1]; -elseif strcmp(condition,'t') - rep_vec = [ones(1,8)*4 1 1]; -elseif strcmp(condition,'b') - rep_vec = [ones(1,8)*4 1 1]; -elseif strcmp(condition,'bshort')%with null events - rep_vec = [ones(1,9)*2 1 1]; - null_events=1;%will shift everything so that null events are indexed as 0. -elseif strcmp(condition,'tshort') - rep_vec = [ones(1,9)*3 1 1]; - null_events=1; -elseif strcmp(condition,'cshort') - %rep_vec = [30 30 18 4 1]; - rep_vec = [22 22 22 1]; - rr = 0.275; - null_events=1; -end - -%% create the block-wise structure of trials -seq.CrossPosition = []; -ok = 0; -fprintf('Starting Constraint Check....\n') -while ~ok - %create the 2nd Order Balanced Sequence - [seq.cond_id,ranks] = seq_SecondOrderBalancedSequence(rep_vec,1); - - - condid_odd = max(unique(seq.cond_id)); - % - seq.oddball = seq.cond_id == condid_odd; - - if strcmp(condition,'cshort') - seq.ucs = zeros(1,length(seq.cond_id)); - howmanyucs = round(rr*sum(seq.cond_id == 2)); - seq.ucs(randsample(find(seq.cond_id == 2),howmanyucs)) = 1; - tface = length(unique(seq.cond_id) > 0)-1; - - else - tface = length(unique(seq.cond_id) > 0)-2; - condid_ucs = condid_odd-1; - %first and second from the last are special - seq.ucs = seq.cond_id == condid_ucs; - end - %check constraints. - %inputs after seq are: IsEventAfter(seq.ucs,0.95), IsEventAfter(seq.oddball,0.95), IsEventBefore(seq.oddball,0.1), SlopeCheck(seq.ucs), IsEventTooFar(seq.ucs,50) - ok=seq_feargen_constraints(seq,1,1,1,1,1); - - if ok - tucs = sum(seq.ucs); - seq.tTrial = length(seq.cond_id); - if null_events - seq.cond_id = seq.cond_id - 1; - end - computeEff; - computeEnt; - fprintf('Constraint Check: OK. \n') - end -end - -%% final variables -%prestim durations should be smaller than ISI, right now they are [0.4 0.7] -seq.prestim_duration = mini_ps+rand(1,seq.tTrial).*.3; -% -DistributeISI; -FixationCrossSequence; - -fprintf('Starting sanity checks: RR \n') - -% real Reinforcement Rate -seq.RRR=tucs./(tucs+sum(seq.cond_id == 1));%any condition wd do it. -fprintf('The effective RRR is %g percent \n',seq.RRR*100); - - -fprintf('Starting sanity checks: Duration (s) \n') -duration = sum(seq.isi); -fprintf('Total duration is %02g minutes.\n',duration./60); - -%% viz stuff. -visualization =0; -if visualization == 1 - subplot(3,1,1) - plot(1:length(seq.ucs==1 ),seq.cond_id,'o-'); - hold on; - plot(find(seq.ucs == 1),seq.cond_id(seq.ucs == 1),'+r','markersize',10); - plot(find(seq.oddball == 1),seq.cond_id(seq.oddball == 1),'sg','markersize',10); - hold off; - subplot(3,1,2) - n = hist3([seq.cond_id ; [seq.cond_id(2:end) NaN]]'); - imagesc(n) - title('transition check'); - subplot(3,1,3) - n = hist3([seq.cond_id ; [seq.cond_id(2:end) NaN]]'); - for y = 1:length(unique(seq.cond_id)); - for x = 1:length(unique(seq.cond_id)); - r = ranks(y,x,:); - isis_m(y,x) = mean(seq.isi(r(~isnan(r)))); - end; - end - imagesc(isis_m);colorbar; - title('Average ISIs'); -end - - - function FixationCrossSequence - seq.CrossPosition = nan(1,seq.tTrial); - - radius=520; %in px - cross_direction = [0 180]; - center = [800 600]; - for ncond = 1:tface - ind = seq.cond_id == ncond; - seq.CrossPosition(ind) = seq_BalancedDist(ones(1,sum(ind)),cross_direction); - end - - %Transitions to/from UCS/Oddball. - seq.CrossPosition(isnan(seq.CrossPosition)) = seq_BalancedDist(ones(1,sum(isnan(seq.CrossPosition))),cross_direction); - - seq.CrossPosition = seq.CrossPosition + rand(1,length(seq.cond_id))*30-15; - seq.CrossPosition=round([cosd(seq.CrossPosition')*radius+center(1) sind(seq.CrossPosition')*radius+center(2)]); - - end - - - - function computeEff - Q = max(seq.cond_id); - [dummy_eff dummy_det] = calc_meffdet(seq.cond_id , 10 , Q , 3 ); - seq.stats.eff = dummy_eff(1); - seq.stats.det = dummy_det(1); - [~,~,seq.stats.max_det,seq.stats.max_eff] = tcurve(Q,10,length(seq.cond_id)); - fprintf('Normalized efficiency is %03g...\n',seq.stats.eff./seq.stats.max_eff); - end - function computeEnt - seq.stats.ent_order =0:5; - for order = 0:5; - [seq.stats.ent(order+1),seq.stats.entmax] = calcent(seq.cond_id,order); - end - end - - function DistributeISI - % balance the ISI - if strcmp(balancing,'uniform') - seq.isi = seq_BalancedDist(seq.cond_id,isis); - elseif strcmp(balancing,'exponential') - if length(isis)~=2 - fprintf('Enter correct parameters for exponential distribution [min mean]! \n') - return - end - dummy=exprnd(isis(2),[1 seq.tTrial]); - seq.isi = isis(1)+floor(dummy*2)/2; - elseif strcmp(balancing,'quasiuniform') - seq.isi = nan(1,seq.tTrial); - seq.cond_id(end+1)=NaN; - % if method ==1 - %search for transitions from all 'first'=1:2or8 faces to sth else. - for first = 1:tface; - first_i = find(seq.cond_id==first); - nexts = first_i+1;%transition to the following face - nexts_clean = nexts(seq.cond_id(nexts) < tface+1); %exclude trans to ucs/odd - - for i = unique(seq.cond_id(nexts_clean)) - %for each destination face, randomly assign an ISI - pos = nexts_clean(seq.cond_id(nexts_clean) == i)-1; - seq.isi(pos) = seq_BalancedDist(ones(1,length(pos)),isis); - end - end - %find transitions FROM ucs/odd, set them to max(isi) - events_i=seq.ucs|seq.oddball; - seq.isi(events_i) = max(isis); - % from faces to ucs/odd should also be nicely random - nanpos = isnan(seq.isi); - seq.isi(isnan(seq.isi)) = seq_BalancedDist(ones(1,sum(nanpos)),isis); - seq.cond_id(end) = []; - elseif strcmp(balancing,'random') - seq.isi = randsample(isis,seq.tTrial,1); - elseif strcmp(balancing,'constant') - seq.isi = repmat(isis,[1,seq.tTrial]); - end - - end -end diff --git a/seq_feargen_eyelab_fillpool.m b/seq_feargen_eyelab_fillpool.m deleted file mode 100644 index fdeb057..0000000 --- a/seq_feargen_eyelab_fillpool.m +++ /dev/null @@ -1,25 +0,0 @@ -function seq_feargen_eyelab_fillpool(varargin) -%seq_feargen_eyelab_fillpool(varargin) -% -% Generates pool of second order sequences. Will run forever. The results -% of this pool has first to be selected by efficiency. -% -% VARARGIN is fed to seq_feargen_eyelab. -% -% Example: -% seq_feargen_eyelab_fillpool('tshort','constant',[2.5]); -% would generate sequence pool for test phase. -% -% - -path2pool = sprintf('%s/%s_%s.mat',fileparts(which(mfilename)),mfilename,varargin{1}); -pool = []; -try %try to get what is already there -load(path2pool); -end - -while 1 - pool = [pool seq_feargen_eyelab(varargin{:})]; - fprintf('run no %d...\n',length(pool)); - save(path2pool,pool); -end diff --git a/seq_feargen_eyelab_filterpool.m b/seq_feargen_eyelab_filterpool.m deleted file mode 100644 index fb1acbd..0000000 --- a/seq_feargen_eyelab_filterpool.m +++ /dev/null @@ -1,19 +0,0 @@ -function [pool]=seq_feargen_eyelab_filterpool(pool) -%[pool]=seq_feargen_eyelab_filterpool(pool) -% -% Will sort the sequence pool created by seq_feargen_eyelab_fillpool -% based on efficiency. - -%% -stats = [pool(:).stats]; -eff = [stats(:).eff]; -eff = eff(1,:);%global efficiency -eff = eff(:); -ent = vertcat(stats(:).ent); -figure; -subplot(3,1,1);hist(eff);title('efficiencies'); -subplot(3,1,2);hist(ent(:,3));title('entropy'); -subplot(3,1,3);plot(ent(:,3),eff,'o'); - -[~,i] = sort(eff,1,'descend'); -pool = pool(i); \ No newline at end of file diff --git a/seq_feargen_eyelab_pool2subjects.m b/seq_feargen_eyelab_pool2subjects.m deleted file mode 100644 index 2311816..0000000 --- a/seq_feargen_eyelab_pool2subjects.m +++ /dev/null @@ -1,40 +0,0 @@ -function [s]=seq_feargen_eyelab_pool2subjects(varargin) -%[s]=seq_feargen_eyelab_pool2subjects(pool,phases) -%[s]=seq_feargen_eyelab_pool2subjects(pool,phases,pool2,phases2,...) -% -% Will distribute sequences in a pool (following filtering) to subjects, -% phases and runs. This can be then be read by the stimulus presentation -% function. -% -% Examples: -% This distributes pool into phases 1 and 3 -% [s]=seq_feargen_eyelab_pool2subjects(pool,[1 3]); -% This distributes pool into phases 1 and 3 and pool2 into phase 2. -% [s]=seq_feargen_eyelab_pool2subjects(pool,[1 3],pool2,[2]); -% -% - -%% - -trun = 5;%how many runs per subject, each run is about 8-10 minutes so this has to be decided, -%but 5 seems to be a reasonable upper limit. -% -for v = 1:2:length(varargin)/2; - %will distribute sequences POOL to phases. - pool = varargin{v}; - phases = varargin{v+1}; - tseq = length(pool); - %For each phase fill in the phase and runs with randomly selected - %sequences. - for ns = 1:100 - for run = 1:trun - %select a sequence - dummy = pool(randsample(1:tseq,1)); - %distribute the selected seq to phases - for nphase = phases - %randomly assign one sequence to both c and b phases. - s(ns).phase(nphase).run(run) = dummy; - end - end - end -end \ No newline at end of file diff --git a/seq_feargen_fixcross.m b/seq_feargen_fixcross.m deleted file mode 100644 index ad17297..0000000 --- a/seq_feargen_fixcross.m +++ /dev/null @@ -1,25 +0,0 @@ -function [CrossPosition] = seq_feargen_fixcross(s) -%SEQ_FEARGEN_FIXCROSS -%sets up all the fixation cross positions left/right from the face - -CrossPosition = nan(1,s.tTrial); -tface = length(unique(s.cond_id) > 0)-2; - -radius=590; %in px -cross_direction = [0 180]; -center = [800 600]; -for ncond = 1:tface - ind = s.cond_id == ncond; - CrossPosition(ind) = seq_BalancedDist(ones(1,sum(ind)),cross_direction); -end - -%Transitions to/from UCS/Oddball. -CrossPosition(isnan(CrossPosition)) = seq_BalancedDist(ones(1,sum(isnan(CrossPosition))),cross_direction); - -CrossPosition = CrossPosition + rand(1,length(s.cond_id))*30-15; -CrossPosition=round([cosd(CrossPosition')*radius+center(1) sind(CrossPosition')*radius+center(2)]); - - - -end - diff --git a/seq_feargen_getprobability.m b/seq_feargen_getprobability.m deleted file mode 100644 index 74267cb..0000000 --- a/seq_feargen_getprobability.m +++ /dev/null @@ -1,35 +0,0 @@ -function [p,p2]=seq_feargen_getprobability(rr,oddball) -%[p,p2]=seq_feargen_getprobability(rr,oddball) -% -% Will return a vector of probabilities in P as a function of reinforcement -% and oddball rates, assuming there are 9 (8 face +1 null) conditions. -% p*total_trial would return the number of required trials to maintain a -% desired number of trials. P2 is the same but probabilities are computed -% without taking null condition into account. -% -% Use together with seq_feargen_FirstOrderBalanced. - - -%equatiom to solve following discussion with LK -%1 = 9p + rr./(1-rr)*p + ro; (nothing magic). -%p = 1/sum(....) - -%a function handle to get to the number of UCSs to present given a rate and -%knowledge about csp. -f = @(csp,p) p*csp./(1-p); - -p = (1-oddball)./(9+rr./(1-rr));%solve for p -p = [repmat(p,1,9) p*f(1,rr) oddball];%return a vector of p - - -%do the same without the null condition -p2 = (1-oddball)./(8+rr./(1-rr));%solve for p -p2 = [repmat(p2,1,8) p2*f(1,rr) oddball];%return a vector of p - - - - - - - - diff --git a/seq_feargen_information.m b/seq_feargen_information.m deleted file mode 100644 index 95eb76d..0000000 --- a/seq_feargen_information.m +++ /dev/null @@ -1,174 +0,0 @@ -function [out]=seq_feargen_information(s,varargin) -%[out]=seq_feargen_information(s,varargin) -% -% Will spit out interesting information on the sequences S. Interesting -% stuff are also shown as a figure. Assumes the last and last -1 are UCS -% and oddballs, respectively. OUT contains all the information. Use -% VARARGIN flag to turn off visualizations or verbose. [0 0] -% no figure, no verbose, [1 0], only figure, [0 1] only vervose. Default -% [1 1]. -% -% - -verbose = 1; -fig = 1; -if nargin > 1 - fig = varargin{1}(1); - verbose = varargin{1}(2); -end -%%set some constants -nummods = 10;%number of time bin in the FIR matrix -odd_id = 9; -ucs_id = 10; -null_id = 0; -%% -s = s(:); -tcond = length(unique(s));%with the null event -tstimcond = max(unique(s));%stimulus showing conditions i.e. without the null -conds = 0:tstimcond; -out.ttrial = length(s); -if verbose - fprintf('\n\n\n\n\n'); - fprintf('Total trial: %g\n',out.ttrial); - fprintf('%g and %g are considered as UCS and oddball, respectively\n',ucs_id,odd_id); - fprintf('Probability of different conditions:\n'); -end -count = zeros(1,tstimcond); -for c = 1:tcond - count(c) = sum(s == conds(c)); - if verbose - fprintf('Cond %g: %g (%g)\n',conds(c),count(c),count(c)./out.ttrial); - end -end - -ucs = sum(s == ucs_id); -csp = sum(s == 2); -out.rr = ucs./(ucs+csp)*100; - -odd = sum(s == odd_id); -out.or = odd./out.ttrial*100; -if verbose - fprintf('=====================================\n'); - fprintf('RRei: %g percent.\n',out.rr); - fprintf('=====================================\n'); - fprintf('ROdd: %g percent.\n',out.or); - fprintf('=====================================\n'); - fprintf('Transition Check\n'); -end -n = hist3([s(1:end-1) s(2:end)],{conds conds}); -[dummy_eff dummy_det] = calc_meffdet(s, 10 , tstimcond, 3); -[~,~,max_det,max_eff] = tcurve(tstimcond,10,length(s)); -tmaxeff = out.ttrial/(2*(tcond)*10); -eff_norm = dummy_eff(1)./max_eff(1); -if verbose - fprintf('=====================================\n'); - fprintf('Efficiency: %g\n',dummy_eff(1)); - fprintf('Max efficiency: %g\n',tmaxeff); - fprintf('Normalized efficiency: %g percent\n',eff_norm(1)*100 ); - fprintf('Power: %g\n',dummy_det(1)); - fprintf('Normalized power: %g\n',dummy_det(1)/max_det(1)*100); - fprintf('=====================================\n'); - for isis = [1 2.5 3 6] - fprintf('Expected duration: ISI of %g s -> %g minutes..\n',isis,isis*out.ttrial/60); - end -end -%% get the FIR matrix and efficiencies -[X,CX] = seq_seq2fir(s,nummods); -[effmat] = calc_meffdet(s,nummods,tstimcond,eye(out.ttrial)); -[~,~,~,tmaxeff] = tcurve(tstimcond,nummods,out.ttrial,0); -[~, v] = eig(CX(1:(tstimcond-2)*nummods,1:(tstimcond-2)*nummods)); -%% compute also the entropies -out.ent_order = 1:5; -for order = 1:5 - [out.ent(order),out.ent0,out.entmax] = calcent(s,order); -end -%% viz stuff. -if fig - figure(1000); - clf; - nr = 3; - nc = 4; - % - subplot(nr,nc,1:3); - plot(s,'.-','markersize',10);hold on; - plot(find(s == tstimcond-1),s(s == tstimcond-1),'+r','markersize',10); - plot(find(s == tstimcond),s(s == tstimcond),'sg','markersize',10); - xlabel('trials') - set(gca,'ytick',0:tstimcond,'yticklabel',{'N' '1' '2' '3' '4' '5' '6' '7' '8' 'UCS' 'ODD'}) - grid on; - title(sprintf('the sequence (length: %g, duration: %3.3g m (ISI:3s))',out.ttrial,3*out.ttrial/60)) - box off - hold off; - ylim([0 tstimcond+1]) - % - subplot(nr,nc,4); - imagesc(n); - thincolorbar('vertical'); - title('2nd order Transition Matrix'); - set(gca,'ytick',1:tstimcond+1,'yticklabel',{'N' '1' '2' '3' '4' '5' '6' '7' '8' 'UCS' 'ODD'}) - set(gca,'xtick',1:tstimcond+1,'xticklabel',{'N' '1' '2' '3' '4' '5' '6' '7' '8' 'U' 'O'}) - % - subplot(nr,nc,5) - imagesc(X);colormap('jet'); - title('FIR matrix') - set(gca,'xtick',[],'ytick',[]) - xlabel('conditions');ylabel('trials') - % - subplot(nr,nc,6) - bar([1./mean(effmat(2:tstimcond)) ;1./effmat(2:tstimcond+1)],'k') - hold on - plot(xlim,[tmaxeff tmaxeff],'r--') - ylim([0 tmaxeff]*1.5); - xlim([0 tstimcond+1+1]) - box off - xlabel('conditions'); - ylabel('efficiency'); - set(gca,'xticklabel',{'All' '1' '2' '3' '4' '5' '6' '7' '8' 'U' 'O'}) - title(sprintf('Eff. of estimation(%2.4g %% ) ',1./mean(effmat(2:tstimcond))/tmaxeff*100)) - hold off - % - subplot(nr,nc,7) - bar(1./effmat(tstimcond+2:end),'k') - hold on; - plot(xlim,[tmaxeff tmaxeff],'r--'); - hold off - title('Eff. of contrasts') - axis tight; - ylim(ylim*1.5); - xlim([0 length(effmat)-tstimcond] ); - box off; - % - subplot(nr,nc,8) - bar([0 out.ent_order]+1, [ out.ent0 out.ent],'k') - hold on - xlabel('n^{th} order') - ylabel('entropy') - box off - axis tight; - plot(xlim,[out.entmax out.entmax],'r--') - ylim(ylim*1.2); - title('entropy') - grid on; - % - subplot(nr,nc,9) - imagesc(cov(X)); - thincolorbar('vertical'); - title(sprintf('covariance (rank: %g (%g))',rank(cov(X)),size(X,2)));axis off; - % - subplot(nr,nc,10) - plot(diag(v),'ok-') - title('Eigenvalue spectrum') - box off; - % - subplot(nr,nc,11) - hist(diff(find(s ~= 0))); - title('Distribution of ISIs') - box off; -end -%% create output -out.eff_overall = 1./mean(effmat(2:tstimcond)); -out.eff_estimate = 1./effmat(2:tstimcond+1); -out.eff_contrasts = 1./effmat(tstimcond+2:end); -out.eff_max = tmaxeff; -out.eff_norm = out.eff_overall./out.eff_max*100; -out.probability = count./out.ttrial; diff --git a/seq_feargen_mseq_pruned.m b/seq_feargen_mseq_pruned.m deleted file mode 100644 index 31d45eb..0000000 --- a/seq_feargen_mseq_pruned.m +++ /dev/null @@ -1,44 +0,0 @@ -function [s]=seq_feargen_mseq_pruned(method,pr,po) -%1: concat power 2 and then prune -%2: same as 1 but null it instead of pruning -%22: same for conditioning -%3: generate power 3 and the prune -%4: same as 3 but null it instead of pruning - - -if method == 1 - %% will prune a 360 trial long mseq, the result is a bit longer than 300 but comparable - s = []; - for n = 1:3 - s = [s; mseq2(11,2,0,RandSample(1:18,[1 1]))]; - end - [s] = seq_feargen_prune(s,pr,po); - -elseif method == 2 - %% will zero all the unnecessary trials, the result is 240 trial long and extremely efficient. - %% maybe this is the one I am looking since ages now ;) - - %%use this if you want to combine two shorter seqs into one - % s = []; - % for n = 1:2 - % s = [s; mseq2(11,2,RandSample(1:100,[1 1]),RandSample(1:18,[1 1]))]; - % end - [s] = mseq2(11,2,RandSample(1:100,[1 1]),RandSample(1:18,[1 1])); - [s] = seq_feargen_prune(s,pr,po,0); - %seq_feargen_information(s); - -elseif method ==22; - %this is for conditioning - [s] = mseq2(5,3,RandSample(1:100,[1 1]),RandSample(1:18,[1 1])); - [s] = seq_feargen_prune(s,pr,po,0); - %seq_feargen_information(s); - -elseif method == 3 - %WORK to be done: GET AN M-sequence and equalize the transition to UCS - %and ODDBALL trials that is it. - s = mseq2(11,3,0,RandSample(1:18,[1 1])); - [s] = seq_feargen_prune(s,pr,po,0); - s = s(1:300); -elseif method == 4 - -end \ No newline at end of file diff --git a/seq_feargen_null_ucsodd.m b/seq_feargen_null_ucsodd.m deleted file mode 100644 index 6d72c6d..0000000 --- a/seq_feargen_null_ucsodd.m +++ /dev/null @@ -1,64 +0,0 @@ -function [s] = seq_feargen_null_ucsodd(s,rr,or,varargin) -%"null" given sequence so that transitions from UCS OR ODDBALL are -%balanced. This would mean same column sums in the transition matrix (over -%rows UCS and oddballs) - -remove = 1; -if nargin == 4 - remove = 0; -end - -conds = unique(s);%all conditions + nulls -ttrial = length(s); - -%prune odds -if ~isempty(or) - o_i = find(s==max(conds));%oddball index - o_trial_current = length(o_i);%number of current oddballs - o_trial_target = round(ttrial*or);%number of oddballs to have - - - %find cond after oddball - fo = hist(s(o_i+1),max(conds)+1); - imagesc(fo) - %collects indices of transitions from oddball to cond=i and builts a - %vector out of it - for i=1:max(conds) - trans_i(i,:)=Shuffle(strfind(s', [max(conds) i])); - end - - %now i just take the first column completely and set it to - %zero/varargin - while length(find(s==max(conds))) ~= o_trial_target - if remove - s(trans_i(:,1)) = []; - trans_i(:,1)=[]; - s(trans_i(1:2:end))=[]; - - else - s(trans_i(:,1)) = varargin{1}; - trans_i(:,1)=[]; - s(trans_i(1:2:end))= varargin{1}; - - end - end - fprintf('%g oddballs are deleted/replaced...\n',o_trial_current - o_trial_target); -end - -%prune ucs -if ~isempty(rr) - u_i=find(s==max(conds)-1); %indexes of ucs trials - nucs = round(sum(s == 4)*(rr./(1-rr)));%how many do we need to have? - tucs = sum(s == (max(conds)-1)); - - %%%%stopped work here... - if remove - s(randsample(find(s == (max(conds)-1)),tucs-nucs)) = []; - else - s(randsample(find(s == (max(conds)-1)),tucs-nucs)) = varargin{1}; - end - fprintf('%g UCSs are deleted/replaced...\n',tucs-nucs); -end - -end - diff --git a/seq_feargen_prune.m b/seq_feargen_prune.m deleted file mode 100644 index 9630258..0000000 --- a/seq_feargen_prune.m +++ /dev/null @@ -1,42 +0,0 @@ -function [s]=seq_feargen_prune(s,rr,or,varargin) -%[s]=seq_feargen_prune(s,rr,or,varargin) -% -% Prunes a balanced sequence for target UCS and oddball conditions so -% that the final sequence has a RR and OR occurence probability. RR and -% RO are between 0 and 1. If VARARGIN is given, instead of removal, a -% replacement is realized by the value in VARARGIN. Use 0 to switch -% events to null. - -remove = 1; -if nargin == 4 - remove = 0; -end - -conds = unique(s);%all conditions + nulls -ttrial = length(s); -%prune odds -if ~isempty(or) - o_i = s == max(conds);%oddball index - o_trial_current = sum(o_i);%number of current oddballs - o_trial_target = round(ttrial*or);%number of oddballs to have - if remove - s( randsample(find(s == max(conds)), o_trial_current - o_trial_target) ) = []; - else - s( randsample(find(s == max(conds)), o_trial_current - o_trial_target) ) = varargin{1}; - end - fprintf('%g oddbals are deleted/replaced...\n',o_trial_current - o_trial_target); -end - -%prune ucs -if ~isempty(rr) - %nucs = round(sum(s == 4)*(rr./(1-rr)));%4 gives a problem when @ - %conditioning... - nucs = round(sum(s == 2)*(rr./(1-rr)));%how many do we need to have? - tucs = sum(s == (max(conds)-1)); - if remove - s(randsample(find(s == (max(conds)-1)),tucs-nucs)) = []; - else - s(randsample(find(s == (max(conds)-1)),tucs-nucs)) = varargin{1}; - end - fprintf('%g UCSs are deleted/replaced...\n',tucs-nucs); -end diff --git a/seq_information.m b/seq_information.m deleted file mode 100644 index 0647c2c..0000000 --- a/seq_information.m +++ /dev/null @@ -1,231 +0,0 @@ -function [out]=seq_information(s,isi,varargin) -%[out]=seq_information(s,isi,varargin) -% -% Will spit out interesting information on the sequences S. Interesting -% stuff are also shown as a figure. Assumes the last and last -1 are UCS -% and oddballs, respectively. OUT contains all the information. -% -% If ISI is [], then a constant ISI is assumed. The jitter in this case -% is implemented using null trials. However ISI can also be explicitely -% given. This only matters for the measurements of efficiencies. -% -% Use VARARGIN flag to turn off visualizations or verbose. [0 0] -% no figure, no verbose, [1 0], only figure, [0 1] only vervose. Default -% [1 1]. -% -% This version attempts to achieve sequence analysis independent of the -% study. - -verbose = 1; -fig = 1; -if nargin > 2 - fig = varargin{1}(1); - verbose = varargin{1}(2); -end -%%set some constants -nummods = 10;%number of time bin in the FIR matrix -odd_id = 10; -ucs_id = 9; -null_id = 0; -%% -s = s(:); -tcond = length(unique(s));%with the null event -tstimcond = max(unique(s));%stimulus showing conditions i.e. without the null -conds = 0:tstimcond; -out.ttrial = length(s); -if verbose - fprintf('\n\n\n\n\n'); - fprintf('Total trial: %g\n',out.ttrial); - fprintf('%g and %g are considered as UCS and oddball, respectively\n',ucs_id,odd_id); - fprintf('Probability of different conditions:\n'); -end -count = zeros(1,tstimcond); -for c = 1:tcond - count(c) = sum(s == conds(c)); - if verbose - fprintf('Cond %g: %g (%g)\n',conds(c),count(c),count(c)./out.ttrial); - end -end - -ucs = sum(s == ucs_id); -csp = sum(s == 2); -out.rr = ucs./(ucs+csp)*100; - -odd = sum(s == odd_id); -out.or = odd./out.ttrial*100; -if verbose - fprintf('=====================================\n'); - fprintf('RRei: %g percent.\n',out.rr); - fprintf('=====================================\n'); - fprintf('ROdd: %g percent.\n',out.or); - fprintf('=====================================\n'); -end -%% -fprintf('Transition Check\n'); -n = hist3([s(1:end-1) s(2:end)],{conds conds}); -[dummy_eff dummy_det] = calc_meffdet(s, 10 , tstimcond, 3); -[~,~,max_det,max_eff] = tcurve(tstimcond,10,length(s)); -tmaxeff = out.ttrial/(2*(tcond)*10); -eff_norm = dummy_eff(1)./max_eff(1); -if verbose - fprintf('=====================================\n'); - fprintf('Efficiency: %g\n',dummy_eff(1)); - fprintf('Max efficiency: %g\n',tmaxeff); - fprintf('Normalized efficiency: %g percent\n',eff_norm(1)*100 ); - fprintf('Power: %g\n',dummy_det(1)); - fprintf('Normalized power: %g\n',dummy_det(1)/max_det(1)*100); - fprintf('=====================================\n'); - for isis = [1 2.5 3 6] - fprintf('Expected duration: ISI of %g s -> %g minutes..\n',isis,isis*out.ttrial/60); - end -end -%% compute second-order optimality. -fprintf('=====================================\n'); -fprintf('=====================================\n'); -sopt = seq_SecondOrderBalanceOptimality(s); -fprintf('If this sequence was randomized, it would have a '); -seq_SecondOrderBalanceOptimality(Shuffle(s)); -fprintf('And if the sequence was sorted, it would be '); -seq_SecondOrderBalanceOptimality(sort(s)); -fprintf('=====================================\n'); -fprintf('=====================================\n'); -fprintf('=====================================\n'); -%% compute design efficiency, this is taken from: -% Experimental Design: Efficiency, -% Coding, and Choice Designs Warren F. Kuhfeld - -if isempty(isi) - isi = ones(length(s),1)*3; -end -dm = seq_designmatrix(s,isi); -dm = dm(:,1:8); - -max_efficiency = 1./trace(inv(diag(sum(dm)))); -fprintf('The maximum efficiency is %g...\n',max_efficiency); -efficiency = 1./(trace(inv(dm'*dm))); -fprintf('Efficiency of this design is %g (%g percent)...\n',efficiency,100*efficiency./max_efficiency); -out.dm = dm; -fprintf('=====================================\n'); -fprintf('=====================================\n'); -fprintf('=====================================\n'); -%% get the FIR matrix and efficiencies -try -[X,CX] = seq_seq2fir(s,nummods); -[effmat] = calc_meffdet(s,nummods,tstimcond,eye(out.ttrial)); -[~,~,~,tmaxeff] = tcurve(tstimcond,nummods,out.ttrial,0); -[~, v] = eig(CX(1:(tstimcond-2)*nummods,1:(tstimcond-2)*nummods)); -end -%% compute also the entropies -out.ent_order = 1:5; -for order = 1:5 - [out.ent(order),out.ent0,out.entmax] = calcent(s,order); -end -%% viz stuff. -if fig - figure(1000); - clf; - nr = 4; - nc = 4; - % - subplot(nr,nc,1:3); - plot(s,'.-','markersize',10);hold on; - plot(find(s == ucs_id),s(s == ucs_id),'+r','markersize',10); - plot(find(s == odd_id),s(s == odd_id),'sg','markersize',10); - xlabel('trials') - set(gca,'ytick',0:tstimcond,'yticklabel',{'N' '1' '2' '3' '4' '5' '6' '7' '8' 'UCS' 'ODD'}) - grid on; - title(sprintf('the sequence (length: %g, duration: %3.3g m (ISI:3s))',out.ttrial,3*out.ttrial/60)) - box off - hold off; - ylim([0 tstimcond+1]) - % - subplot(nr,nc,4); - imagesc(n); - colormap jet - thincolorbar('vertical'); - title(sprintf('2nd order Transition Matrix (%g)',sopt)); - set(gca,'ytick',1:tstimcond+1,'yticklabel',{'N' '1' '2' '3' '4' '5' '6' '7' '8' 'UCS' 'ODD'}) - set(gca,'xtick',1:tstimcond+1,'xticklabel',{'N' '1' '2' '3' '4' '5' '6' '7' '8' 'U' 'O'}) - % - subplot(nr,nc,5) - imagesc(X);colormap('jet'); - title('FIR matrix') - set(gca,'xtick',[],'ytick',[]) - xlabel('conditions');ylabel('trials') - % - subplot(nr,nc,6) - bar([1./mean(effmat(2:tstimcond)) ;1./effmat(2:tstimcond+1)],'k') - hold on - plot(xlim,[tmaxeff tmaxeff],'r--') - ylim([0 tmaxeff]*1.5); - xlim([0 tstimcond+1+1]) - box off - xlabel('conditions'); - ylabel('efficiency'); - set(gca,'xticklabel',{'All' '1' '2' '3' '4' '5' '6' '7' '8' 'U' 'O'}) - title(sprintf('Eff. of estimation(%2.4g %% ) ',1./mean(effmat(2:tstimcond))/tmaxeff*100)) - hold off - % - subplot(nr,nc,7) - bar(1./effmat(tstimcond+2:end),'k') - hold on; - plot(xlim,[tmaxeff tmaxeff],'r--'); - hold off - title('Eff. of contrasts') - axis tight; - ylim(ylim*1.5); - xlim([0 length(effmat)-tstimcond] ); - box off; - % - subplot(nr,nc,8) - bar([0 out.ent_order]+1, [ out.ent0 out.ent],'k') - hold on - xlabel('n^{th} order') - ylabel('entropy') - box off - axis tight; - plot(xlim,[out.entmax out.entmax],'r--') - ylim(ylim*1.2); - title('entropy') - grid on; - % - subplot(nr,nc,9) - imagesc(cov(X)); - thincolorbar('vertical'); - title(sprintf('covariance (rank: %g (%g))',rank(cov(X)),size(X,2)));axis off; - % - try - subplot(nr,nc,10) - plot(diag(v),'ok-') - title('Eigenvalue spectrum') - box off; - end - % - subplot(nr,nc,11) - if length(unique(isi)) > 1 - hist(isi); - else - hist(diff(find(s ~= 0))); - end - title('Distribution of ISIs') - box off; - % - subplot(nr,nc,13) - [e v] = eig(inv(dm'*dm)); - bar(diag(v)) - title(sprintf('ev of the dm')); - % - subplot(nr,nc,14) - imagesc(dm); - colormap gray - title(sprintf('design matrix eff(max):\n %2.2g(%2.2g))',efficiency,max_efficiency)); - box off; - axis tight; -end -%% create output -out.eff_overall = 1./mean(effmat(2:tstimcond)); -out.eff_estimate = 1./effmat(2:tstimcond+1); -out.eff_contrasts = 1./effmat(tstimcond+2:end); -out.eff_max = tmaxeff; -out.eff_norm = out.eff_overall./out.eff_max*100; -out.probability = count./out.ttrial; diff --git a/seq_optseq22dm.m b/seq_optseq22dm.m deleted file mode 100644 index d55a49a..0000000 --- a/seq_optseq22dm.m +++ /dev/null @@ -1,54 +0,0 @@ -function [dm,cond] = seq_optseq22dm(filename) - -%read the optseq -[time cond c d e] = textread(filename,'%f%f%s%s%s','delimiter','\t'); -time = time/2; -i = cond == 0; -cond(i) = []; -time(i) = []; -time(end+1) = time(end); - -for i = 1:length(cond) - seq.cond_id(i) = cond(i); - seq.isi(i) = time(i+1)-time(i); -end -%% IRF -sampling_rate = 2; -TR = sampling_rate;%in seconds -fMRI_T = 16;%spm_get_defaults('stats.fmri_t'); -fMRI_T0 = 1;%spm_get_defaults('stats.fmri.t0');in spm8 it was 1, so I am keeping it here -xBF.T = fMRI_T; -xBF.T0 = fMRI_T0; -xBF.dt = TR/xBF.T; -xBF.UNITS = 'scans'; -xBF.Volterra = 1; -xBF.name = 'hrf'; -xBF = spm_get_bf(xBF); -%% -Sess = []; -for nt = 1:length(unique(seq.cond_id)); - Sess.U(nt).dt = xBF.dt;%- time bin (seconds) - Sess.U(nt).name = {sprintf('%02d',nt)};%- cell of names for each input or cause - %no parametric modulation here - Sess.U(nt).dur = 0;%- durations (in SPM.xBF.UNITS) - Sess.U(nt).P.name = 'none'; - Sess.U(nt).P.P = 'none'; - Sess.U(nt).P.h = 0;%- order of polynomial expansion - Sess.U(nt).P.i = 1;%- sub-indices of u pertaining to P -end -SPM.xBF = xBF; -cums = cumsum(seq.isi); -SPM.nscan = max(cums)+5; -SPM.Sess = Sess; - - -%% get the onsets -for i = 1:length(unique(seq.cond_id));%one regressor for each condition - SPM.Sess.U(i).ons = cums( seq.cond_id == i );%- onsets (in SPM.xBF.UNITS) -end -SPM.Sess.U = spm_get_ons(SPM,1); -%% -% Convolve stimulus functions with basis functions -[X,Xn,Fc] = spm_Volterra(SPM.Sess.U,SPM.xBF.bf,SPM.xBF.Volterra); -% Resample regressors at acquisition times (32 bin offset) -dm = X((0:(SPM.nscan - 1))*fMRI_T + fMRI_T0 + 32,:); \ No newline at end of file diff --git a/seq_optseq22s.m b/seq_optseq22s.m deleted file mode 100644 index 6561d30..0000000 --- a/seq_optseq22s.m +++ /dev/null @@ -1,7 +0,0 @@ -function [s]=seq_optseq22s(filename) -%seq_optseq22s(filename) -% -% Reads the opt2 sequence from FILENAME and returns a sequence vector. - -%read the optseq -[time s c d e] = textread(filename,'%f%f%s%s%s','delimiter','\t'); diff --git a/seq_pruned_mseq.m b/seq_pruned_mseq.m deleted file mode 100644 index 677b6a8..0000000 --- a/seq_pruned_mseq.m +++ /dev/null @@ -1,35 +0,0 @@ -function [ms]=seq_pruned_mseq(ttrial,rr,or) -%[ms]=seq_pruned_mseq(ttrial,rr,or) -% -% Generates a pseudo-maximum length sequence, pruned for UCS and oddball -% conditions. - - - -%randomly create an mseq with 11^2 using random taps -ms0 = []; -for r = randsample(1:18,18); - [ms0]=[ms0 ; mseq2(11,2,[],r)]; -end -OK = 1; -%ttrial is the target trials, however we have to cut it a bit longer so -%that when pruned target trial is reached. -ttrial2 = ttrial; -while OK - ms = ms0(1:ttrial2); - %prune - conds = unique(ms);%all conditions - o_i = ms == max(conds);%oddball index - o_trial_current = sum(o_i);%number of current oddbalss - o_trial_target = round(ttrial*or);%number of oddballs to have - ms( randsample(find(ms == max(conds)), o_trial_current - o_trial_target) ) = []; - - nucs = round(sum(ms == 4)*(rr./(1-rr)));%how many do we need to have? - tucs = sum(ms == (max(conds)-1)); - ms(randsample(find(ms == (max(conds)-1)),tucs-nucs)) = []; - if length(ms) == ttrial - OK = 0; - else - ttrial2 = ttrial2 + 1; - end -end \ No newline at end of file diff --git a/seq_seq2dm.m b/seq_seq2dm.m deleted file mode 100644 index 3e68fb7..0000000 --- a/seq_seq2dm.m +++ /dev/null @@ -1,45 +0,0 @@ -function [X]=seq_seq2dm(seq) -%[X]=seq_seq2dm(seq) -% -% SEQ is the output of seq_SecondOrderBalancedSequence or compatible -% (e.g. presentation protocol file). This function returns a spm-like -% design matrix based on canonical HRF definition from SEQ. SEQ has to -% have ISI and COND_ID fields. - -cums = cumsum(seq.isi); -% -TR = 2;%in seconds -fMRI_T = 16;%spm_get_defaults('stats.fmri_t'); -fMRI_T0 = 1;%spm_get_defaults('stats.fmri.t0');in spm8 it was 1, so I am keeping it here -xBF.T = fMRI_T; -xBF.T0 = fMRI_T0; -xBF.dt = TR/xBF.T; -xBF.UNITS = 'scans'; -xBF.Volterra = 1; -xBF.name = 'hrf'; -xBF = spm_get_bf(xBF); -%% -Sess = []; -for nt = 1:length(unique(seq.cond_id)); - Sess.U(nt).dt = xBF.dt;%- time bin (seconds) - Sess.U(nt).name = {sprintf('%02d',nt)};%- cell of names for each input or cause - %no parametric modulation here - Sess.U(nt).dur = 0;%- durations (in SPM.xBF.UNITS) - Sess.U(nt).P.name = 'none'; - Sess.U(nt).P.P = 'none'; - Sess.U(nt).P.h = 0;%- order of polynomial expansion - Sess.U(nt).P.i = 1;%- sub-indices of u pertaining to P -end -SPM.xBF = xBF; -SPM.nscan = max(cums)+5; -SPM.Sess = Sess; -%% get the onsets -for i = 1:length(unique(seq.cond_id));%one regressor for each condition - SPM.Sess.U(i).ons = cums( seq.cond_id == i );%- onsets (in SPM.xBF.UNITS) -end -SPM.Sess.U = spm_get_ons(SPM,1); -%% -% Convolve stimulus functions with basis functions -[X,~,~] = spm_Volterra(SPM.Sess.U,SPM.xBF.bf,SPM.xBF.Volterra); -% Resample regressors at acquisition times (32 bin offset) -X = X((0:(SPM.nscan - 1))*fMRI_T + fMRI_T0 + 32,:); \ No newline at end of file diff --git a/seq_seq2fir.m b/seq_seq2fir.m deleted file mode 100644 index 5e754de..0000000 --- a/seq_seq2fir.m +++ /dev/null @@ -1,22 +0,0 @@ -function [X,CX,eff] = seq_seq2fir(s,nummods) - -%% -s = s(:); -baseveclen = length(s)+nummods; -basevec = s; -nevents = max(unique(s)); -order = 3; -for k = 1:nevents - thispattern = zeros(baseveclen,1); - thispattern(find(basevec == k)) = 1; - span = (1:nummods) + (k-1)*nummods; - X(:,span) = toeplitz(thispattern,[thispattern(1) zeros(1,nummods-1)]); -end -% -X = demean(X); -% -% S = legendremat(order,baseveclen ); -% PS = eye(baseveclen)-S*pinv(S); -PS = eye(baseveclen); -K = X'*PS*X; -CX = inv(K); diff --git a/seq_treatgen.m b/seq_treatgen.m deleted file mode 100644 index ba9916a..0000000 --- a/seq_treatgen.m +++ /dev/null @@ -1,123 +0,0 @@ -%% testphase -for nsub = 1:200; - for csp = 1:8; - others = setdiff(1:8,csp); - cond_id = []; - ok = 0; - while ~ok - ok = 1 ; - %random - s = Shuffle([repmat(others,[1 6]) ones(1,3)*csp ones(1,3)*9]); - s = [0 s]; - %constraints - % never two ucs after each other - ind = find(s==9); - if any(ismember(find(diff(s)==0),ind)) - ok = 0; - end - % one of the first three trials has to be an ucs - if all(find(s==9)> 3) - ok = 0; - end - %ucs not in the last 5 trials - if any(find(s==9) > length(s)-5) - ok = 0; - end - %not too close to each other - if any(diff(find(s==9))<8) - ok = 0; - end -% % not too far away also -% % if any(diff(find(s==9))>15) -% % ok = 0; -% % end - end - for n = 1:9;fprintf('%g: %g\n',n,sum(s == n));end - % put the data to format usable by the presentation script. - seq2 = []; - seq2.cond_id = s; - seq2.ucs = s == 9; - seq2.tonicpain = seq_BalancedDist(s,[5 6 7]); %take as many isi possibilities as reps for conds -% seq2.tonicpain(s ==9) = Shuffle([5 6 7 5.5 6.5]); % because there is only two, it would not be distributed the same across sequences otherwise - seq2.tonicpain(s ==0) = 6; % because there is only two, it would not be distributed the same across sequences otherwise -% seq2.isi2 = 6 - seq2.isi1; -% seq2.isi3 = seq_BalancedDist(s,[.5 .75 1]); -% seq2.poststim = 1 - seq2.isi3; - seq2.ratepain = zeros(length(s),1); - seq2.ratepain(mod(1:length(s),floor(length(s)/3))==1) = 1; - seq2.ratepain(end) = 0; - seq2.stim_id = s; - seq2.stim_id(s==9) = csp; - seq2.dist = MinimumAngle((seq2.stim_id-1)*45,(csp-1)*45); - seq2.tTrial = length(seq2.cond_id); - %ucs=500 - seq2.dist(seq2.cond_id == 9)= 500; - seq2.dist(seq2.cond_id == 0)= 3000; - % balance the cross Positions, left right for the face conditions. - seq2.CrossPosition = seq_feargen_fixcross(seq2); - seq2.CrossPosition(1,:) = seq2.CrossPosition(end,:); - if nsub == 1 - fprintf('seq is about %g minutes long and has %g trials...\n',(3*10+length(s)*(1.5+1+6+5)+sum(seq2.tonicpain))/60,length(s)); - end - % - seq(nsub,csp) = seq2; - end -end -%% conditioning -for nsub = 1:200; - nsub - for csp = 1:8; - csn = mod( csp + 8/2-1, 8)+1; - cond_id = []; - ok = 0; - while ~ok - ok =1 ; - %random - s = [0 2 3 Shuffle([ones(1,5) ones(1,9)*2 ones(1,4)*3])]; % 1 = CSP 2 = CSN 3 = UCS - %constraints -% % one of the first three trials has to be an ucs -% if all(find(s==3)> 3) -% ok = 0; -% end - % don't repeat any condition three times - if any(diff(diff(s))==0) - ok = 0; - end - % never more than 8 trials without reinforcement - if any(diff(find(s==3))>5) - ok = 0; - end - end - if nsub == 200;for n = 1:length(unique(s));fprintf('%g: %g\n',n,sum(s == n));end;end - % put the data to format usable by the presentation script. - seq2 = []; - seq2.cond_id = s; - seq2.ucs = s == 3; - seq2.tonicpain = seq_BalancedDist(s,[5 6 7 5.5 6.5]); %take as many isi possibilities as reps for conds -% seq2.tonicpain(s == 3) = Shuffle([5 6 7 5.5 6.5]); % because there is an equal number, it would not be distributed the same across sequences, i.e. peoples otherwise - seq2.tonicpain(s == 0) = 6; % because there -% seq2.isi2 = 6 - seq2.isi1; -% seq2.isi3 = seq_BalancedDist(s,[.5 .75 1]); -% seq2.poststim = 1 - seq2.isi3; - seq2.ratepain = zeros(length(s),1); - seq2.ratepain(mod(1:length(s),floor(length(s)/2))==1) = 1; - seq2.ratepain(end) = 0; %is taken care of anyway in the experiment - seq2.stim_id = s; - seq2.stim_id(s==1) = csp; - seq2.stim_id(s==2) = csn; - seq2.stim_id(s==3) = csp; - seq2.dist = MinimumAngle((seq2.stim_id-1)*45,(csp-1)*45); - seq2.tTrial = length(seq2.cond_id); - %ucs=500 - seq2.dist(seq2.ucs)= 500; - seq2.dist(seq2.cond_id==0) = 3000; - % balance the cross Positions, left right for the face conditions. - seq2.CrossPosition = seq_feargen_fixcross(seq2); - seq2.CrossPosition(1,:) = seq2.CrossPosition(end,:); - if nsub == 1 - fprintf('seq is about %g minutes long and has %g trials...\n',(length(s)*(1.5+.85+6+5)+sum(seq2.tonicpain))/60,length(s)); - end - % - seq(nsub,csp) = seq2; - end -end \ No newline at end of file diff --git a/start_cogent.m b/start_cogent.m deleted file mode 100755 index fb63129..0000000 --- a/start_cogent.m +++ /dev/null @@ -1,195 +0,0 @@ -function start_cogent -% START_COGENT initialises Matlab for running Cogent 2000 commands. -% -% Description: -% Start initialise Malab for running Cogent 2000. Call this after devices have been configued. -% -% Usage: -% START_COGENT -% -% Arguments: -% NONE -% -% Examples: -% -% See also: -% STOP_COGENT, TIME, CONFIG_DATA, CONFIG_KEYBOARD, CONFIG_PARALLEL, CONFIG_SOUND, CONFIG_DEVICE, -% CONFIG_LOG, CONFIG_RESULTS, CONFIG_DISPLAY CONFIG_MOUSE, CONFIG_SERIAL -% -% Cogent 2000 function. - -global cogent; -cgloadlib; % added 14/03/2003. EF. (see line 64 also) -cogent.version = '1.30'; % updated to v1.25 14/04/03 - -cogstd( 'soutstr', [ 'Cogent 2000 Version ' num2str(cogent.version) char(10) ] ) -cogstd( 'svers' ); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Set process priority to high -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -cogprocess( 'version' ); -cogent.priority.class = cogprocess( 'enumpriorities' ); -cogent.priority.old = cogprocess( 'getpriority' ); -cogprocess( 'setpriority', cogent.priority.class.high ); - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Initialise parallel ports -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% 4-4-2002 "cogport" obsolete -% Replaced by "inportb" & outportb" which need no initialisation -%if isfield( cogent, 'lpt' ) -% cogport( 'version' ); -% cogport( 'initialise' ); -% cogent.lpt = cogport( 'getlpts' ); -%end - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Initialise log file -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if isfield(cogent,'log') & isfield(cogent.log,'filename') - cogstd( 'sLogFil', cogent.log.filename ); -end -cogent.log.time=0; - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Initialise display -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if isfield( cogent, 'display' ) - - % Clear screen to background colour - % cgloadlib; % removed 14/03/2003. EF. This comamnd is now run unconditionally (see line 22) - cgopen( cogent.display.size(1), cogent.display.size(2) , cogent.display.nbpp, 0, cogent.display.mode ); - bg = cogent.display.bg; - fg = cogent.display.fg; -% cgpencol( bg(1), bg(2), bg(3) ); % Add palette mode 27-3-01 - if cogent.display.nbpp~=8 - cgpencol( bg(1), bg(2), bg(3) ); - else - cgpencol( bg(1) ); - end - cgrect; - cgflip; -% cgpencol( fg(1), fg(2), fg(3) ); % Add palette mode 27-3-01 - if cogent.display.nbpp~=8 - cgpencol( fg(1), fg(2), fg(3) ); - else - cgpencol( fg(1) ); - end - - % Create offscreen buffers - for i=1:cogent.display.number_of_buffers -% cgmakesprite( i, cogent.display.size(1), cogent.display.size(2), bg(1), bg(2), bg(3) ); % Add palette mode 27-3-01 - if cogent.display.nbpp~=8 - cgmakesprite( i, cogent.display.size(1), cogent.display.size(2), bg(1), bg(2), bg(3) ); - else - cgmakesprite( i, cogent.display.size(1), cogent.display.size(2), bg(1) ); - end % if - end % for - - % Setup drawing parameters -% cgpencol( cogent.display.fg(1), cogent.display.fg(2), cogent.display.fg(3) ); % Add palette mode 27-3-01 - if cogent.display.nbpp~=8 - cgpencol( cogent.display.fg(1), cogent.display.fg(2), cogent.display.fg(3) ); - else - cgpencol( cogent.display.fg(1) ); - end - cgfont( cogent.display.font, cogent.display.fontsize ); - - if isfield( cogent.display, 'scale' ) - cgscale( cogent.display.scale ); - end - -end - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Initialise sound -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if isfield( cogent, 'sound' ) - cogcapture( 'Version' ); - cogcapture( 'Initialise' ); - cogsound( 'Version' ); - cogsound( 'Initialise', cogent.sound.nbits, cogent.sound.frequency, cogent.sound.nchannels ); -end - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Load and initialise DirectInput if required -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if isfield(cogent,'keyboard') | isfield(cogent,'mouse') - coginput( 'Version' ); - coginput( 'Initialise' ); -end - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Initialise keyboard -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if isfield( cogent, 'keyboard' ) - hDevice = coginput( 'Create', 'keyboard', cogent.keyboard.mode, cogent.keyboard.queuelength ); - cogent.keyboard.hDevice = hDevice; - cogent.keyboard.map = coginput( 'GetMap', hDevice ); - coginput( 'Acquire', hDevice ); - if ( cogent.keyboard.polling_flag ) - coginput( 'StartPolling', hDevice, cogent.keyboard.resolution ); - end -end - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Initialise mouse -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if isfield( cogent, 'mouse' ) - cogent.mouse.hDevice = coginput( 'Create', 'mouse', cogent.mouse.mode ); - cogent.mouse.map = coginput( 'GetMap', cogent.mouse.hDevice ); - coginput( 'Acquire', cogent.mouse.hDevice ); - if ( cogent.mouse.polling_flag ) - coginput( 'StartPolling', cogent.mouse.hDevice, cogent.mouse.resolution ); - end -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Initialise serial -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if isfield( cogent, 'serial' ) - cogserial( 'version' ); - for i = 1 : length(cogent.serial) - port = cogent.serial{i}; - if ~isempty(port) - port.hPort = cogserial( 'open', port.name ); - - attr.Baud = port.baudrate; - attr.Parity = port.parity; - attr.StopBits = port.stopbits; - attr.ByteSize = port.bytesize; - cogserial( 'setattr', port.hPort, attr ); - cogserial( 'record', port.hPort, 200000 ); - - cogent.serial{i} = port; - end - end -end - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Initialise National Instruments DAQ DIO24 -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if isfield( cogent, 'dio24' ) - cogdio24( 'version' ); - cogdio24( 'initialise', cogent.dio24.deviceno ); - for i=1:length(cogent.dio24.input) - if ~isempty( cogent.dio24.input{i} ) - cogdio24( 'config', i, 0 ); - cogdio24( 'start', i, cogent.dio24.interval, 1000 ); - end - end -end - -% Set timer to 0 -cogstd( 'sgettime', 0 ); - -logstring( 'COGENT START' ); diff --git a/stimulus_sequences.mat b/stimulus_sequences.mat new file mode 100644 index 0000000..1a0ca90 Binary files /dev/null and b/stimulus_sequences.mat differ diff --git a/tool/calibrate_display.m b/tool/calibrate_display.m new file mode 100644 index 0000000..2110f1e --- /dev/null +++ b/tool/calibrate_display.m @@ -0,0 +1,121 @@ +function [ gammaTables1, displayBaselines, displayRanges, displayGammas, maxLevel, measurements, levels] = calibrate_display(numMeasures, ppd, gabor_dim_pix, varargin) +% Adapt psychtoolbox's CalibrateMonitorPhotometer to show two stimuli at +% different locations and to read measurements from a color hug. +Screen('Preference', 'SkipSyncTests', 1); +xpos = 0; +ypos = 0; +devices =1; + +screenid = min(Screen('Screens')); + +psychlasterror('reset'); +try + + % Open black window: + white = WhiteIndex(screenid); + black = BlackIndex(screenid); + grey = white / 2; + % Open the screen + [win, windowRect] = Screen('OpenWindow', screenid, grey); + maxLevel = Screen('ColorRange', win); + + % Compute presentation locations + xpos = xpos*ppd; + ypos = ypos*ppd; + [xCenter, yCenter] = RectCenter(windowRect); + xpos = xpos + xCenter; + ypos = ypos + yCenter; + ngabors = numel(xpos); + baseRect = [0 0 gabor_dim_pix gabor_dim_pix]; + allRects = nan(4, ngabors); + for i = 1:ngabors + allRects(:, i) = CenterRectOnPointd(baseRect, xpos(i), ypos(i)); + end + for n = 1:ngabors + Screen('FillOval', win, i, allRects(:,n)); + end + Screen('Flip',win); + + % make Kb Queue + keyList = zeros(1, 256); keyList(KbName({'ESCAPE'})) = 1; % only listen to those keys! + PsychHID('KbQueueCreate', [], keyList); + PsychHID('KbQueueStart'); + WaitSecs(.1); + PsychHID('KbQueueFlush'); + + % keyIsDown = false; + % while ~keyIsDown + % [keyIsDown, firstPress] = PsychHID('KbQueueCheck'); + % end + + + + % Load identity gamma table for calibration: + LoadIdentityClut(win); + + measurements = []; + + inputV = [0:(maxLevel+1)/(numMeasures - 1):(maxLevel+1)]; %#ok + inputV(end) = maxLevel; + levels = inputV; + for i = inputV + colors = [i, i]; + for n = 1:ngabors + Screen('FillOval', win, colors(n), allRects(:,n)); + end + Screen('Flip',win); + WaitSecs(0.1); + cMatrix = ColorCal2('ReadColorMatrix'); + s = ColorCal2('MeasureXYZ'); + correctedValues = cMatrix(1:3,:) * [s.x s.y s.z]'; + + %data = read_xyz();g + measurements = [measurements; correctedValues(2)]; %#ok + + end + + % Restore normal gamma table and close down: + RestoreCluts; + Screen('CloseAll'); +catch %#ok<*CTCH> + RestoreCluts; + Screen('CloseAll'); + psychrethrow(psychlasterror); +end + + +% [ gammaTable1, gammaTable2, displayBaseline, displayRange, displayGamma, maxLevel, raw_vals, levels] +gammaTables1 = []; +gammaTables2 = []; +displayBaselines = []; +displayRanges = []; +displayGammas = []; + + +for n = 1:1 + %Normalize values + + vals = measurements; + vals = vals(:, n)'; + displayRange = range(vals); + displayBaseline = min(vals); + displayRanges = [displayRanges displayRange]; + displayBaselines = [displayBaselines displayBaseline]; + + raw_vals = vals; + vals = (vals - displayBaseline) / displayRange; + inputV = [0:(maxLevel+1)/(numMeasures - 1):(maxLevel+1)]; %#ok + inputV(end) = maxLevel; + inputV = inputV/maxLevel; + + %Gamma function fitting + g = fittype('x^g'); + fittedmodel = fit(inputV',vals',g); + displayGamma = fittedmodel.g; + displayGammas = [displayGammas displayGamma]; + gammaTable1 = ((([0:maxLevel]'/maxLevel))).^(1/fittedmodel.g); %#ok + gammaTables1 = [gammaTables1, gammaTable1]; %#ok + firstFit = fittedmodel([0:maxLevel]/maxLevel); %#ok + +end +return; diff --git a/tool/grating_test.m b/tool/grating_test.m new file mode 100644 index 0000000..7f4d956 --- /dev/null +++ b/tool/grating_test.m @@ -0,0 +1,121 @@ +function [contrast, lums] = grating_test(gTmp) +small_window =0; +commandwindow; %focus on the command window, so that output is not written on the editor +p = struct(); +SetParams;%set parameters of the experiment +SetPTB;%set visualization parameters. +lums = []; +ks = 50; +Screen('LoadNormalizedGammaTable', p.ptb.w, gTmp); +for k = 1:10 + vbl = Screen('Flip', p.ptb.w); %<----- FLIP +end +contrast = [0, 150, 0, 150, 0, 150, 0, 150, 0, 150]; +Screen('FillRect',p.ptb.w, 128); +vbl = Screen('Flip', p.ptb.w); %<----- FLIP + +lums = []; +fprintf('Waiting') +waitforbuttonpress + +for k = 1:length(contrast) + Screen('LoadNormalizedGammaTable', p.ptb.w, gTmp); + + Screen('FillRect',p.ptb.w, 128); + + draw_stimulus(p, contrast(k)) + vbl = Screen('Flip', p.ptb.w); %<----- FLIP + lums = [lums, luminance()]; + lums; +end +%contrast = [-0.1, contrast]; +sca + + function draw_stimulus(p, contrast) + stim_id = 1; + angle = 90*stim_id; + df = p.ptb.rect(3) - p.ptb.rect(4); + rect = [df/2., 0, p.ptb.rect(4)+df/2, p.ptb.rect(4)]; + Screen('DrawTexture', p.ptb.w, p.ptb.gabortex, [], rect, ... + angle, [], [], [], [], [], [0, p.stim.sf, contrast, 100, 1, 0, 0, 0]); + oc = [p.ptb.midpoint(1)-25, p.ptb.midpoint(2)-25, p.ptb.midpoint(1)+25, p.ptb.midpoint(2)+25]; + %Screen('FillOval', p.ptb.w, p.stim.bg, oc); + %draw also the fixation cross + end + + + + function SetParams + %% %%%%%%%%%%%%%%%%%%%%%%%%% + p.stim.bg = [128, 128, 128]; + p.stim.white = get_color('white'); + p.text.fontname = 'Times New Roman'; + p.text.fontsize = 18; + p.text.fixsize = 60; + + + end + + + function SetPTB + %Sets the parameters related to the PTB toolbox. Including + %fontsizes, font names. + %Default parameters + Screen('Preference', 'SkipSyncTests', 1); + Screen('Preference', 'DefaultFontSize', p.text.fontsize); + Screen('Preference', 'DefaultFontName', p.text.fontname); + Screen('Preference', 'TextAntiAliasing',2);%enable textantialiasing high quality + Screen('Preference', 'VisualDebuglevel', 0); + Screen('Preference', 'SkipSyncTests', 1); + Screen('Preference', 'SuppressAllWarnings', 1); + %%Find the number of the screen to be opened + screens = Screen('Screens'); + p.ptb.screenNumber = min(screens);%the maximum is the second monitor + + %set the resolution correctly + res = Screen('resolution', p.ptb.screenNumber); + HideCursor(p.ptb.screenNumber);%make sure that the mouse is not shown at the participant's monitor + + fprintf('Resolution of the screen is %dx%d...\n',res.width,res.height); + + %Open a graphics window using PTB + if ~small_window + [p.ptb.w p.ptb.rect] = Screen('OpenWindow', p.ptb.screenNumber, [0.5, 0.5, 0.5]); + else + [p.ptb.w p.ptb.rect] = Screen('OpenWindow', p.ptb.screenNumber, [128, 128, 128], [0, 0, 1000, 500]); + end + + %Screen('BlendFunction', p.ptb.w, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + Screen('Flip',p.ptb.w);%make the bg + + p.ptb.slack = Screen('GetFlipInterval',p.ptb.w)./2; + [p.ptb.width, p.ptb.height] = Screen('WindowSize', p.ptb.screenNumber); + + %find the mid position on the screen. + x = p.ptb.rect(1) + (p.ptb.rect(3)/2); + y = p.ptb.rect(2) + (p.ptb.rect(4)/2); + + p.ptb.midpoint = [x, y] % p.ptb.width./2 p.ptb.height./2]; + %NOTE about RECT: + %RectLeft=1, RectTop=2, RectRight=3, RectBottom=4. + p.ptb.CrossPosition_x = p.ptb.midpoint(1); + p.ptb.CrossPosition_y = p.ptb.midpoint(2); + %cross position for the eyetracker screen. + p.ptb.fc_size = 10; + + Priority(MaxPriority(p.ptb.w)); + + %% Build a procedural gabor texture for a gabor with a support of tw x th + % pixels, and a RGB color offset of 0.5 -- a 50% gray. + p.display.ppd = 60; + p.stim.radius = p.ptb.rect(4)/2; + p.stim.sf = 2/p.display.ppd; + fprintf('R and SF: %f %f', p.stim.radius, p.stim.sf) + %p.ptb.gabortex = CreateProceduralGabor(p.ptb.w, p.ptb.width, p.ptb.height, 0, [0.5 0.5 0.5 0.0]); + p.ptb.gabortex = CreateProceduralSineGrating(p.ptb.w, 2*p.stim.radius, 2*p.stim.radius,... + [0.5, 0.5, 0.5, 0.5], p.stim.radius); + end + + + +end \ No newline at end of file diff --git a/tool/luminance.m b/tool/luminance.m new file mode 100644 index 0000000..a365150 --- /dev/null +++ b/tool/luminance.m @@ -0,0 +1,6 @@ +function lum = luminance() +cMatrix = ColorCal2('ReadColorMatrix'); +s = ColorCal2('MeasureXYZ'); +correctedValues = cMatrix(1:3,:) * [s.x s.y s.z]'; +lum = correctedValues(2); +end \ No newline at end of file diff --git a/vpixx_gamma_table.mat b/vpixx_gamma_table.mat new file mode 100644 index 0000000..d05481e Binary files /dev/null and b/vpixx_gamma_table.mat differ