1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262 |
- function runstim(Hnd)
- % Updated November 2017, Chris Klink (c.klink@nin.knaw.nl)
- % Fixation & diverse retinotopic mapping stimuli
- global Par %global parameters
- global StimObj %stimulus objects
- global Log %Logs
- %% THIS SWITCH ALLOW TESTING THE RUNSTIM WITHOUT DASCARD & TRACKER ========
- TestRunstimWithoutDAS = false;
- %==========================================================================
- % Do this only for testing without DAS
- if TestRunstimWithoutDAS
- cd .. %#ok<*UNRCH>
- addpath(genpath(cd));
- ptbInit % initialize PTB
- Par.scr=Screen('screens');
- Par.ScrNr=max(Par.scr); % use the screen with the highest #
- Par.ScreenChoice = 'Mock';
- if Par.ScrNr==0
- % part of the screen
- [Par.window, Par.wrect] = ...
- Screen('OpenWindow',Par.ScrNr,0,[0 0 1000 800],[],2);
- else
- [Par.window, Par.wrect] = Screen('OpenWindow',Par.ScrNr,0,[],[],2);
- end
- % Reduce PTB3 verbosity
- oldLevel = Screen('Preference', 'Verbosity', 0); %#ok<*NASGU>
- Screen('Preference', 'VisualDebuglevel', 0);
- Screen('Preference','SkipSyncTests',1);
-
- %Do some basic initializing
- AssertOpenGL;
- KbName('UnifyKeyNames');
-
- %Set ParFile and Stimfile
- Par.PARSETFILE = 'ParSettings_NoDas';
- Par.STIMSETFILE = 'StimSettings_NaturalMovie_1'; %'StimSettings_pRF_8bars'; %'StimSettings_FullscreenCheckerboard';
- Par.MONKEY = 'TestWithoutDAS';
- end
- clc;
- %% Prior To Dealing With Stimuli ==========================================
- % set PTB priority to max
- priorityLevel=MaxPriority(Par.window);
- oldPriority=Priority(priorityLevel);
- Par.ExpFolder = pwd;
- %% set up the manual response task ========================================
- for define_square=1 % left / square
- lmost=-1/2; rmost= 1/2;
- tmost=-1/2; bmost= 1/2;
- left_square = [lmost,tmost; rmost,tmost; rmost,bmost; lmost,bmost ];
- end
- for define_diamond=1 % right / diamond
- lmost=-sqrt(2)*1/2; rmost= sqrt(2)*1/2;
- tmost=-sqrt(2)*1/2; bmost= sqrt(2)*1/2;
- right_diamond = [lmost,0; 0,tmost; rmost,0; 0,bmost ];
- end
- for define_circle=1 % shown when subject needs to release response
- lmost=-sqrt(1/pi); rmost= sqrt(1/pi);
- tmost=-sqrt(1/pi); bmost= sqrt(1/pi);
- blocked_circle = [lmost, tmost, rmost, bmost ];
- end
- %% initialize stuff =======================================================
- Par.ESC = false; %escape has not been pressed
- GrandTotalReward=0;
- LastRewardAdded=false;
- CollectPerformance=[];
- CloseTextures=false;
- json_done=false;
- Par.RewardStartTime=0;
- % re-run parameter-file to update stim-settings without restarting Tracker
- eval(Par.PARSETFILE); % can be chosen in menu
- if ~isfield(Par,'PostErrorDelay')
- Par.PostErrorDelay = 0;
- fprintf('No PostErrorDelay defined: Setting it to 0\n');
- end
- if ~isfield(Par,'DelayOnMiss')
- Par.DelayOnMiss = 0;
- fprintf('No DelayOnMiss defined: Setting it to 0\n');
- end
- if ~isfield(Par,'RewardForHandsIn_Delay')
- Par.RewardForHandsIn_Delay = 0;
- fprintf('No RewardForHandsIn_Delay defined: Setting it to 0\n');
- end
- if ~isfield(Par,'RewardForHandIn_ResetIntervalWhenOut')
- Par.RewardForHandIn_ResetIntervalWhenOut = false;
- Par.RewardForHandIn_MinIntervalBetween = 0;
- fprintf('No RewardForHandIn_ResetIntervalWhenOut defined: Setting it to false\n');
- end
- if ~isfield(Par,'LeversUpTimeOut')
- Par.LeversUpTimeOut = [Inf 0];
- fprintf('No LeversUpTimeOut defined: Setting it to [Inf 0]\n');
- end
- if strcmp(StimObj.Stm(1).RetMap.StimType{1},'movie-vlc')
- Par.ResponseBox.Task = 'Fixate';
- fprintf('No hand task possible during vlc-movies\n');
- fprintf('Setting task to fixate\n');
- end
- % Add keys to fix left/right/random responses
- Par.KeyLeftResp = KbName(',<');
- Par.KeyRightResp = KbName('.>');
- Par.KeyRandResp = KbName('/?');
- Par.RespProbSetting=0; % initialize with random left/right indicators
- Par.ScrCenter=Par.wrect(3:4)/2;
- DateString_sec = datestr(clock,30);
- DateString = DateString_sec(1:end-2);
- Par_BU=Par;
- if ~TestRunstimWithoutDAS
- refreshtracker(1);
- end
- if strcmp(Par.SetUp,'NIN')
- blockstr = inputdlg('BlockNr','BlockNr',1,{'000'});
- blockstr=blockstr{1};
- end
- % output stimsettings filename to cmd
- fprintf(['Setup selected: ' Par.SetUp '\n']);
- %fprintf(['Screen selected: ' Par.ScreenChoice '\n']);
- fprintf(['TR: ' num2str(Par.TR) 's\n\n']);
- fprintf(['=== Running ' Par.STIMSETFILE ' for ' Par.MONKEY ' ===\n']);
- if ~strcmp(Par.ResponseBox.Task, 'DetectGoSignal')% do no show this if reward is based on task
- if numel(Par.Times.Targ)>1
- fprintf(['Progressive fix-to-reward times between ' num2str(Par.Times.Targ(1,2)) ...
- ' and ' num2str(Par.Times.Targ(end,2)) ' ms\n']);
- else
- fprintf(['Hold fixation for ' num2str(Par.Times.Targ) ' ms to get reward\n']);
- end
- end
- Par.RewardTime=Par.RewardTimeSet;
- Stm = StimObj.Stm;
- fprintf(['Started at ' DateString '\n']);
- % overwrite the stimsettings fix-window with the one from parsettings
- for sss=1:length(Stm)
- Stm(sss).FixWinSize = Par.FixWinSize;
- if ~TestRunstimWithoutDAS
- refreshtracker(1);
- end
- end
- % If multiple stimuli are defined, arrange order
- Log.StimOrder=[];
- for nR=1:Stm(1).nRepeatsStimSet
- if length(Stm)>1
- nSTIM=length(Stm);
- if Stm(1).RandomizeStim
- Log.StimOrder = [Log.StimOrder randperm(nSTIM)];
- else
- Log.StimOrder = [Log.StimOrder 1:nSTIM];
- end
- StimLoopNr=0;
- else
- Log.StimOrder = [Log.StimOrder 1];
- StimLoopNr=0;
- end
- end
- % This control parameter needs to be outside the stimulus loop
- FirstEyeRecSet=false;
- if ~TestRunstimWithoutDAS
- dasbit(0,1); %set eye-recording trigger to 1 (=stopped)
- %reset reward slider based on ParSettings
- handles=guihandles(Par.hTracker);
- if numel(Par.RewardTime)==1
- set(handles.Lbl_Rwtime, 'String', num2str(Par.RewardTime, 5))
- set(handles.slider1, 'Value', Par.RewardTime)
- else
- set(handles.Lbl_Rwtime, 'String', num2str(Par.RewardTime(1,2), 5))
- set(handles.slider1, 'Value', Par.RewardTime(1,2))
- end
- end
- %% Load stimuli before entering the display loop to be faster later =======
- % Load retinotopic mapping stimuli
- FaceRingsLoaded=false; FaceWedgeLoaded=false;
- WalkerRingsLoaded=false; WalkerWedgeLoaded=false;
- for STIMNR = unique(Log.StimOrder)
- switch Stm(STIMNR).RetMap.StimType{1}
- case 'none'
- Stm(STIMNR).Descript = 'NoStim';
- case 'ret'
- %% Retinotopy stim
- if strcmp(Stm(STIMNR).RetMap.StimType{2},'pRF_8bar')
- Stm(STIMNR).Order=1:Stm(STIMNR).RetMap.nSteps;
- Stm(STIMNR).Descript = 'pRF_8bar';
- elseif strcmp(Stm(STIMNR).RetMap.StimType{2},'wedge_cw')
- Stm(STIMNR).Order=Stm(STIMNR).RetMap.nSteps:-1:1;
- Stm(STIMNR).Descript = 'wedge_cw';
- elseif strcmp(Stm(STIMNR).RetMap.StimType{2},'wedge_ccw')
- Stm(STIMNR).Order=1:Stm(STIMNR).RetMap.nSteps;
- Stm(STIMNR).Descript = 'wedge_ccw';
- elseif strcmp(Stm(STIMNR).RetMap.StimType{2},'ring_con')
- Stm(STIMNR).Order=Stm(STIMNR).RetMap.nSteps:-1:1;
- Stm(STIMNR).Descript = 'ring_con';
- elseif strcmp(Stm(STIMNR).RetMap.StimType{2},'ring_exp')
- Stm(STIMNR).Order=1:Stm(STIMNR).RetMap.nSteps;
- Stm(STIMNR).Descript = 'ring_exp';
- end
- if Stm(STIMNR).RetMap.LoadFromFile
- fprintf(['\nLoading retinotopy stimulus: ' ...
- Stm(STIMNR).RetMap.FileName '...\n']);
- cd Stimuli
- cd RetMap
- D=load(Stm(STIMNR).RetMap.FileName);
- stimulus=D.stimulus;fps=D.fps;
- cd ..
- cd ..
- else
- fprintf('Creating retinotopy stimulus...\n');
- stimulus = ck_ret(Stm,STIMNR);
- fps = Stm(STIMNR).RetMap.fps;
- if Stm(STIMNR).RetMap.SaveToFile
- fprintf('\nSaving retinotopy stimulus...\n');
- cd Stimuli
- cd RetMap
- save(Stm(STIMNR).RetMap.FileName,'stimulus','fps','Stm','-v7.3');
- cd ..
- cd ..
- end
- end
- %% img to textures
- pos=0; %Stm(STIMNR).RetMap.posmap = [];
- if strcmp(Stm(STIMNR).RetMap.StimType{2},'pRF_8bar')
- for rv=1:length(stimulus(1).orient) %length(stimulus) % directions
- for ii=1:length(stimulus(1).img) % positions
- pos=pos+1;
- for jj = 1:size(stimulus(1).img{ii},3) % frame
- if rv==1
- img1 = stimulus(1).img{ii}(:,:,jj);
- ret_vid(pos).img{jj} = img1; %#ok<*AGROW>
- ret_vid(pos).text(jj) = Screen('MakeTexture', ...
- Par.window,img1);
- end
- ret_vid(pos).fps = fps;
- ret_vid(pos).orient(jj) = stimulus(1).orient(rv);
- end
- end
- end
- else
- for rv=1:length(stimulus)
- for ii=1:length(stimulus(rv).img) % positions
- pos=pos+1;
- for jj = 1:size(stimulus(rv).img{ii},3) % frame
- ret_vid(pos).img{jj} = stimulus(rv).img{ii}(:,:,jj); %#ok<*AGROW>
- ret_vid(pos).fps = fps;
- ret_vid(pos).text(jj) = Screen('MakeTexture', Par.window, ...
- ret_vid(pos).img{jj});
- end
- end
- end
- end
- CloseTextures = true;
- Stm(STIMNR).RetMap.posmap = stimulus(1).posmap;
- case 'face'
- %% Classic retinotopy: faces
- if strcmp(Stm(STIMNR).RetMap.StimType{2},'circle')
- if Stm(STIMNR).RetMap.Dir == 1 %expanding
- Stm(STIMNR).Order=1:32;
- Stm(STIMNR).Descript = 'FaceRingExp';
- elseif Stm(STIMNR).RetMap.Dir == -1 %contracting
- Stm(STIMNR).Order=32:-1:1;
- Stm(STIMNR).Descript = 'FaceRingCon';
- end
- if ~FaceRingsLoaded
- cd Stimuli
- cd faces
- fprintf('Loading faces01_rings.mat\n');
- vid_face_ring = load('faces01_rings.mat'); % loads 'ret_vid' structure
- FaceRingsLoaded=true;
- cd ..
- cd ..
- face_ring_vidtex_made=false;
- end
- elseif strcmp(Stm(STIMNR).RetMap.StimType{2},'wedge')
- if Stm(STIMNR).RetMap.Dir == 1 %ccw
- Stm(STIMNR).Order=1:32;
- Stm(STIMNR).Descript = 'FaceWedgeCCW';
- elseif Stm(STIMNR).RetMap.Dir == -1 %cw
- Stm(STIMNR).Order=[1 32:-1:2];
- Stm(STIMNR).Descript = 'FaceWedgeCW';
- end
- if ~FaceWedgeLoaded
- cd Stimuli
- cd faces
- fprintf('Loading faces01_wedge.mat\n');
- vid_face_wedge = load('faces01_wedge.mat'); % loads 'ret_vid' structure
- FaceWedgeLoaded=true;
- cd ..
- cd ..
- face_wedge_vidtex_made=false;
- end
- end
- Stm(STIMNR).RetMap.posmap = [(1:32)' Stm(STIMNR).Order'];
- % img to textures
- if strcmp(Stm(STIMNR).RetMap.StimType{2},'circle') && ~face_ring_vidtex_made
- fprintf('Creating stimulus textures\n');
- for rv=1:length(vid_face_ring.ret_vid)
- for ii=1:length(vid_face_ring.ret_vid(rv).img)
- vid_face_ring.ret_vid(rv).text(ii) = Screen('MakeTexture', Par.window, ...
- vid_face_ring.ret_vid(rv).img{ii});
- end
- end
- face_ring_vidtex_made=true;
- elseif strcmp(Stm(STIMNR).RetMap.StimType{2},'wedge') && ~face_wedge_vidtex_made
- fprintf('Creating stimulus textures\n');
- for rv=1:length(vid_face_wedge.ret_vid)
- for ii=1:length(vid_face_wedge.ret_vid(rv).img)
- vid_face_wedge.ret_vid(rv).text(ii) = Screen('MakeTexture', Par.window, ...
- vid_face_wedge.ret_vid(rv).img{ii});
- end
- end
- face_wedge_vidtex_made=true;
- end
- CloseTextures = true;
- case 'walker'
- %% Classic retinotopy: walkers
- if strcmp(Stm(STIMNR).RetMap.StimType{2},'circle')
- if Stm(STIMNR).RetMap.Dir == 1 %expanding
- Stm(STIMNR).Order=1:32;
- Stm(STIMNR).Descript = 'WalkerRingExp';
- elseif Stm(STIMNR).RetMap.Dir == -1 %contracting
- Stm(STIMNR).Order=32:-1:1;
- Stm(STIMNR).Descript = 'WalkerRingCon';
- end
- if ~WalkerRingsLoaded
- cd Stimuli
- cd walkers
- fprintf('Loading walker01_rings.mat\n');
- vid_walker_ring = load('walker01_rings.mat'); % loads ret_vid structure
- WalkerRingsLoaded=true;
- cd ..
- cd ..
- walker_ring_vidtex_made=false;
- end
- elseif strcmp(Stm(STIMNR).RetMap.StimType{2},'wedge')
- if Stm(STIMNR).RetMap.Dir == 1 %ccw
- Stm(STIMNR).Order=1:32;
- Stm(STIMNR).Descript = 'WalkerWedgeCCW';
- elseif Stm(STIMNR).RetMap.Dir == -1 %cw
- Stm(STIMNR).Order=[1 32:-1:2];
- Stm(STIMNR).Descript = 'WalkerWedgeCW';
- end
- if ~WalkerWedgeLoaded
- cd Stimuli
- cd walkers
- fprintf('Loading walker01_wedge.mat\n');
- vid_walker_wedge = load('walker01_wedge.mat'); % loads ret_vid structure
- WalkerWedgeLoaded=true;
- cd ..
- cd ..
- walker_wedge_vidtex_made=false;
- end
- end
- Stm(STIMNR).RetMap.posmap = [(1:32)' Stm(STIMNR).Order'];
- % img to textures
- if strcmp(Stm(STIMNR).RetMap.StimType{2},'circle') && ~walker_ring_vidtex_made
- fprintf('Creating stimulus textures\n');
- for rv=1:length(vid_walker_ring.ret_vid)
- for ii=1:length(vid_walker_ring.ret_vid(rv).img)
- vid_walker_ring.ret_vid(rv).text(ii) = Screen('MakeTexture', Par.window, ...
- vid_walker_ring.ret_vid(rv).img{ii});
- end
- end
- walker_ring_vidtex_made=true;
- elseif strcmp(Stm(STIMNR).RetMap.StimType{2},'wedge') && ~walker_wedge_vidtex_made
- fprintf('Creating stimulus textures\n');
- for rv=1:length(vid_walker_wedge.ret_vid)
- for ii=1:length(vid_walker_wedge.ret_vid(rv).img)
- vid_walker_wedge.ret_vid(rv).text(ii) = Screen('MakeTexture', Par.window, ...
- vid_walker_wedge.ret_vid(rv).img{ii});
- end
- end
- walker_wedge_vidtex_made=true;
- end
- CloseTextures = true;
- case 'checkerboard'
- %% fullscreen checkerboard
- Stm(STIMNR).Descript = 'FullChecker';
- case 'movie'
- Stm(STIMNR).Descript = 'movie';
- case 'movie-vlc'
- Stm(STIMNR).Descript = 'movie-vlc';
- end
- end
- TotTime=0;
- for i=1:length(Stm)
- if strcmp(Stm(i).RetMap.StimType{1},'checkerboard')
- Stm(i).RetMap.PreDur = ...
- Stm(i).RetMap.PreDur_TRs*Par.TR;
- Stm(i).RetMap.PostDur = ...
- Stm(i).RetMap.PostDur_TRs*Par.TR;
- Stm(i).RetMap.Checker.OnOff = ...
- Stm(i).RetMap.Checker.OnOff_TRs*Par.TR;
- TotTime = TotTime + ...
- (sum(Stm(i).RetMap.Checker.OnOff)*Stm(i).RetMap.nCycles)+...
- Stm(i).RetMap.PreDur+Stm(i).RetMap.PostDur;
- elseif strcmp(Stm(i).RetMap.StimType{1},'movie') || ...
- strcmp(Stm(i).RetMap.StimType{1},'movie-vlc')
- Stm(i).RetMap.PreDur = ...
- Stm(i).RetMap.PreDur_TRs*Par.TR;
- Stm(i).RetMap.PostDur = ...
- Stm(i).RetMap.PostDur_TRs*Par.TR;
- TotTime = TotTime + ...
- Stm(i).RetMap.moviedur + ...
- Stm(i).RetMap.PreDur + Stm(i).RetMap.PostDur;
- else
- Stm(i).RetMap.PreDur = ...
- Stm(i).RetMap.PreDur_TRs*Par.TR;
- Stm(i).RetMap.PostDur = ...
- Stm(i).RetMap.PostDur_TRs*Par.TR;
- if strcmp(Stm(i).RetMap.StimType{1},'ret')
- if Stm(i).RetMap.nCycles
- TotTime = TotTime + ...
- Stm(i).RetMap.nCycles*...
- size(Stm(i).RetMap.posmap,1)*...
- Stm(i).RetMap.TRsPerStep*Par.TR + ...
- Stm(i).RetMap.PreDur + Stm(i).RetMap.PostDur;
- else % no endpoint defined
- TotTime = Inf;
- end
- else
- if Stm(i).RetMap.nCycles
- TotTime = TotTime + ...
- Stm(i).nRepeatsStimSet*Stm(i).RetMap.nCycles*...
- Stm(i).RetMap.nSteps *...
- Stm(i).RetMap.TRsPerStep*Par.TR + ...
- Stm(i).RetMap.PreDur + Stm(i).RetMap.PostDur;
- else % no endpoint defined
- TotTime = Inf;
- end
- end
- end
- end
- if ~isinf(TotTime)
- NumVolNeeded=(Stm(1).nRepeatsStimSet*TotTime)/Par.TR;
- if strcmp(Par.SetUp,'NIN') % ephys
- fprintf(['This StimSettings file will take ' ...
- num2str(ceil(Stm(1).nRepeatsStimSet*TotTime)) ' seconds.\n']);
- Log.uniqueID = round(rand(1).*2^14);
-
- if strcmp(Par.SetUp,'NIN')
- send_serial_data(Log.uniqueID); % Xing's Blackrock rig
- % dasword(Log.uniqueID); % other ephys
- else
- dasword(Log.uniqueID);
- end
-
- pause(.05); % make sure the word is received
- dasclearword();
- WordsSent=1; %keep track of how many words are sent so we back-check TDT against the log
- Log.Words(WordsSent)=Log.uniqueID; %collect all the words that are sent to TDT
- else
- fprintf(['This StimSettings file requires at least ' num2str(ceil(NumVolNeeded)) ...
- ' scanvolumes (check scanner)\n']);
- end
- else
- fprintf('NB: No end-time defined. This will keep running until stopped.\n')
- end
- %% Run this loop all stimuli the StimSettings file ========================
- Par.ESC=false; Log.TotalTimeOut = 0; Par.Pause = false;
- update_trackerfix_now = true;
- for STIMNR = Log.StimOrder
- %% Cycles of stimuli --------------------------------------------------
- nCyclesDone=0;
- nCyclesReported=0;
- Log.TimeOutThisRun=0;
- Stm(STIMNR).IsPostDur=false;
- if ~Par.ESC
- StimLoopNr=StimLoopNr+1;
- Log.RunNr=StimLoopNr;
- %% Stimulus preparation -------------------------------------------
- % Fixation
- if StimLoopNr == 1 % only defining the fix window on first loop allows setting it via gui
- Stm(STIMNR).FixWinSizePix = round(Stm(STIMNR).FixWinSize*Par.PixPerDeg);
- RunParStim_Saved = false;
- end
- Stm(STIMNR).FixDotSizePix = round(Stm(STIMNR).FixDotSize*Par.PixPerDeg);
- Par.RespIndSizePix = round(Par.RespIndSize*Par.PixPerDeg);
- Stm(STIMNR).FixDotSurrSizePix = round(Stm(STIMNR).FixDotSurrSize*Par.PixPerDeg);
- Par.GoBarSizePix = round(Par.GoBarSize*Par.PixPerDeg);
- Stm(STIMNR).Center =[];
- for i=1:size(Stm(STIMNR).Position,2)
- Stm(STIMNR).Center =[Stm(STIMNR).Center; ...
- round(Stm(STIMNR).Position{i}.*Par.PixPerDeg)];
- end
-
- % Load retinotopic mapping stimuli
- switch Stm(STIMNR).RetMap.StimType{1}
- case 'none'
- %% only fixation
- RetMapStimuli=false;
- DispChecker=false;
- MovieRun=false;
- VLCMovieRun=false;
- case 'ret'
- %% Population receptive field stim
- RetMapStimuli=true;
- DispChecker=false;
- MovieRun=false;
- VLCMovieRun=false;
- case 'face'
- %% Classic retinotopy: faces
- RetMapStimuli=true;
- DispChecker=false;
- MovieRun=false;
- VLCMovieRun=false;
- if strcmp(Stm(STIMNR).RetMap.StimType{2},'circle')
- ret_vid=vid_face_ring.ret_vid;
- elseif strcmp(Stm(STIMNR).RetMap.StimType{2},'wedge')
- ret_vid=vid_face_wedge.ret_vid;
- end
- case 'walker'
- %% Classic retinotopy: walkers
- RetMapStimuli=true;
- DispChecker=false;
- MovieRun=false;
- VLCMovieRun=false;
- if strcmp(Stm(STIMNR).RetMap.StimType{2},'circle')
- ret_vid=vid_walker_ring.ret_vid;
- elseif strcmp(Stm(STIMNR).RetMap.StimType{2},'wedge')
- ret_vid=vid_walker_wedge.ret_vid;
- end
- case 'checkerboard'
- %% fullscreen checkerboard
- fn_lead='fullchecker_';
- Stm(STIMNR).Descript = 'FullChecker';
- RetMapStimuli=false;
- DispChecker=true;
- MovieRun=false;
- VLCMovieRun=false;
- if Stm(STIMNR).RetMap.Checker.LoadFromFile
- fprintf(['\nLoading checkerboard ' ...
- Stm(STIMNR).RetMap.Checker.FileName '...\n']);
- cd Stimuli
- cd fullchecker
- load(Stm(STIMNR).RetMap.Checker.FileName);
- cd ..
- cd ..
- else
- fprintf('\nCreating checkerboard...\n');
- % create the checkerboard
- chksize = ceil(Stm(STIMNR).RetMap.Checker.Size*Par.PixPerDeg);
- chkimg = double(RadialCheckerBoard(...
- [chksize ...
- ceil(Stm(STIMNR).RetMap.Checker.centerradius*Par.PixPerDeg)], ...
- Stm(STIMNR).RetMap.Checker.Sector, ...
- Stm(STIMNR).RetMap.Checker.chsz));
- if Stm(STIMNR).RetMap.Checker.SaveToFile
- fprintf('\nSaving checkerboard...\n');
- cd Stimuli
- cd fullchecker
- save(Stm(STIMNR).RetMap.Checker.FileName,'chkimg');
- cd ..
- cd ..
- end
- end
- % create texture
- CB1R = chkimg(:,:,1)./Par.ScrWhite;
- CB1R(chkimg(:,:,1)==Par.ScrWhite) = ...
- Stm(STIMNR).RetMap.Checker.Colors(1,1);
- CB1R(chkimg(:,:,1)==0) = ...
- Stm(STIMNR).RetMap.Checker.Colors(2,1);
- CB1G=chkimg(:,:,1)./Par.ScrWhite;
- CB1G(chkimg(:,:,1)==Par.ScrWhite) = ...
- Stm(STIMNR).RetMap.Checker.Colors(1,2);
- CB1G(chkimg(:,:,1)==0) = ...
- Stm(STIMNR).RetMap.Checker.Colors(2,2);
- CB1B=chkimg(:,:,1)./Par.ScrWhite;
- CB1B(chkimg(:,:,1)==Par.ScrWhite) = ...
- Stm(STIMNR).RetMap.Checker.Colors(1,3);
- CB1B(chkimg(:,:,1)==0) = ...
- Stm(STIMNR).RetMap.Checker.Colors(2,3);
- CB1A = chkimg(:,:,3);
- CB1 = CB1R.*Par.ScrWhite;
- CB1(:,:,2)=CB1G.*Par.ScrWhite;
- CB1(:,:,3)=CB1B.*Par.ScrWhite;
- %CB1(:,:,4)=CB1A;
- CB1(:,:,4)=CB1A *1; % Make more transparent
-
- CB2R = chkimg(:,:,2)./Par.ScrWhite;
- CB2R(chkimg(:,:,2)==Par.ScrWhite) = ...
- Stm(STIMNR).RetMap.Checker.Colors(1,1);
- CB2R(chkimg(:,:,2)==0) = ...
- Stm(STIMNR).RetMap.Checker.Colors(2,1);
- CB2G=chkimg(:,:,2)./Par.ScrWhite;
- CB2G(chkimg(:,:,2)==Par.ScrWhite) = ...
- Stm(STIMNR).RetMap.Checker.Colors(1,2);
- CB2G(chkimg(:,:,2)==0) = ...
- Stm(STIMNR).RetMap.Checker.Colors(2,2);
- CB2B=chkimg(:,:,2)./Par.ScrWhite;
- CB2B(chkimg(:,:,2)==Par.ScrWhite) = ...
- Stm(STIMNR).RetMap.Checker.Colors(1,3);
- CB2B(chkimg(:,:,2)==0) = ...
- Stm(STIMNR).RetMap.Checker.Colors(2,3);
- CB2A = chkimg(:,:,3);
- CB2 = CB2R.*Par.ScrWhite;
- CB2(:,:,2)=CB2G.*Par.ScrWhite;
- CB2(:,:,3)=CB2B.*Par.ScrWhite;
- %CB2(:,:,4)=CB2A;
- CB2(:,:,4)=CB2A *1; % Make more transparent
-
- CheckTexture(1)=Screen('MakeTexture', Par.window, CB1);
- CheckTexture(2)=Screen('MakeTexture', Par.window, CB2);
- TrackingCheckerContChange = false;
- case 'movie'
- %% only fixation
- RetMapStimuli=false;
- DispChecker=false;
- MovieRun=true;
- VLCMovieRun=false;
- moviename = fullfile(Par.ExpFolder,'Stimuli','Movies',...
- Stm(STIMNR).RetMap.FileName);
- % prepare the movie
- [Log.movie.name, Log.movie.duration, ...
- Log.movie.fps, Log.movie.imgw, Log.movie.imgh] = ...
- Screen('OpenMovie', Par.window, moviename, ...
- [], [], [], [], []);
- MovieRunning=false;
- case 'movie-vlc'
- RetMapStimuli=false;
- DispChecker=false;
- MovieRun=false;
- VLCMovieRun=true;
- moviebat = fullfile(Par.ExpFolder,'Stimuli','Movies',...
- Stm(STIMNR).RetMap.VLC_batfile);
- stopVLCbat = fullfile(Par.ExpFolder,'Stimuli','Movies',...
- Stm(STIMNR).RetMap.VLC_stop);
- MovieRunning=false;
- end
-
- fprintf(['\nRun: ' num2str(Log.RunNr)]);
- fprintf(['\n-- Stimulus: ' Stm(STIMNR).Descript ' --\n']);
-
- %% Code Control Preparation ---------------------------------------
- Par.FixStatToCMD=true;
-
- % Some intitialization of control parameters
- if Par.MRITrigger_OnlyOnce && StimLoopNr == 1
- Log.MRI.TriggerReceived = false;
- elseif ~Par.MRITrigger_OnlyOnce
- Log.MRI.TriggerReceived = false;
- end
- Log.MRI.TriggerTime = [];
- Log.ManualReward = false;
- Log.ManualRewardTime = [];
- Log.TotalReward=0;
-
- % Initial stimulus position is 1
- Par.PosNr=1;
- Par.PrevPosNr=1;
-
- % Initialize the side of response
- Par.ResponseSide=0;
- Par.CurrResponseSide=Par.ResponseSide;
- Par.CurrOrient=1; % 1=default, 2=switched
- Par.Orientation = [1 0]; % [def a1lt] 0=hor, 1=vert
- Par.ResponseState = Par.RESP_STATE_DONE;
- Par.ResponseStateChangeTime = 0;
-
- % Initialize KeyLogging
- Par.KeyIsDown=false;
- Par.KeyWasDown=false;
- Par.KeyDetectedInTrackerWindow=false;
-
- % Initialize control parameters
- Par.SwitchPos = false;
- Par.ToggleCyclePos = false; % overrules the Stim(1)setting; toggles with 'p'
- Par.ToggleHideStim = false;
- Par.ToggleHideFix = false;
- Par.ManualReward = false;
- Par.PosReset=false;
- Par.RewardStarted=false;
- Par.MovieStopped=false;
- Par.Allow_Calls_To_PTB_win = true;
-
- % Trial Logging
- Par.Response = 0; % maintained fixations
- Par.ResponsePos = 0; % maintained fixations
- Par.RespTimes = [];
- Par.ManRewThisTrial=[];
-
- Par.FirstInitDone=false;
- Par.CheckFixIn=false;
- Par.CheckFixOut=false;
- Par.CheckTarget=false;
- Par.RewardRunning=false;
-
- % Initialize photosensor manual response
- Par.BeamIsBlocked=false(size(Par.ConnectBox.PhotoAmp));
- Par.HandIsIn =[false false];
- Par.HandWasIn = Par.HandIsIn;
- Par.LeverIsUp = [false; false];
- Par.LeverWasUp = Par.LeverIsUp;
- Par.BothLeversUp_time = Inf;
- AutoPauseStartTime = Inf;
- AutoPausing = false;
-
- %video control
- Par.VideoLoaded=false;
- Par.VideoPlaying=false;
- Par.VidNumber=1;
- Par.nVidStarted=0;
- Par.VidFrameTime=-1;
- Par.LastVidFrameTime=-1;
- Par.VidFrameNr=1;
- Par.VidCycleNr=1;
- Par.VidTexMade=false;
- Par.VideoAppend=false;
- LogFirstVidStartTime=false;
- FirstVidDrawn=false;
-
- % keep track of timing
- Log.lfts=[];
-
- %Screen('FillRect',Par.window,[0 0 0].*Par.ScrWhite); % black first
- % Flip the proper background on screen
- %Screen('FillRect',Par.window,Par.BG.*Par.ScrWhite);
-
- if ~Par.Pause
- Screen('FillRect',Par.window,Par.BG.*Par.ScrWhite);
- else
- Screen('FillRect',Par.window,[0 0 0].*Par.ScrWhite); % black first
- end
- lft=Screen('Flip', Par.window);
-
- Par.ExpStart = lft;
- Log.nEvents=1;
- Log.Events = [];
- Log.Events(Log.nEvents).event='ExpStart';
- Log.Events(Log.nEvents).t=0;
- Log.Events(Log.nEvents).info='Start';
- Log.Eye =[];
- Par.CurrEyePos = [];
- Par.CurrEyeZoom = [];
-
- EyeRecMsgShown=false;
- RunEnded=false;
-
- %% Eye-tracker recording
- if Par.EyeRecAutoTrigger
- if ~FirstEyeRecSet
- SetEyeRecStatus(0); % send record off signal
- hmb=msgbox('Prepare the eye-tracker for recording','Eye-tracking');
- uiwait(hmb);
- FirstEyeRecSet=true;
- pause(1);
- end
-
- MoveOn=false;
- StartSignalSent=false;
- while ~MoveOn
- StartEyeRecCheck = GetSecs;
- while ~Par.EyeRecStatus && GetSecs < StartEyeRecCheck + 3 % check for 3 seconds
- CheckEyeRecStatus; % checks the current status of eye-recording
- if ~StartSignalSent
- SetEyeRecStatus(1);
- StartSignalSent=true;
- end
- end
- BreakTime = GetSecs;
- if Par.EyeRecStatus % recording
- StartedEyeRecTime=BreakTime;
- fprintf('Started recording eyetrace\n');
- MoveOn=true;
- else
- fprintf('not recording yet\n')
- SetEyeRecStatus(1); %trigger recording
- end
- end
- else
- fprintf('Eye recording not triggered (ephys or training?). Make sure it''s running!\n');
- end
-
- %% MRI triggered start
- Screen('FillRect',Par.window,Par.BG.*Par.ScrWhite);
- lft=Screen('Flip', Par.window);
- if Par.MRITriggeredStart
- fprintf('Waiting for MRI trigger (or press ''t'' on keyboard)\n');
- while ~Log.MRI.TriggerReceived
- CheckKeys;
- %Screen('FillRect',Par.window,Par.BG.*Par.ScrWhite);
- %lft=Screen('Flip', Par.window);
- end
- if Par.MRITrigger_OnlyOnce && lft-Par.ExpStart == 0
- fprintf('Triggering only once, move on automatically now.\n');
- else
- fprintf(['MRI trigger received after ' num2str(GetSecs-Par.ExpStart) ' s\n']);
- end
- end
- else
- if VLCMovieRun
- if MovieRunning
- eval(['!' stopVLCbat])
- Reopen_PTB_win;
- MovieRunning=false;
- end
- end
- end
-
- %% Displaying the stimuli ---------------------------------------------
- while ~Par.ESC && ~RunEnded
- while ~Par.FirstInitDone
- %set control window positions and dimensions
- if ~TestRunstimWithoutDAS
- DefineEyeWin(STIMNR);
- refreshtracker(1) %for your control display
- last_tracker_update = GetSecs;
- SetWindowDas; %for the dascard, initializes eye control windows
- end
-
- Par.Trlcount = Par.Trlcount+1; %keep track of trial numbers
- % send trial nr to ephys rig
- if strcmp(Par.SetUp,'NIN') % ephys
- %dasword(Par.Trlcount(1)); % TDT
- send_serial_data(Par.Trlcount(1)); % Blackrock
- WordsSent+1; %#ok<*VUNUS>
- Log.Words(WordsSent)=Par.Trlcount(1);
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event='TrialStart';
- Log.Events(Log.nEvents).t=GetSecs-Par.ExpStart;
- Log.Events(Log.nEvents).info = Par.Trlcount(1);
- end
- Par.ResponseGiven=false;
- Par.FalseResponseGiven=false;
- Par.RespValid = false;
- Par.CorrectThisTrial=false;
- Par.LastFixInTime=0;
- Par.LastFixOutTime=0;
- Par.FixIn=false; %initially set to 'not fixating'
- Par.CurrFixCol=Stm(STIMNR).FixDotCol(1,:).*Par.ScrWhite;
- Par.FixInOutTime=[0 0];
- Par.FirstStimDrawDone=false;
- Par.ForceRespSide = false;
- Par.IsCatchBlock = false;
- Par.RewHandStart = GetSecs;
- Par.HandInNew_Moment = 0;
- Par.HandInPrev_Moment = 0;
- Par.PickRandomIndicatorPosition = true;
- Par.s_order=[1]; %#ok<*NBRAK>
-
- if StimLoopNr == 1 % allow time-outs to across runs
- Par.Pause=false;
- end
- if Par.Pause
- Screen('FillRect',Par.window,[0 0 0]);
- lft=Screen('Flip', Par.window); %initial flip to sync up timing
- else
- lft=Screen('Flip', Par.window); %initial flip to sync up timing
- end
- nf=0;
- Log.StartBlock=lft;
- Stm(STIMNR).IsPreDur=true;
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event='PreDurStart';
- Log.Events(Log.nEvents).t=Log.StartBlock-Par.ExpStart;
- Log.Events(Log.nEvents).info = 'Start';
- if TestRunstimWithoutDAS; Hit=0; end
-
- PreStarted = false;
- OnStarted = false;
- OffStarted = false;
- PostStarted = false;
- CurrPostErrorDelay = 0;
- nNonCatchTrials = 0;
- LastMissed = false;
- NumberOfConsecutiveErrors=0;
- if Par.CatchBlock.StartWithCatch
- Prev_nNonCatchTrials = -1;
- else
- Prev_nNonCatchTrials = nNonCatchTrials;
- end
-
- Log.dtm=[];
-
- if strcmp(Par.ResponseBox.Task, 'DetectGoSignal')
- RESP_NONE = 0;
- RESP_CORRECT = 1;
- RESP_FALSE = 2;
- RESP_MISS = 3;
- RESP_EARLY = 4;
- RESP_BREAK_FIX = 5;
- RespText = {'Correct', 'False', 'Miss', 'Early', 'Fix. break'};
- Par.ManResponse = [0 0 0 0 0];
- end
-
- RewardGivenForHandPos=false;
-
- Par.FirstInitDone=true;
- end
-
- %% Check what to draw depending on time ---------------------------
- if RetMapStimuli || MovieRun || VLCMovieRun
- if GetSecs < Log.StartBlock + Stm(STIMNR).RetMap.PreDur % PreDur
- IsPre=true;
- IsPost=false;
- if ~PreStarted
- PreStarted = true;
- CheckStartLogged = false;
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event='PreDurStart';
- Log.Events(Log.nEvents).t=GetSecs-Par.ExpStart;
- Log.Events(Log.nEvents).info = 'Start';
- posn=0;
- end
- elseif RetMapStimuli && ...
- GetSecs >= Log.StartBlock + Stm(STIMNR).RetMap.PreDur && ...
- GetSecs < Log.StartBlock + Stm(STIMNR).RetMap.PreDur + ...
- (Stm(STIMNR).RetMap.nCycles*size(Stm(STIMNR).RetMap.posmap,1)*...
- Stm(STIMNR).RetMap.TRsPerStep*Par.TR) % in stimulus cycle
- IsPre=false;
- IsPost=false;
- if ~OnStarted
- OnStarted=true;
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event='StimON';
- Log.Events(Log.nEvents).t=GetSecs-Par.ExpStart;
- Log.Events(Log.nEvents).info = Stm(STIMNR).Descript;
- end
-
- TRn=ceil((GetSecs-Log.StartBlock-Stm(STIMNR).RetMap.PreDur)/Par.TR);
- prevposn=posn;
- posn = ceil(TRn/Stm(STIMNR).RetMap.TRsPerStep);
-
- while posn>size(Stm(STIMNR).RetMap.posmap,1)
- posn=posn-size(Stm(STIMNR).RetMap.posmap,1);
- end
- posn=Stm(STIMNR).RetMap.posmap(posn,2);
- if posn ~= prevposn
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event='NewPosition';
- Log.Events(Log.nEvents).t=GetSecs-Par.ExpStart;
- Log.Events(Log.nEvents).info = posn;
- if strcmp(Par.SetUp,'NIN') % ephys
- dasbit(Par.StimB,1);
- daspause(0.05);
- dasbit(Par.StimB,0);
- %send_serial_data(posn);
- %WordsSent+1;
- %Log.Words(WordsSent)=posn;
- end
- end
-
- if strcmp(Stm(STIMNR).RetMap.StimType{1},'ret') && posn
- posn_adj = mod(posn-1,length(stimulus(1).img))+1;
- texn = ceil(mod(GetSecs-Log.StartBlock,Par.TR)*...
- ret_vid(posn_adj).fps);
- if ~texn; texn=1; end
- while texn>numel(ret_vid(posn_adj).text)
- texn=texn-numel(ret_vid(posn_adj).text);
- end
- elseif posn
- % posn_adj = mod(posn-1,length(stimulus(1).img))+1;
- % texn = ceil(mod(GetSecs-Log.StartBlock,Par.TR)*...
- % ret_vid(Stm(STIMNR).Order(posn_adj)).fps);
- % if ~texn; texn=1; end;
- % while texn>numel(ret_vid(Stm(STIMNR).Order(posn_adj)).text);
- % texn=texn-numel(ret_vid(Stm(STIMNR).Order(posn_adj)).text);
- % end
- texn = ceil(mod(GetSecs-Log.StartBlock,Par.TR)*...
- ret_vid(Stm(STIMNR).Order(posn)).fps);
- if ~texn; texn=1; end
- while texn>numel(ret_vid(Stm(STIMNR).Order(posn)).text)
- texn=texn-numel(ret_vid(Stm(STIMNR).Order(posn)).text);
- end
- end
- elseif (MovieRun || VLCMovieRun) && ...
- GetSecs >= Log.StartBlock + Stm(STIMNR).RetMap.PreDur && ...
- GetSecs < Log.StartBlock + Stm(STIMNR).RetMap.PreDur + ...
- (Stm(STIMNR).RetMap.moviedur/Stm(STIMNR).RetMap.movierate)
- IsPre=false;
- IsPost=false;
- if ~OnStarted
- OnStarted=true;
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event='StimON';
- Log.Events(Log.nEvents).t=GetSecs-Par.ExpStart;
- Log.Events(Log.nEvents).info = Stm(STIMNR).Descript;
- end
- elseif RetMapStimuli && ...
- GetSecs < Log.StartBlock + Stm(STIMNR).RetMap.PreDur + ...
- (Stm(STIMNR).RetMap.nCycles*size(Stm(STIMNR).RetMap.posmap,1)*...
- Stm(STIMNR).RetMap.TRsPerStep*Par.TR) + ...
- Stm(STIMNR).RetMap.PostDur % PostDur
- IsPre=false;
- IsPost = true;
- if ~PostStarted
- PostStarted=true;
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event='PostDurStart';
- Log.Events(Log.nEvents).t=GetSecs-Par.ExpStart;
- Log.Events(Log.nEvents).info = 'Start';
- tPostStarted=GetSecs;
- end
- elseif MovieRun && ...
- GetSecs < Log.StartBlock + Stm(STIMNR).RetMap.PreDur + ...
- (Stm(STIMNR).RetMap.moviedur/Stm(STIMNR).RetMap.movierate) + ...
- Stm(STIMNR).RetMap.PostDur % PostDur
- IsPre=false;
- IsPost = true;
- if ~PostStarted
- PostStarted=true;
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event='PostDurStart';
- Log.Events(Log.nEvents).t=GetSecs-Par.ExpStart;
- Log.Events(Log.nEvents).info = 'Start';
- tPostStarted=GetSecs;
- % Done. Stop playback:
- Screen('PlayMovie', Log.movie.name, 0);
- % Close movie object:
- Screen('CloseMovie', Log.movie.name);
- MovieRunning=false;
- end
- elseif VLCMovieRun && ...
- GetSecs < Log.StartBlock + Stm(STIMNR).RetMap.PreDur + ...
- Stm(STIMNR).RetMap.moviedur + Stm(STIMNR).RetMap.PostDur % PostDur
- IsPre=false;
- IsPost = true;
- if ~PostStarted
- PostStarted=true;
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event='PostDurStart';
- Log.Events(Log.nEvents).t=GetSecs-Par.ExpStart;
- Log.Events(Log.nEvents).info = 'Start';
- tPostStarted=GetSecs;
- % Done. Stop playback:
- eval(['!' stopVLCbat])
- Reopen_PTB_win;
- MovieRunning=false;
- end
- else
- RunEnded=true;
- IsPre=false;
- IsPost=false;
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event='RunStop';
- Log.Events(Log.nEvents).t=lft-Par.ExpStart;
- Log.Events(Log.nEvents).info = 'Stop';
- end
- DrawChecker=false;
- elseif DispChecker % coarse checkerboard
- %% fullscreen checkerboard
- if lft < Log.StartBlock+Stm(STIMNR).RetMap.PreDur
- IsPre = true;
- IsOn = false;
- IsOff = false;
- IsPost = false;
- if ~PreStarted
- PreStarted = true;
- CheckStartLogged = false;
- Log.CheckerON=[];
- Log.CheckerOFF=[];
- CheckStartLogged=false;
- CheckStopLogged=false;
- ChkNum = 1;
- end
- WasPreDur=true;
- DrawChecker = false;
- elseif mod(lft-Log.StartBlock-Stm(STIMNR).RetMap.PreDur,...
- sum(Stm(STIMNR).RetMap.Checker.OnOff)) <= ...
- Stm(STIMNR).RetMap.Checker.OnOff(1) && ...
- lft < Log.StartBlock + Stm(STIMNR).RetMap.PreDur + ...
- sum(Stm(STIMNR).RetMap.Checker.OnOff)*Stm(STIMNR).RetMap.nCycles
- IsPre = false;
- IsOn = true;
- IsOff = false;
- IsPost = false;
- if ~OnStarted
- OnStarted=true;
- OffStarted=false;
- Log.CheckerON = [Log.CheckerON; lft];
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event='StimON';
- Log.Events(Log.nEvents).t=lft-Par.ExpStart;
- Log.Events(Log.nEvents).info = Stm(STIMNR).Descript;
- CheckStartLogged = true;
- CheckStopLogged =false;
- end
- if WasPreDur % coming out of predur
- Par.FixInOutTime=[Par.FixInOutTime;0 0];
- WasPreDur=false;
- end
- if nCyclesDone < Stm(STIMNR).RetMap.nCycles || ...
- ~Stm(STIMNR).RetMap.nCycles
- DrawChecker = true;
- if nCyclesDone > 0 && nCyclesReported < nCyclesDone
- %output fixation statistics
- if Par.FixStatToCMD
- fprintf(['Fix perc. cycle ' num2str(nCyclesDone) ': ' ...
- sprintf('%0.1f',...
- 100*(Par.FixInOutTime(end,1)/sum(Par.FixInOutTime(end,:)))) ...
- '%%, Run: ' ...
- sprintf('%0.1f',...
- 100*(sum(Par.FixInOutTime(2:end,1))/sum(sum(Par.FixInOutTime(2:end,:))))) ...
- '%%\n']);
- Par.FixInOutTime = [Par.FixInOutTime;0 0];
- nCyclesReported=nCyclesReported+1;
- end
- end
- end
- elseif mod(lft-Log.StartBlock-Stm(STIMNR).RetMap.PreDur-Stm(STIMNR).RetMap.Checker.OnOff(1),...
- sum(Stm(STIMNR).RetMap.Checker.OnOff)) <= ...
- Stm(STIMNR).RetMap.Checker.OnOff(1) && ...
- lft < Log.StartBlock + Stm(STIMNR).RetMap.PreDur + ...
- sum(Stm(STIMNR).RetMap.Checker.OnOff)*Stm(STIMNR).RetMap.nCycles
- IsPre = false;
- IsOn = false;
- IsOff = true;
- IsPost = false;
- if ~OffStarted
- OffStarted=true;
- OnStarted=false;
- Log.CheckerOFF = [Log.CheckerOFF; lft];
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event='StimOFF';
- Log.Events(Log.nEvents).t=lft-Par.ExpStart;
- Log.Events(Log.nEvents).info = Stm(STIMNR).Descript;
- nCyclesDone=nCyclesDone+1;
- CheckStartLogged = false;
- CheckStopLogged =true;
- end
- DrawChecker = false;
- elseif mod(lft-Log.StartBlock-Stm(STIMNR).RetMap.PreDur,...
- sum(Stm(STIMNR).RetMap.Checker.OnOff)) <= ...
- Stm(STIMNR).RetMap.Checker.OnOff(1) && ...
- lft >= Log.StartBlock + Stm(STIMNR).RetMap.PreDur + ...
- sum(Stm(STIMNR).RetMap.Checker.OnOff)*Stm(STIMNR).RetMap.nCycles && ...
- ~PostStarted
- IsPre = false;
- IsOn = false;
- IsOff = false;
- IsPost = true;
- if ~PostStarted
- PostStarted=true;
- Log.StartPostDur=lft;
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event='PostDurStart';
- Log.Events(Log.nEvents).t=Log.StartPostDur-Par.ExpStart;
- Log.Events(Log.nEvents).info = 'Start';
- DrawChecker = false;
- if nCyclesDone > 0 && nCyclesReported < nCyclesDone
- %output fixation statistics
- if Par.FixStatToCMD
- fprintf(['Fix perc. cycle ' num2str(nCyclesDone) ': ' ...
- sprintf('%0.1f',...
- 100*(Par.FixInOutTime(end,1)/sum(Par.FixInOutTime(end,:)))) ...
- '%%, Run: ' ...
- sprintf('%0.1f',...
- 100*(sum(Par.FixInOutTime(2:end,1))/sum(sum(Par.FixInOutTime(2:end,:))))) ...
- '%%\n']);
- Par.FixInOutTime = [Par.FixInOutTime;0 0];
- nCyclesReported=nCyclesReported+1;
- end
- end
- end
- elseif lft >= Log.StartBlock + Stm(STIMNR).RetMap.PreDur + ...
- sum(Stm(STIMNR).RetMap.Checker.OnOff)*Stm(STIMNR).RetMap.nCycles + ...
- Stm(STIMNR).RetMap.PostDur
- RunEnded = true;
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event='RunStop';
- Log.Events(Log.nEvents).t=lft-Par.ExpStart;
- Log.Events(Log.nEvents).info = 'Stop';
- end
- else
- DrawChecker = false;
- end
-
- prevlft=lft;
- FixTimeThisFlip = 0; NonFixTimeThisFlip = 0;
- Par.LastFlipFix = Par.FixIn;
-
- %% Check if eye enters fixation window ----------------------------
- if ~Par.FixIn %not fixating
- if ~Par.CheckFixIn && ~TestRunstimWithoutDAS
- dasreset(0); % start testing for eyes moving into fix window
- % sets timer to 0
- %fprintf('dasreset in\n')
- end
- Par.CheckFixIn=true;
- Par.CheckFixOut=false;
- Par.CheckTarget=false;
- elseif Par.FixIn %fixating
- if ~Par.CheckFixOut && ~TestRunstimWithoutDAS
- dasreset(1); % start testing for eyes leaving fix window
- % sets timer to 0
- %fprintf('dasreset out\n')
- end
- Par.CheckFixIn=false;
- Par.CheckFixOut=true;
- Par.CheckTarget=false;
- end
-
- %% Check eye position ---------------------------------------------
- %Hit=0;
- if ~TestRunstimWithoutDAS
- dasrun(5); % takes max 5 ms
- [Hit, Time] = DasCheck;
- %Hit = LPStat(1); %Hit yes or no
- %Time = LPStat(0); %time
- end
-
- %% interpret ------------------------------------------------------
- if Par.CheckFixIn && Hit~=0
- % add time to fixation duration
- NonFixTimeThisFlip = NonFixTimeThisFlip+Time;
- Par.FixIn=true;
- %fprintf('fix in detected\n')
- Par.LastFixInTime=GetSecs;
- %Par.GoBarOnset = rand(1)*Par.EventPeriods(2)/1000 + ...
- % Par.EventPeriods(1)/1000;
- elseif Par.CheckFixOut && Hit~=0
- % add time to non-fixation duration
- FixTimeThisFlip = FixTimeThisFlip+Time;
- Par.FixIn=false;
- %fprintf('fix out detected\n')
- Par.LastFixOutTime=GetSecs;
- end
-
- %% Do this routine for all remaining flip time --------------------
- DoneOnce=false;
- while ~DoneOnce || GetSecs < prevlft+0.80*Par.fliptimeSec
- DoneOnce=true;
-
- %% check for key-presses --------------------------------------
- CheckKeys; % internal function
-
- %% Change stimulus if required --------------------------------
- ChangeStimulus(STIMNR);
-
- %% give manual reward -----------------------------------------
- if Par.ManualReward && ~TestRunstimWithoutDAS
- GiveRewardManual;
- Par.ManualReward=false;
- end
-
- %% give reward for hand in box --------------------------------
- if Par.RewardForHandsIn && ...
- any(Par.HandIsIn) && ~Par.Pause && ...
- ~Par.RewardRunning && ...
- GetSecs - Par.HandInNew_Moment > Par.RewardForHandsIn_Delay
- if GetSecs - Par.RewHandStart > Par.RewardForHandIn_MinInterval % kept in long enough
- GiveRewardAutoHandIn;
- elseif Par.RewardForHandIn_ResetIntervalWhenOut && ...
- Par.HandInPrev_Moment ~= Par.HandInNew_Moment && ...
- GetSecs - Par.RewHandStart > Par.RewardForHandIn_MinIntervalBetween
- GiveRewardAutoHandIn;
- end
- end
-
- %% check photosensor ------------------------------------------
- if ~TestRunstimWithoutDAS
- CheckManual;
- if ~strcmp(Par.ResponseBox.Task,'DetectGoSignal') && ...
- Par.StimNeeds.HandIsIn && ...
- ((strcmp(Par.HandInBothOrEither,'Both') && ~any(Par.HandIsIn)) || ...
- (strcmp(Par.HandInBothOrEither,'Either') && ~all(Par.HandIsIn)))
- % assumes only 1 photo-channel in use, or only checks
- % first defined channel
- Par.FixIn = false;
- % reset the fixation status to false if his hands are not where
- % they should be, otherwise he may get an immediate reward when
- % he maintains the proper eye-position and puts his hand in
- %
- % Doing this via StimNeedsHandInBox allows showing a fix dot
- % which is only marked as fixating when the hands are also in
- % the box
- end
- end
-
- %% Stop reward ------------------------------------------------
- StopRewardIfNeeded();
- end
-
- %% Draw stimulus --------------------------------------------------
- if ~Par.Pause
- if RetMapStimuli
- DrawStimuli;
- if ~IsPre && ~IsPost && ~RunEnded && ~Par.ToggleHideStim ...
- && ~Par.HideStim_BasedOnHandIn(Par) ...
- && ~Par.Pause
- if strcmp(Stm(STIMNR).RetMap.StimType{1},'ret')
- posn_adj = (mod(posn-1,length(stimulus(1).img))+1);
- orinum = ceil(posn/length(stimulus(1).img));
- if posn
- if strcmp(Stm(STIMNR).RetMap.StimType{2},'pRF_8bar')
- Screen('DrawTexture',Par.window,ret_vid(posn_adj).text(texn),...
- [],[],ret_vid(posn).orient(orinum),1);
- else
- Screen('DrawTexture',Par.window,ret_vid(posn).text(texn),...
- [],[],[],1);
- end
- end
- else
- if posn
- Screen('DrawTexture',Par.window,ret_vid(posn).text(texn),...
- [],[Par.ScrCenter(1)-Par.wrect(4)/2 0 ...
- Par.ScrCenter(1)+Par.wrect(4)/2 Par.wrect(4)],...
- [],1);
- end
- end
- end
- elseif MovieRun || VLCMovieRun
- if MovieRun
- DrawStimuli;
- end
- if ~IsPre && ~IsPost && ~RunEnded && ~Par.ToggleHideStim ...
- && ~Par.HideStim_BasedOnHandIn(Par) ...
- && ~Par.Pause
- % start the movie if it hasn't started yet
- if ~MovieRunning
- if MovieRun
- Screen('PlayMovie', Log.movie.name, Stm(STIMNR).RetMap.movierate, 1, 0);
- % looping avoid early stops (duration is regulated
- % based on movieduration separately)
- MovieRunning=true;
- % calculate movie presentation size
- PlayWindow = [ (Par.wrect(3)-Stm(STIMNR).RetMap.PlaySize(1))/2 0 ...
- Par.wrect(3)-(Par.wrect(3)-Stm(STIMNR).RetMap.PlaySize(1))/2 ...
- Stm(STIMNR).RetMap.PlaySize(2)];
- elseif VLCMovieRun
- fprintf('\n========================================\n');
- fprintf('Temporarily closing PTB window for VLC\n');
- fprintf('========================================\n');
- Close_PTB_win;
- eval(['!' moviebat ' &']);
- MovieRunning=true;
- end
- end
- if MovieRun
- % grab a texture
- movietex = Screen('GetMovieImage', Par.window, Log.movie.name, 1);
- % draw that texture
- if movietex>0
- Screen('DrawTexture', Par.window, movietex, [], ...
- PlayWindow, [], [], [], [], []);
- end
- end
- end
- elseif DrawChecker
- DrawStimuli;
- if ~Par.HideStim_BasedOnHandIn(Par) && ~Par.Pause
- Screen('DrawTexture',Par.window,CheckTexture(ChkNum),[],...
- [],[],1);
- end
- else
- DrawStimuli;
- end
- end
-
- %% Draw fixation dot ----------------------------------------------
- if ~Par.ToggleHideFix ...
- && ~Par.HideFix_BasedOnHandIn(Par) ...
- && ~Par.Pause && ~MovieRun && ~VLCMovieRun
- DrawFix(STIMNR);
- end
-
- if ~FixTimeThisFlip && ~NonFixTimeThisFlip
- % new event
- if FixTimeThisFlip > NonFixTimeThisFlip % more fixation than not
- Par.AddFixIn = true;
- else
- Par.AddFixIn = false;
- end
- else
- % continuation of previous flip
- if Par.FixIn % already fixating
- Par.AddFixIn = true;
- else
- Par.AddFixIn = false;
- end
- end
-
- %% darken the screen if on time-out -------------------------------
- if Par.Pause
- Screen('FillRect',Par.window,[0 0 0]);
- end
-
- %% Calculate proportion fixation for this flip-time and label it --
- % fix or no-fix
- if Par.FixIn
- if Par.RewardFixFeedBack
- Par.CurrFixCol=Stm(STIMNR).FixDotCol(2,:).*Par.ScrWhite;
- end
-
- Par.Trlcount=Par.Trlcount+1;
- %refreshtracker(3);
- if GetSecs >= Par.LastFixInTime+Par.Times.TargCurrent/1000 % fixated long enough
- % start Reward
- if ~Par.RewardRunning && ~TestRunstimWithoutDAS && ~Par.Pause && ...
- Par.Rew_BasedOnHandIn(Par) && ~Par.HideFix_BasedOnHandIn(Par)
- % nCons correct fixations
- Par.CorrStreakcount=Par.CorrStreakcount+1;
- Par.Response=Par.Response+1;
- Par.ResponsePos=Par.ResponsePos+1;
- % Start reward ========================================
- if ~strcmp(Par.ResponseBox.Task, 'DetectGoSignal') % when not doing task
- GiveRewardAutoFix; % ------------------------ Fix Reward
- Par.RewardRunning=true;
- Par.RewardStartTime=GetSecs;
- Par.LastFixInTime=Par.RewardStartTime; % reset start fix time
- end
- Par.Trlcount=Par.Trlcount+1;
- %refreshtracker(1);refreshtracker(3);
- end
- end
- else
- Par.CurrFixCol=Stm(STIMNR).FixDotCol(1,:).*Par.ScrWhite;
- Par.CorrStreakcount=[0 0];
- %refreshtracker(1);
- end
-
- %% Stop reward ----------------------------------------------------
- StopRewardIfNeeded();
-
- %% Autopause due to lever lifts -----------------------------------
- if Par.LeversUpTimeOut(2) % there is a timeout interval defined
- if all(Par.LeverIsUp) && ... % both up
- GetSecs > Par.BothLeversUp_time + Par.LeversUpTimeOut(1) && ...
- ~Par.Pause % levers have been up too long
- Par.Pause=true;
- fprintf(['Automatic time-out due to lever lifts ON (min ' ...
- num2str(Par.LeversUpTimeOut(2)) 's)\n']);
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event='AutoPauseOn';
- Log.Events(Log.nEvents).t=GetSecs-Par.ExpStart;
- Log.Events(Log.nEvents).info = 'Start';
- AutoPauseStartTime=GetSecs;
- AutoPausing = true;
- elseif GetSecs > AutoPauseStartTime + Par.LeversUpTimeOut(2) && ...
- Par.Pause && AutoPausing % Time-out time over
- if all(Par.LeverIsUp)
- % still both up, continue time-out
- else
- Par.Pause=false;
- fprintf('Automatic time-out due to lever lifts OFF\n');
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event='AutoPauseOff';
- Log.Events(Log.nEvents).t=GetSecs-Par.ExpStart;
- Log.Events(Log.nEvents).info = 'Stop';
- AutoPausing = false;
- end
- end
- end
-
- %% if doing Par.ResponseBox.Task of 'DetectGoSignal': -------------
- if strcmp(Par.ResponseBox.Task, 'DetectGoSignal') && ~TestRunstimWithoutDAS
- % ==== Start wait period ====
- if Par.ResponseState == Par.RESP_STATE_DONE && ...
- Par.CanStartTrial(Par)
- UpdateHandTaskState(Par.RESP_STATE_WAIT);
- %Par.ResponseState = Par.RESP_STATE_WAIT;
- %Par.ResponseStateChangeTime = GetSecs;
- StartWaitTime = Par.ResponseStateChangeTime;
-
- if Par.PickRandomIndicatorPosition
- Par.s_order=randperm(size(Par.RespIndPos,1));
- Par.PickRandomIndicatorPosition = false;
- end
-
- if ~Par.IsCatchBlock
- if Par.ResponseSide == 0 || Par.ForceRespSide
- if NumberOfConsecutiveErrors >= Par.MaxNumberOfConsecutiveErrors
- if Par.ResponseSide == 1
- Par.ResponseSide = 2;
- else
- Par.ResponseSide =1;
- end
- else
- if Par.RespProbSetting % 0=random, 1=left, 2=right
- Par.ResponseSide = Par.RespProbSetting;
- else
- Par.ResponseSide = randi([1 2]);
- Par.ForceRespSide = false;
- end
- end
- end
- elseif Par.IsCatchBlock % catchblock
- Par.ResponseSide = CatchSides(1);
- end
- Par.CurrResponseSide = Par.ResponseSide;
- Log.Events(Log.nEvents).info = num2str(Par.ResponseSide);
- Par.GoBarOnset = rand(1)*Par.EventPeriods(2)/1000 + ...
- Par.EventPeriods(1)/1000 + CurrPostErrorDelay/1000;
- Par.WaitIndicatorOnset = Par.DrawDuringWait_SOA + CurrPostErrorDelay/1000;
-
- % Give side indicator (1 or 2) ... again
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event=strcat(...
- 'HandTask-TargetSide', num2str(Par.ResponseSide));
- Log.Events(Log.nEvents).t=Par.ResponseStateChangeTime;
- % ==== During wait period ====
- elseif Par.ResponseState == Par.RESP_STATE_WAIT
- if Par.RespIndLeds; dasbit(Par.LED_B(1),0);dasbit(Par.LED_B(2),0);end % LEDS off
- if GetSecs >= Par.ResponseStateChangeTime + Par.GoBarOnset
- UpdateHandTaskState(Par.RESP_STATE_GO);
- %Par.ResponseState = Par.RESP_STATE_GO;
- %Par.ResponseStateChangeTime = GetSecs;
- CurrPostErrorDelay=0;
- end
- % check for early responses before go-signal -----
- t = GetSecs;
- if (Par.CorrectResponseGiven(Par) || ... % Early during wait
- Par.IncorrectResponseGiven(Par))
- UpdateHandTaskState(Par.RESP_STATE_DONE);
- if Par.CorrectResponseGiven(Par)
- Log.Events(Log.nEvents).info = 'EarlyCorrect';
- else
- Log.Events(Log.nEvents).info = 'EarlyIncorrect';
- end
- Par.ManResponse(RESP_EARLY) = Par.ManResponse(RESP_EARLY)+1;
- %fprintf('Early during wait\n');
- CurrPostErrorDelay = Par.PostErrorDelay;
- if ~Par.ForceRespSide
- if rand(1) <= Par.ProbSideRepeatOnEarly % same side
- Par.ResponseSide=Par.ResponseSide; % keep same
- else
- if Par.ResponseSide==1
- Par.ResponseSide=2;
- else
- Par.ResponseSide=1;
- end
- end
- end
- if Par.IsCatchBlock
- CatchSides = Shuffle(CatchSides);
- else
- nNonCatchTrials = nNonCatchTrials+1;
- end
- LastMissed = false;
- % play feedback sound
- if Par.ResponseState > 0 && ...
- isfield(Par, 'FeedbackSound') && ...
- isfield(Par, 'FeedbackSoundPar') && ...
- Par.FeedbackSound(4) && ...
- all(~isnan(Par.FeedbackSoundPar(4,:)))
- if Par.FeedbackSoundPar(4)
- try
- % fprintf('trying to play a sound\n')
- PsychPortAudio('Start', ...
- Par.FeedbackSoundSnd(4).h, 1, 0, 1);
- catch
- end
- end
- end
- end
- % -----
- % ==== Go signal is given ====
- elseif Par.ResponseState == Par.RESP_STATE_GO
- t = GetSecs;
- % ---- Early after go ----
- if (Par.CorrectResponseGiven(Par) || ...
- Par.IncorrectResponseGiven(Par)) && ...
- t < Par.ResponseStateChangeTime + ...
- Par.ResponseAllowed(1)/1000
- % Early response after go-signal ------
- UpdateHandTaskState(Par.RESP_STATE_DONE);
- if Par.CorrectResponseGiven(Par)
- Log.Events(Log.nEvents).info = 'EarlyCorrect';
- else
- Log.Events(Log.nEvents).info = 'EarlyIncorrect';
- end
- Par.ManResponse(RESP_EARLY) = Par.ManResponse(RESP_EARLY)+1;
- %fprintf('Early after go\n');
- CurrPostErrorDelay = Par.PostErrorDelay;
- if ~Par.ForceRespSide
- if rand(1) <= Par.ProbSideRepeatOnEarly % same side
- Par.ResponseSide=Par.ResponseSide; % keep same
- else
- if Par.ResponseSide==1
- Par.ResponseSide=2;
- else
- Par.ResponseSide=1;
- end
- end
- if Par.IsCatchBlock
- CatchSides = Shuffle(CatchSides);
- else
- nNonCatchTrials = nNonCatchTrials+1;
- end
- end
- LastMissed = false;
- % play feedback sound
- if Par.ResponseState > 0 && ...
- isfield(Par, 'FeedbackSound') && ...
- isfield(Par, 'FeedbackSoundPar') && ...
- Par.FeedbackSound(4) && ...
- all(~isnan(Par.FeedbackSoundPar(4,:)))
- if Par.FeedbackSoundPar(4)
- try
- % fprintf('trying to play a sound\n')
- PsychPortAudio('Start', ...
- Par.FeedbackSoundSnd(4).h, 1, 0, 1);
- catch
- end
- end
- end
- % ---- Incorrect ----
- elseif Par.IncorrectResponseGiven(Par) && Par.RespLeverMatters
- UpdateHandTaskState(Par.RESP_STATE_DONE);
- Log.Events(Log.nEvents).info = 'Incorrect';
- NumberOfConsecutiveErrors=NumberOfConsecutiveErrors+1;
- if ~Par.ForceRespSide
- if rand(1) <= Par.ProbSideRepeatOnError % same side
- Par.ResponseSide=Par.ResponseSide; % keep same
- else
- if Par.ResponseSide==1
- Par.ResponseSide=2;
- else
- Par.ResponseSide=1;
- end
- end
- end
- % RESP_NONE = 0; RESP_CORRECT = 1;
- % RESP_FALSE = 2; RESP_MISS = 3;
- % RESP_EARLY = 4; RESP_BREAK_FIX = 5;
- Par.ManResponse(RESP_FALSE) = Par.ManResponse(RESP_FALSE)+1;
- %fprintf('Error\n');
- CurrPostErrorDelay = Par.PostErrorDelay;
- if Par.IsCatchBlock
- CatchSides = Shuffle(CatchSides);
- else
- nNonCatchTrials = nNonCatchTrials+1;
- end
- LastMissed = false;
- % play feedback sound
- if Par.ResponseState > 0 && ...
- isfield(Par, 'FeedbackSound') && ...
- isfield(Par, 'FeedbackSoundPar') && ...
- Par.FeedbackSound(2) && ...
- all(~isnan(Par.FeedbackSoundPar(2,:)))
- if Par.FeedbackSoundPar(2)
- try
- % fprintf('trying to play a sound\n')
- PsychPortAudio('Start', ...
- Par.FeedbackSoundSnd(2).h, 1, 0, 1);
- catch
- end
- end
- end
- % ---- Correct ----
- elseif Par.CorrectResponseGiven(Par) && Par.RespLeverMatters
- %Par.ResponseStateChangeTime = GetSecs;
- %Par.ResponseState = Par.RESP_STATE_DONE;
- UpdateHandTaskState(Par.RESP_STATE_DONE);
- Log.Events(Log.nEvents).info = 'Hit';
- NumberOfConsecutiveErrors=0;
- GiveRewardAutoTask;
- if ~Par.ForceRespSide
- if rand(1) <= Par.ProbSideRepeatOnCorrect % same side
- Par.ResponseSide=Par.ResponseSide; % keep same
- else
- if Par.ResponseSide==1
- Par.ResponseSide=2;
- else
- Par.ResponseSide=1;
- end
- end
- end
- % RESP_NONE = 0; RESP_CORRECT = 1;
- % RESP_FALSE = 2; RESP_MISS = 3;
- % RESP_EARLY = 4; RESP_BREAK_FIX = 5;
- Par.ManResponse(RESP_CORRECT) = Par.ManResponse(RESP_CORRECT)+1;
- %fprintf('Correct\n');
- CurrPostErrorDelay = Par.PostCorrectDelay;
- if Par.IsCatchBlock
- CatchSides(1) = [];
- else
- nNonCatchTrials = nNonCatchTrials+1;
- end
- LastMissed = false;
- % play feedback sound
- if Par.ResponseState > 0 && ...
- isfield(Par, 'FeedbackSound') && ...
- isfield(Par, 'FeedbackSoundPar') && ...
- Par.FeedbackSound(1) && ...
- all(~isnan(Par.FeedbackSoundPar(1,:)))
- if Par.FeedbackSoundPar(1)
- try
- % fprintf('trying to play a sound\n')
- PsychPortAudio('Start', ...
- Par.FeedbackSoundSnd(1).h, 1, 0, 1);
- catch
- end
- end
- end
- % Correct if side doesn't matter
- elseif ~Par.RespLeverMatters && ...
- (Par.CorrectResponseGiven(Par) || Par.IncorrectResponseGiven(Par))
- UpdateHandTaskState(Par.RESP_STATE_DONE);
- Log.Events(Log.nEvents).info = 'HitEither';
- GiveRewardAutoTask;
- if ~Par.ForceRespSide
- if rand(1) <= Par.ProbSideRepeatOnCorrect % same side
- Par.ResponseSide=Par.ResponseSide; % keep same
- else
- if Par.ResponseSide==1
- Par.ResponseSide=2;
- else
- Par.ResponseSide=1;
- end
- end
- end
- % RESP_NONE = 0; RESP_CORRECT = 1;
- % RESP_FALSE = 2; RESP_MISS = 3;
- % RESP_EARLY = 4; RESP_BREAK_FIX = 5;
- Par.ManResponse(RESP_CORRECT) = Par.ManResponse(RESP_CORRECT)+1;
- %fprintf('Correct\n');
- CurrPostErrorDelay = Par.PostCorrectDelay;
- if Par.IsCatchBlock
- CatchSides(1) = [];
- else
- nNonCatchTrials = nNonCatchTrials+1;
- end
- LastMissed = false;
- % play feedback sound
- if Par.ResponseState > 0 && ...
- isfield(Par, 'FeedbackSound') && ...
- isfield(Par, 'FeedbackSoundPar') && ...
- Par.FeedbackSound(1) && ...
- all(~isnan(Par.FeedbackSoundPar(1,:)))
- if Par.FeedbackSoundPar(1)
- try
- % fprintf('trying to play a sound\n')
- PsychPortAudio('Start', ...
- Par.FeedbackSoundSnd(1).h, 1, 0, 1);
- catch
- end
- end
- end
- % ---- Miss ----
- elseif t >= Par.ResponseStateChangeTime + ...
- Par.ResponseAllowed(2)/1000
- UpdateHandTaskState(Par.RESP_STATE_DONE);
- Log.Events(Log.nEvents).Info = 'Miss';
- %Par.ResponseState = Par.RESP_STATE_DONE;
- %Par.ResponseStateChangeTime = GetSecs;
- if ~Par.ForceRespSide
- if rand(1) <= Par.ProbSideRepeatOnMiss % same side
- Par.ResponseSide=Par.ResponseSide; % keep same
- else
- if Par.ResponseSide==1
- Par.ResponseSide=2;
- else
- Par.ResponseSide=1;
- end
- end
- end
- % RESP_NONE = 0; RESP_CORRECT = 1;
- % RESP_FALSE = 2; RESP_MISS = 3;
- % RESP_EARLY = 4; RESP_BREAK_FIX = 5;
- Par.ManResponse(RESP_MISS) = Par.ManResponse(RESP_MISS)+1;
- LastMissed = true;
- %fprintf('Miss\n');
- CurrPostErrorDelay = Par.DelayOnMiss;
- if Par.IsCatchBlock
- CatchSides = Shuffle(CatchSides);
- else
- nNonCatchTrials = nNonCatchTrials+1;
- end
- % play feedback sound
- if Par.ResponseState > 0 && ...
- isfield(Par, 'FeedbackSound') && ...
- isfield(Par, 'FeedbackSoundPar') && ...
- Par.FeedbackSound(3) && ...
- all(~isnan(Par.FeedbackSoundPar(3,:)))
- if Par.FeedbackSoundPar(3)
- try
- % fprintf('trying to play a sound\n')
- PsychPortAudio('Start', ...
- Par.FeedbackSoundSnd(3).h, 1, 0, 1);
- catch
- end
- end
- end
- end
- end
- % draw the indicators
- if ~Par.ToggleHideFix && ~Par.HideFix_BasedOnHandIn(Par) && ~Par.Pause
- if Par.ResponseState == Par.RESP_STATE_WAIT && ... ~LastMissed && ...
- (isfield(Par,'NoIndicatorDuringPunishDelay') && ...
- Par.NoIndicatorDuringPunishDelay) && ...
- (GetSecs < StartWaitTime + CurrPostErrorDelay/1000)
- else
- DrawHandIndicator(STIMNR);
- DrawGoBar(STIMNR);
- end
- end
- end
-
- %% dim the screen if requested due to hand position ---------------
- AutoDim; % checks by itself if it's required
-
- %% refresh the screen ---------------------------------------------
- if Par.Allow_Calls_To_PTB_win
- %lft=Screen('Flip', Par.window, prevlft+0.9*Par.fliptimeSec);
- lft=Screen('Flip', Par.window); % as fast as possible
- nf=nf+1;
- end
-
- %% log eye-info if required ---------------------------------------
- LogEyeInfo;
-
- %% change the checkerboard contrast if required -------------------
- if DrawChecker
- if TrackingCheckerContChange
- if lft-tLastCheckerContChange >= ...
- 1/Stm(1).RetMap.Checker.FlickFreq_Approx
- if ChkNum==1
- ChkNum=2;
- elseif ChkNum==2
- ChkNum=1;
- end
- tLastCheckerContChange=lft;
- end
- else
- tLastCheckerContChange=lft;
- TrackingCheckerContChange=true;
- end
- end
-
- %% Switch position if required to do this automatically -----------
- if Par.ToggleCyclePos && Stm(STIMNR).CyclePosition && ...
- Par.Trlcount(1) >= Stm(STIMNR).CyclePosition
- % next position
- Par.SwitchPos = true;
- Par.WhichPos = 'Next';
- ChangeStimulus(STIMNR);
- Par.SwitchPos = false;
- end
-
- %% update fixation times ------------------------------------------
- if nf>1 %&& ~Stm(STIMNR).IsPreDur
- dt=lft-prevlft;
- % log the screen flip timing
- Log.dtm=[Log.dtm;dt GetSecs-Par.ExpStart];
- if Par.FixIn % fixating
- Par.FixInOutTime(end,1)=Par.FixInOutTime(end,1)+dt;
- else
- Par.FixInOutTime(end,2)=Par.FixInOutTime(end,2)+dt;
- end
- end
-
- %% Update Tracker window ------------------------------------------
- if ~TestRunstimWithoutDAS && update_trackerfix_now
- %SCNT = {'TRIALS'};
- SCNT(1) = { ['F: ' num2str(Par.Response) ' FC: ' num2str(Par.CorrStreakcount(2))]};
- %SCNT(2) = { ['FC: ' num2str(Par.CorrStreakcount(2)) ] };
- SCNT(2) = { ['%FixC: ' ...
- sprintf('%0.1f',100*(Par.FixInOutTime(end,1)/sum(Par.FixInOutTime(end,:))))]};
- if size(Par.FixInOutTime,1)>=2
- SCNT(3) = { ['%FixR: ' ...
- sprintf('%0.1f',100* ( sum(Par.FixInOutTime(2:end,1))/sum( sum(Par.FixInOutTime(2:end,:)))))]};
- else
- SCNT(3) = { ['%FixR: ' ...
- sprintf('%0.1f',100* ( sum(Par.FixInOutTime(:,1))/sum( sum(Par.FixInOutTime) ) ))]};
- end
- if strcmp(Par.ResponseBox.Task, 'DetectGoSignal')
- SCNT(4) = { ['C: ' num2str(Par.ManResponse(RESP_CORRECT)) ...
- ' F: ' num2str(Par.ManResponse(RESP_FALSE))]};
- SCNT(5) = { ['M: ' num2str(Par.ManResponse(RESP_MISS)) ...
- ' E: ' num2str(Par.ManResponse(RESP_EARLY))]};
- else
- SCNT(4) = { 'NO MANUAL'};
- SCNT(5) = { 'NO MANUAL'};
- end
- SCNT(6) = { ['Rew: ' num2str(Log.TotalReward) ] };
- set(Hnd(1), 'String', SCNT ) %display updated numbers in GUI
- % Give noise-on-eye-channel info
- SD = dasgetnoise();
- SD = SD./Par.PixPerDeg;
- set(Hnd(2), 'String', SD )
- last_trackerfix_update = GetSecs;
- end
- if ~TestRunstimWithoutDAS && ...
- GetSecs - last_trackerfix_update >= 1 % update tracker every second
- update_trackerfix_now=true;
- else
- update_trackerfix_now=false;
- end
-
- %% Catch block ----------------------------------------------------
- if strcmp(Par.ResponseBox.Task,'DetectGoSignal') && ...
- Par.CatchBlock.do && ~Par.IsCatchBlock && ...
- nNonCatchTrials > Prev_nNonCatchTrials && ...
- mod(nNonCatchTrials,Par.CatchBlock.AfterNumberOfTrials)==0
- Par.IsCatchBlock = true;
- %fprintf('Catch block started...')
- CatchSides = Shuffle([ones(1,Par.CatchBlock.NoCorrectPerSideNeeded) ...
- 2*ones(1,Par.CatchBlock.NoCorrectPerSideNeeded)]);
- Prev_nNonCatchTrials = nNonCatchTrials;
- elseif strcmp(Par.ResponseBox.Task,'DetectGoSignal') && ...
- Par.CatchBlock.do && Par.IsCatchBlock && isempty(CatchSides)
- Par.IsCatchBlock = false;
- %fprintf('completed\n')
- end
-
- %% Stop reward ----------------------------------------------------
- StopRewardIfNeeded();
- end
- % if breaking out with stop/escape during vlc
- if VLCMovieRun
- if MovieRunning
- eval(['!' stopVLCbat])
- Reopen_PTB_win;
- MovieRunning=false;
- end
- end
-
- %% Clean up and Save Log ----------------------------------------------
- % end eye recording if necessary
- if Par.EyeRecAutoTrigger && ~EyeRecMsgShown
- cn=0;
- while Par.EyeRecStatus == 0 && cn < 100
- CheckEyeRecStatus; % checks the current status of eye-recording
- cn=cn+1;
- end
- if Par.EyeRecStatus % recording
- while Par.EyeRecStatus
- SetEyeRecStatus(0);
- pause(1)
- CheckEyeRecStatus
- end
- fprintf('\nStopped eye-recording. Save the file or add more runs.\n');
- %fprintf(['Suggested filename: ' Par.MONKEY '_' DateString '.tda\n']);
- else % not recording
- fprintf('\n>> Alert! Could not find a running eye-recording!\n');
- end
- EyeRecMsgShown=true;
- end
-
- if MovieRun
- if MovieRunning
- % Done. Stop playback:
- Screen('PlayMovie', Log.movie.name, 0);
- % Close movie object:
- Screen('CloseMovie', Log.movie.name);
- MovieRunning=false;
- end
- end
-
- if ~isempty(Stm(STIMNR).Descript) && ~TestRunstimWithoutDAS
-
- % Empty the screen
- if ~Par.Pause
- Screen('FillRect',Par.window,Par.BG.*Par.ScrWhite);
- else
- Screen('FillRect',Par.window,[0 0 0].*Par.ScrWhite); % black first
- end
- lft=Screen('Flip', Par.window,lft+.9*Par.fliptimeSec);
- if ~TestRunstimWithoutDAS
- dasjuice(0); %stop reward if its running
- end
-
- % go back to default priority
- Priority(oldPriority);
-
- % save stuff
- if strcmp(Par.SetUp,'NIN') % ephys
- LogPath = fullfile(Par.LogFolder,... % base log folder
- Par.SetUp,... % setup
- Par.LogFolder,... % task (/subtask)
- Par.MONKEY,... % subject
- [Par.MONKEY '_' DateString(1:8)],... % session
- [Par.MONKEY '_HRF_' DateString_sec]... % run
- );
- else
- LogPath = fullfile(getenv('TRACKER_LOGS'),... % base log folder
- Par.SetUp,... % setup
- Par.LogFolder,... % task (/subtask)
- Par.MONKEY,... % subject
- [Par.MONKEY '_' DateString(1:8)],... % session
- [Par.MONKEY '_HRF_' DateString_sec]... % run
- );
-
- end
- LogFn = [Par.SetUp '_' Par.MONKEY '_' DateString_sec];
- [~,~,~] = mkdir(LogPath);
- cd(LogPath)
-
- if ~TestRunstimWithoutDAS
- if strcmp(Par.SetUp,'NIN')
- FileName=['Log_' LogFn '_' ...
- Stm(STIMNR).Descript '_Run' num2str(StimLoopNr) '_Block' num2str(blockstr)];
- evFileName=[FileName '_eventlog.csv'];
- else
- FileName=['Log_' LogFn '_' ...
- Stm(STIMNR).Descript '_Run' num2str(StimLoopNr)];
- evFileName=[FileName '_eventlog.csv'];
- end
- else
- FileName=['Log_NODAS_' LogFn '_' ...
- Stm(STIMNR).Descript '_Run' num2str(StimLoopNr)];
- evFileName=[FileName '_eventlog.csv'];
- end
- warning off;
- if TestRunstimWithoutDAS; cd ..;end
- StimObj.Stm=Stm;
- % 1st is PreStim, last is PostStim
- Log.FixPerc=100*(Par.FixInOutTime(:,1)./sum(Par.FixInOutTime,2));
-
- % copy the originally used files
- if ~RunParStim_Saved
- % runstim
- fn=['Runstim_' LogFn '.m'];
- cfn=[mfilename('fullpath') '.m'];
- copyfile(cfn,fn);
- % parsettings
- parsetpath = which(Par.PARSETFILE);
- if isempty(ls(Par.PARSETFILE)) % doesn't exist yet
- copyfile(parsetpath,[Par.PARSETFILE '.m']);
- end
- % stimsettings
- stimsetpath = which(Par.STIMSETFILE);
- if isempty(ls(Par.STIMSETFILE)) % doesn't exist yet
- copyfile(stimsetpath,[Par.STIMSETFILE '.m']);
- end
- % stimulus
- if RetMapStimuli
- save('RetMap_Stimulus','ret_vid');
- end
- RunParStim_Saved=true;
- end
-
- % save the events to a csv file
- if length(Log.Events) > 8
- EventCell = cell(length(Log.Events)+1,3);
- %VarNames={'time_s','type','StimName'}; % << old column names
- VarNames={'time_s','event','info'}; % compatible eith other experiments
- for ev = 1:length(Log.Events)
- %EventCell(ev,:)={...
- % Log.Events(ev).t,...
- % Log.Events(ev).type,...
- % Log.Events(ev).StimName };
- EventCell(ev,:)={...
- Log.Events(ev).t,...
- Log.Events(ev).event,...
- Log.Events(ev).info };
- end
- EvTable = cell2table(EventCell,'variablenames',VarNames');
- writetable(EvTable,evFileName)
-
- % save mat and json files
- if ~TestRunstimWithoutDAS && ~json_done &&...
- (StimLoopNr==Stm(1).nRepeatsStimSet || ...
- (Par.ESC && StimLoopNr~=Stm(1).nRepeatsStimSet))
-
- % save json file ===========
- Par.jf.Project = 'Retinotopy';
- if strcmp(Par.SetUp,'NIN')
- Par.jf.Method = 'EPHYS';
- else
- Par.jf.Method = 'MRI';
- end
- Par.jf.Protocol = '17.25.01';
-
- Par.jf.Dataset = Par.LogFolder(...
- find(Par.LogFolder=='\',1,'last')+1:end);
-
- Par.jf.Date = datestr(now,'yyyymmdd');
- Par.jf.Subject = Par.MONKEY;
- Par.jf.Researcher = 'ChrisKlink';
- Par.jf.Setup = Par.SetUp;
- Par.jf.Group = 'awake';
- Par.jf.Stimulus = Stm(STIMNR).Descript;
- Par.jf.LogFolder = [Par.MONKEY '_' DateString];
- Par.jf.logfile_name = FileName; %%%%%%%%
- Par.jf.fixperc = Log.FixPerc;
- Par.jf.RunNumber = 'XXX';
- Par.jf.QualityAsses = '10';
- Par.jf.Comment = '';
- % give the possibility to change
- % only when at scanner
- if strcmp(Par.SetUp, 'Spinoza_3T') || strcmp(Par.SetUp, 'NIN')
- json_defanswer = {Par.jf.Project,Par.jf.Method,Par.jf.Protocol,...
- Par.jf.Dataset,Par.jf.Subject,Par.jf.Researcher,...
- Par.jf.Setup,Par.jf.Group,Par.jf.RunNumber,...
- Par.jf.QualityAsses,Par.jf.Comment};
- json_answer = inputdlg(...
- {'Project','Method','Protocol',...
- 'Dataset','Subject','Researcher',...
- 'Setup','Group','Run','Quality (0-10)',...
- 'Comment'},'JSON SPECS',1,json_defanswer,'on');
- if isempty(json_answer);json_answer=json_defanswer;end
- Par.jf.Project = json_answer{1};
- Par.jf.Method = json_answer{2};
- Par.jf.Protocol = json_answer{3};
- Par.jf.Dataset = json_answer{4};
- Par.jf.Subject = json_answer{5};
- Par.jf.Researcher = json_answer{6};
- Par.jf.Setup = json_answer{7};
- Par.jf.Group = json_answer{8};
- Par.jf.RunNumber = json_answer{9};
- Par.jf.QualityAsses = json_answer{10};
- Par.jf.Comment = json_answer{11};
- end
- json.project.title = Par.jf.Project;
- json.project.method = Par.jf.Method;
- json.dataset.protocol = Par.jf.Protocol;
- json.dataset.name = Par.jf.Dataset;
- json.session.date = Par.jf.Date;
- json.session.subjectId = Par.jf.Subject;
- json.session.investigator = Par.jf.Researcher;
- json.session.setup = Par.jf.Setup;
- json.session.group = Par.jf.Group;
- json.session.stimulus = Par.jf.Stimulus;
- json.session.logfile = Par.jf.logfile_name;
- json.session.logfolder = Par.jf.LogFolder;
- json.session.fixperc = Par.jf.fixperc;
- json.session.run = Par.jf.RunNumber;
- json.session.quality = Par.jf.QualityAsses;
- json.session.comment = Par.jf.Comment;
-
- % retrospectively create jsons for all runs
- for jj = 1:StimLoopNr % save json files for all runs
- if strcmp(Par.SetUp,'NIN')
- json.session.logfile=['Log_' LogFn '_' ...
- Stm(STIMNR).Descript '_Run' num2str(jj) '_Block' num2str(blockstr)];
- else
- json.session.logfile=['Log_' LogFn '_' ...
- Stm(STIMNR).Descript '_Run' num2str(jj)];
- end
- if jj<StimLoopNr
- json.session.fixperc = CollectPerformance{jj,2};
- else
- json.session.fixperc = Par.jf.fixperc;
- end
- savejson('', json, ['Log_' DateString_sec ...
- '_Run' num2str(jj,'%03.f') '_session.json']);
- %savejson('', json, ['Log_' DateString '_session.json']);
- end
- json_done=true;
- end
- end
-
- if ~TestRunstimWithoutDAS
- % save log mat-file ============
- temp_hTracker=Par.hTracker;
- Par=rmfield(Par,'hTracker');
- save(FileName,'Log','Par','StimObj');
- Par.hTracker = temp_hTracker;
- end
-
-
- % write some stuff to a text file as well
- if ~TestRunstimWithoutDAS
- fid=fopen([FileName '.txt'],'w');
- fprintf(fid,['Runstim: ' Par.RUNFUNC '\n']);
- fprintf(fid,['StimSettings: ' Par.STIMSETFILE '\n']);
- fprintf(fid,['ParSettings: ' Par.PARSETFILE '\n\n']);
- fprintf(fid,['Stimulus: ' Stm(STIMNR).Descript '\n\n']);
-
- fprintf(fid,['Fixation perc over run (inc. pre/post): ' num2str(mean(Log.FixPerc)) '\n']);
- fprintf(fid,['Fixation perc over run (exc. pre/post): ' num2str(mean(Log.FixPerc(2:end-1))) '\n']);
- for i=1:length(Log.FixPerc)
- if i==1
- fprintf(fid,['Fixation perc PreStim: ' ...
- num2str(Log.FixPerc(i)) '\n']);
- elseif i==length(Log.FixPerc)
- fprintf(fid,['Fixation perc PostStim: ' ...
- num2str(Log.FixPerc(i)) '\n']);
- else
- fprintf(fid,['Fixation perc cycle ' num2str(i-1) ': ' ...
- num2str(Log.FixPerc(i)) '\n']);
- end
- end
- fprintf(fid,['\nTotal reward: ' num2str(Log.TotalReward) '\n']);
- fclose(fid);
- end
- cd(Par.ExpFolder)
-
- % now show the suggested filename for the eye file
- fprintf(['Suggested filename for eye-file: ' Par.MONKEY '_' DateString '.tda\n']);
-
- if TestRunstimWithoutDAS; cd Experiment;end
- warning on;
-
- % if running without DAS close ptb windows
- if TestRunstimWithoutDAS
- Screen('closeall');
- end
- end
-
- %% diagnostics to cmd -------------------------------------------------
- if ~Par.ESC && ~TestRunstimWithoutDAS
- GrandTotalReward=GrandTotalReward+Log.TotalReward;
- fprintf(['Total reward this run: ' num2str(Log.TotalReward) '\n']);
- fprintf(['Total reward thusfar: ' num2str(GrandTotalReward) '\n']);
- fprintf(['Total time-out this run: ' num2str(Log.TimeOutThisRun) '\n']);
- fprintf(['Total time-out thusfar: ' num2str(Log.TotalTimeOut) '\n']);
- fprintf(['Fixation percentage: ' num2str(nanmean(Log.FixPerc)) '\n']);
-
- CollectPerformance{StimLoopNr,1} = Stm(STIMNR).Descript;
- CollectPerformance{StimLoopNr,2} = nanmean(Log.FixPerc);
- CollectPerformance{StimLoopNr,3} = nanstd(Log.FixPerc)./sqrt(length(Log.FixPerc));
- CollectPerformance{StimLoopNr,4} = Log.TotalReward;
- CollectPerformance{StimLoopNr,5} = Log.TimeOutThisRun;
- elseif Par.ESC && ~LastRewardAdded && ~TestRunstimWithoutDAS
- GrandTotalReward=GrandTotalReward+Log.TotalReward;
- fprintf(['Total reward this run: ' num2str(Log.TotalReward) '\n']);
- fprintf(['Total reward thusfar: ' num2str(GrandTotalReward) '\n']);
- fprintf(['Total time-out this run: ' num2str(Log.TimeOutThisRun) '\n']);
- fprintf(['Total time-out thusfar: ' num2str(Log.TotalTimeOut) '\n']);
- fprintf(['Fixation percentage: ' num2str(nanmean(Log.FixPerc)) '\n']);
-
- CollectPerformance{StimLoopNr,1} = Stm(STIMNR).Descript;
- CollectPerformance{StimLoopNr,2} = nanmean(Log.FixPerc);
- CollectPerformance{StimLoopNr,3} = nanstd(Log.FixPerc);
- CollectPerformance{StimLoopNr,4} = Log.TotalReward;
- CollectPerformance{StimLoopNr,5} = Log.TimeOutThisRun;
- LastRewardAdded=true;
- end
- if Par.RespIndLeds; dasbit(Par.LED_B(1),0);dasbit(Par.LED_B(2),0);end % LEDS off
- end
- %% PostExpProcessing ======================================================
- Screen('FillRect',Par.window,[0 0 0].*Par.ScrWhite);
- Screen('Flip', Par.window);
- Screen('FillRect',Par.window,[0 0 0].*Par.ScrWhite);
- Screen('Flip', Par.window);
- fprintf('\n\n------------------------------\n');
- fprintf('Experiment ended as planned\n');
- fprintf('------------------------------\n');
- % close audio devices
- for i=1:length(Par.FeedbackSoundSnd)
- if ~isnan(Par.FeedbackSoundSnd(i).h)
- PsychPortAudio('Close', Par.FeedbackSoundSnd(i).h);
- end
- end
- if TestRunstimWithoutDAS
- sca; cd Experiment; rmpath(genpath(cd));
- end
- %% Close textures to clean memory =========================================
- if CloseTextures
- fprintf('Cleaning up textures...\n\n');
- for rv = 1:length(ret_vid)
- for jj=1:length(ret_vid(rv).text)
- Screen('Close',ret_vid(rv).text(jj));
- end
- end
- end
- %% Process performance ====================================================
- if ~isempty(CollectPerformance) && ~TestRunstimWithoutDAS
- ColPerf=[];
-
- cd(LogPath);
- fid2=fopen(['SUMMARY_' LogFn '.txt'],'w');
- fprintf(fid2,['Runstim: ' Par.RUNFUNC '\n']);
- fprintf(fid2,['StimSettings: ' Par.STIMSETFILE '\n']);
- fprintf(fid2,['ParSettings: ' Par.PARSETFILE '\n\n']);
-
- for rr = 1:size(CollectPerformance,1)
- fprintf([num2str(rr) ': Performance for ' CollectPerformance{rr,1} ' = ' num2str(CollectPerformance{rr,2}) ' %%\n']);
- fprintf(fid2,[num2str(rr) ': Performance for ' CollectPerformance{rr,1} ' = ' num2str(CollectPerformance{rr,2}) ' %%\n']);
- ColPerf=[ColPerf; CollectPerformance{rr,2}];
- end
- fprintf(['\nAverage performance: ' num2str(nanmean(ColPerf)) '%% (std: ' num2str(nanstd(ColPerf)) ' %%)\n']);
- fprintf(['Total reward: ' num2str(GrandTotalReward) ' s\n']);
- fprintf(fid2,['Average performance: ' num2str(nanmean(ColPerf)) '%% (std: ' num2str(nanstd(ColPerf)) ' %%)\n']);
- fprintf(fid2,['Total reward: ' num2str(GrandTotalReward) ' s']);
- fclose(fid2);
-
- % plot performance
- if Par.PlotPerformance
- if size(CollectPerformance,1) > 15
- xtick_use = 2:2:size(CollectPerformance,1);
- else
- xtick_use = 1:size(CollectPerformance,1);
- end
-
- figperf = figure('units','pixels','outerposition',[0 0 1000 1000]);
- subplot(4,4,1:3); hold on; box on;
- errorbar(1:size(CollectPerformance,1),...
- [CollectPerformance{:,2}],[CollectPerformance{:,3}],...
- 'ko','MarkerFaceColor','k','MarkerSize',6,'linestyle','none')
- set(gca,'ylim',[0 100],'xlim',[0 size(CollectPerformance,1)+1],...
- 'xtick', xtick_use,'FontSize',11)
- tt=title(['Performance: ' Par.MONKEY '_' Par.STIMSETFILE ...
- '_' DateString],'interpreter','none');
- %xx=xlabel('Stimulus (chronol. order)');
- yy=ylabel('Fixation (%)');
- set(tt,'FontSize', 12);
- %set(xx,'FontSize', 12);
- set(yy,'FontSize', 12);
-
- subplot(4,4,5:7); hold on; box on;
- plot(1:size(CollectPerformance,1),[CollectPerformance{:,4}],...
- 'ko','MarkerFaceColor','k','MarkerSize',6)
- set(gca,'xlim',[0 size(CollectPerformance,1)+1],...
- 'xtick', xtick_use,'FontSize',11)
- % tt=title(['Reward (s): ' Par.MONKEY '_' Par.STIMSETFILE ...
- % '_' DateString],'interpreter','none');
- %xx=xlabel('Stimulus (chronol. order)'); yy=ylabel('Reward (s)');
- %xx=xlabel('Stimulus (chronol. order)');
- yy=ylabel('Reward (s)');
- %set(tt,'FontSize', 12);
- %set(xx,'FontSize', 12);
- set(yy,'FontSize', 12);
-
- subplot(4,4,9:11); hold on; box on;
- for sn=1:size(CollectPerformance,1)
- CP{sn}=[num2str(sn) ': ' CollectPerformance{sn,1}];
- end
- plot(1:size(CollectPerformance,1),cumsum([CollectPerformance{:,4}]),...
- 'ro-','MarkerFaceColor','r','MarkerSize',6)
- set(gca,'xlim',[0 size(CollectPerformance,1)+1],...
- 'xtick', xtick_use,'FontSize',11)
- % tt=title(['Reward (s): ' Par.MONKEY '_' Par.STIMSETFILE ...
- % '_' DateString],'interpreter','none');
- %xx=xlabel('Stimulus (chronol. order)');
- yy=ylabel('Cumul. reward (s)');
- %set(tt,'FontSize', 12);
- %set(xx,'FontSize', 12);
- set(yy,'FontSize', 12);
-
- subplot(4,4,13:15); hold on; box on;
- plot(1:size(CollectPerformance,1),[CollectPerformance{:,5}],...
- 'ko','MarkerFaceColor','k','MarkerSize',6)
- set(gca,'xlim',[0 size(CollectPerformance,1)+1],...
- 'xtick', xtick_use,'FontSize',11)
- % tt=title(['Time-outs (s): ' Par.MONKEY '_' Par.STIMSETFILE ...
- % '_' DateString],'interpreter','none');
- xx=xlabel('Stimulus (chronol. order)');
- yy=ylabel('Time-outs (s)');
- %set(tt,'FontSize', 12);
- set(xx,'FontSize', 12);
- set(yy,'FontSize', 12);
-
- subplot(4,4,[4,8,12,16])
- set(gca,'XColor','w','YColor','w','xtick',[],'ytick',[]);
- tb=annotation('textbox',[.75 .1 .15 .8]);
- set(tb,'BackGroundColor','w','EdgeColor','none','String',...
- CP,'FontSize',10,'interpreter','none')
- set(figperf,'Color','w');
-
- % saveas(figperf,['PERFORM_' Par.MONKEY '_' Par.STIMSETFILE '_' DateString],'fig');
- % export_fig(['PERFORM_' Par.MONKEY '_' Par.STIMSETFILE '_' DateString],...
- % '-pdf','-nocrop',figperf);
- saveas(figperf,['PERFORM_' LogFn],'fig');
- export_fig(['PERFORM_' LogFn],'-pdf','-nocrop',figperf);
- close(figperf);
- end
- save(['PERFORM_' LogFn],'CollectPerformance');
- cd(Par.ExpFolder)
- end
- clear Log
- Par=Par_BU;
- %% Standard functions called throughout the runstim =======================
- % create fixation window around target
- function DefineEyeWin(STIMNR)
- FIX = 0; %this is the fixation window
- TALT = 1; %this is an alternative/erroneous target window --> not used
- TARG = 2; %this is the correct target window --> not used
- Par.WIN = [...
- Stm(STIMNR).Center(Par.PosNr,1), ...
- -Stm(STIMNR).Center(Par.PosNr,2), ...
- Stm(STIMNR).FixWinSizePix(1), ...
- Stm(STIMNR).FixWinSizePix(2), FIX]';
- refreshtracker( 1) %clear tracker screen and set fixation and target windows
- SetWindowDas %set das control thresholds using global parameters : Par
- end
- % draw fixation
- function DrawFix(STIMNR)
- % fixation area
- rect=[...
- Stm(STIMNR).Center(Par.PosNr,1)+Par.ScrCenter(1)-Stm(STIMNR).FixDotSizePix/2, ...
- Stm(STIMNR).Center(Par.PosNr,2)+Par.ScrCenter(2)-Stm(STIMNR).FixDotSizePix/2, ...
- Stm(STIMNR).Center(Par.PosNr,1)+Par.ScrCenter(1)+Stm(STIMNR).FixDotSizePix/2, ...
- Stm(STIMNR).Center(Par.PosNr,2)+Par.ScrCenter(2)+Stm(STIMNR).FixDotSizePix/2];
- rect2=[...
- Stm(STIMNR).Center(Par.PosNr,1)+Par.ScrCenter(1)-Stm(STIMNR).FixDotSurrSizePix/2, ...
- Stm(STIMNR).Center(Par.PosNr,2)+Par.ScrCenter(2)-Stm(STIMNR).FixDotSurrSizePix/2, ...
- Stm(STIMNR).Center(Par.PosNr,1)+Par.ScrCenter(1)+Stm(STIMNR).FixDotSurrSizePix/2, ...
- Stm(STIMNR).Center(Par.PosNr,2)+Par.ScrCenter(2)+Stm(STIMNR).FixDotSurrSizePix/2];
-
- Screen('FillOval',Par.window,Par.BG.*Par.ScrWhite,rect2);
- Screen('FillOval',Par.window,Par.CurrFixCol,rect);
-
- cen = [Stm(STIMNR).Center(Par.PosNr,1)+Par.ScrCenter(1), ...
- Stm(STIMNR).Center(Par.PosNr,2)+Par.ScrCenter(2)];
- end
- % draw handindicator
- function DrawHandIndicator(STIMNR)
- if any(any(Par.RespIndPos)) % stimuli not centered
- cen = [Par.ScrCenter(1),Par.ScrCenter(2)];
- if size(Par.RespIndPos,1)>2
- % pick a target location from the options
- p=Par.s_order(1);
- cen1 = [Par.RespIndPos(p,1)*Par.PixPerDeg+Par.ScrCenter(1), ...
- Par.RespIndPos(p,2)*Par.PixPerDeg+Par.ScrCenter(2)];
- cen2=cen1;
- else
- cen1 = [Par.RespIndPos(1,1)*Par.PixPerDeg+Par.ScrCenter(1), ...
- Par.RespIndPos(1,2)*Par.PixPerDeg+Par.ScrCenter(2)];
- cen2 = [Par.RespIndPos(2,1)*Par.PixPerDeg+Par.ScrCenter(1), ...
- Par.RespIndPos(2,2)*Par.PixPerDeg+Par.ScrCenter(2)];
- end
- else % stimulus centered (but can be cycled)
- cen = [Stm(STIMNR).Center(Par.PosNr,1)+Par.ScrCenter(1), ...
- Stm(STIMNR).Center(Par.PosNr,2)+Par.ScrCenter(2)];
- cen1=cen;cen2=cen;
- end
-
- if strcmp(Par.ResponseBox.Task, 'DetectGoSignal')
- if Par.ResponseState == Par.RESP_STATE_DONE && ...
- ~Par.CanStartTrial(Par) && ...
- GetSecs >= Par.ResponseStateChangeTime + 500/1000
- if Par.DrawBlockedInd && (Par.TrialNeeds.LeversAreDown && any(Par.LeverIsUp))
- Screen('FillOval',Par.window, Par.BlockedIndColor.*Par.ScrWhite, ...
- [cen,cen] + Par.RespIndSizePix*blocked_circle)
- end
- elseif Par.ResponseState == Par.RESP_STATE_WAIT && Par.ResponseSide == 1
- if Par.DrawNeutralWaitInd
- if GetSecs >= Par.ResponseStateChangeTime + Par.WaitIndicatorOnset
- Screen('FillOval',Par.window, Par.BlockedIndColor.*Par.ScrWhite, ...
- [cen1,cen1] + Par.RespIndSizePix*blocked_circle)
- end
- else
- if GetSecs >= Par.ResponseStateChangeTime + Par.WaitIndicatorOnset
- Screen('FillPoly',Par.window, Par.RespIndColor(1,:).*Par.ScrWhite, ...
- [cen1;cen1;cen1;cen1] + Par.RespIndSizePix*left_square)
- end
- end
- if Par.RespIndLeds; dasbit(Par.LED_B(Par.ResponseSide),1); end % LED on
- elseif Par.ResponseState == Par.RESP_STATE_WAIT && Par.ResponseSide == 2
- if Par.DrawNeutralWaitInd
- if GetSecs >= Par.ResponseStateChangeTime + Par.WaitIndicatorOnset
- Screen('FillOval',Par.window, Par.BlockedIndColor.*Par.ScrWhite, ...
- [cen2,cen2] + Par.RespIndSizePix*blocked_circle)
- end
- else
- if GetSecs >= Par.ResponseStateChangeTime + Par.WaitIndicatorOnset
- Screen('FillPoly',Par.window, Par.RespIndColor(2,:).*Par.ScrWhite, ...
- [cen2;cen2;cen2;cen2] + Par.RespIndSizePix*right_diamond)
- end
- end
- if Par.RespIndLeds; dasbit(Par.LED_B(Par.ResponseSide),1); end % LED on
- elseif Par.ResponseState == Par.RESP_STATE_GO && ...
- Par.ResponseSide == 1
- Screen('FillPoly',Par.window, Par.RespIndColor(1,:).*Par.ScrWhite, ...
- [cen1;cen1;cen1;cen1] + Par.RespIndSizePix*left_square)
- if Par.RespIndLeds; dasbit(Par.LED_B(Par.ResponseSide),1); end % LED on
- elseif Par.ResponseState == Par.RESP_STATE_GO && ...
- Par.ResponseSide == 2
- Screen('FillPoly',Par.window, Par.RespIndColor(2,:).*Par.ScrWhite, ...
- [cen2;cen2;cen2;cen2] + Par.RespIndSizePix*right_diamond)
- if Par.RespIndLeds; dasbit(Par.LED_B(Par.ResponseSide),1); end % LED on
- elseif Par.ResponseState == Par.RESP_STATE_DONE && ...
- Par.CurrResponseSide == 1
- if Par.RespIndLeds; dasbit(Par.LED_B(1),0);dasbit(Par.LED_B(2),0);end % LEDS off
- % Screen('FillPoly',Par.window, Par.RespIndColor(1,:).*Par.ScrWhite, ...
- % [cen1;cen1;cen1;cen1] + Par.RespIndSizePix*left_square)
- elseif Par.ResponseState == Par.RESP_STATE_DONE && ...
- Par.CurrResponseSide == 2
- if Par.RespIndLeds; dasbit(Par.LED_B(1),0);dasbit(Par.LED_B(2),0);end % LEDS off
- % Screen('FillPoly',Par.window, Par.RespIndColor(2,:).*Par.ScrWhite, ...
- % [cen2;cen2;cen2;cen2] + Par.RespIndSizePix*right_diamond)
- end
- end
- end
- % draw "go bar"
- function DrawGoBar(STIMNR)
- if Par.ResponseSide==0
- return
- end
- % Target bar
- %if ~Par.Orientation(Par.CurrOrient)
- if Par.ResponseState == Par.RESP_STATE_GO %horizontal
- rect=[...
- Stm(STIMNR).Center(Par.PosNr,1)+Par.ScrCenter(1)-Par.GoBarSizePix(1)/2, ...
- Stm(STIMNR).Center(Par.PosNr,2)+Par.ScrCenter(2)-Par.GoBarSizePix(2)/2, ...
- Stm(STIMNR).Center(Par.PosNr,1)+Par.ScrCenter(1)+Par.GoBarSizePix(1)/2, ...
- Stm(STIMNR).Center(Par.PosNr,2)+Par.ScrCenter(2)+Par.GoBarSizePix(2)/2];
- Screen('FillRect',Par.window,Par.GoBarColor.*Par.ScrWhite,rect);
-
- elseif Par.ResponseState == Par.RESP_STATE_WAIT %vertical
- rect=[...
- Stm(STIMNR).Center(Par.PosNr,1)+Par.ScrCenter(1)-Par.GoBarSizePix(2)/2, ... left
- Stm(STIMNR).Center(Par.PosNr,2)+Par.ScrCenter(2)-Par.GoBarSizePix(1)/2, ... top
- Stm(STIMNR).Center(Par.PosNr,1)+Par.ScrCenter(1)+Par.GoBarSizePix(2)/2, ... right
- Stm(STIMNR).Center(Par.PosNr,2)+Par.ScrCenter(2)+Par.GoBarSizePix(1)/2];
- Screen('FillRect',Par.window,Par.GoBarColor.*Par.ScrWhite,rect);
- end
- end
- % draw stimuli
- function DrawStimuli
- % Background
- Screen('FillRect',Par.window,ceil(Par.BG.*Par.ScrWhite));
- end
- % auto-dim the screen if hand is out
- function AutoDim
- if Par.HandOutDimsScreen && (...
- (strcmp(Par.HandInBothOrEither,'Both') && ~all(Par.HandIsIn)) || ...
- (strcmp(Par.HandInBothOrEither,'Either') && ~any(Par.HandIsIn)) ...
- )
- if ~any(Par.HandIsIn) % no hands in
- if size(Par.HandOutDimsScreen_perc,2) == 2
- Screen('FillRect',Par.window,...
- [0 0 0 (Par.HandOutDimsScreen_perc(2))].*Par.ScrWhite,....
- [Par.wrect(1:2) Par.wrect(3:4)+1]);
- else
- Screen('FillRect',Par.window,...
- [0 0 0 (Par.HandOutDimsScreen_perc(1))].*Par.ScrWhite,....
- [Par.wrect(1:2) Par.wrect(3:4)+1]);
- end
- else % a hand in
- Screen('FillRect',Par.window,...
- [0 0 0 (Par.HandOutDimsScreen_perc(1))].*Par.ScrWhite,....
- [Par.wrect(1:2) Par.wrect(3:4)+1]);
- end
- end
- end
- % change stimulus features
- function ChangeStimulus(STIMNR)
- % Change stimulus features if required
- % Position
- if Par.SwitchPos
- Par.PosReset=true;
- Par.PrevPosNr=Par.PosNr;
- switch Par.WhichPos
- case '1'
- Par.PosNr = 1;
- case '2'
- Par.PosNr = 2;
- case '3'
- Par.PosNr = 3;
- case '4'
- Par.PosNr = 4;
- case '5'
- Par.PosNr = 5;
- case 'Next'
- Par.PosNr = Par.PosNr + 1;
- if Par.PosNr > 5
- Par.PosNr = Par.PosNr - 5;
- end
- % case 'Prev'
- % Par.PosNr = Par.PosNr -1;
- % if Par.PosNr < 1
- % Par.PosNr = Par.PosNr + 5;
- % end
- end
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event=['Pos' num2str(Par.PosNr)];
- Log.Events(Log.nEvents).t=Par.KeyTime-Par.ExpStart;
- DefineEyeWin(STIMNR);
- end
- end
- % check for key-presses
- function CheckKeys
- % check
- [Par.KeyIsDown,Par.KeyTime,KeyCode]=KbCheck; %#ok<*ASGLU>
- InterpretKeys(KeyCode)
- end
- % interpret key presses
- function InterpretKeys(KeyCode)
- % Par.KeyDetectedInTrackerWindow is true when key press is detected
- % in the Tracker window, false if it's not. Allows key-press isolation
-
- % interpret key presses
- if Par.KeyIsDown && ~Par.KeyWasDown
- Key=KbName(KbName(KeyCode));
- if isscalar(KbName(KbName(KeyCode)))
- switch Key
- case Par.KeyEscape
- if Par.KeyDetectedInTrackerWindow % only in Tracker
- Par.ESC = true;
- elseif TestRunstimWithoutDAS
- Par.ESC = true;
- end
- case Par.KeyTriggerMR
- Log.MRI.TriggerReceived = true;
- Log.MRI.TriggerTime = ...
- [Log.MRI.TriggerTime; Par.KeyTime];
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event='MRI_Trigger';
- Log.Events(Log.nEvents).t=Par.KeyTime-Par.ExpStart;
- Log.Events(Log.nEvents).info = 'Received';
- if strcmp(Par.SetUp,'NIN') % send start bit to sync ephys system
- %dasword(00000);
- send_serial_data(0);
- WordsSent=WordsSent+1; %keep track of how many words are sent so we back-check TDT against the log
- Log.Words(WordsSent)=00000; %collect all the words that are sent to TDT
- end
- case Par.KeyJuice
- if Par.KeyDetectedInTrackerWindow % only in Tracker
- Par.ManualReward = true;
- Log.ManualRewardTime = ...
- [Log.ManualRewardTime; Par.KeyTime];
- end
- case Par.KeyStim
- if Par.KeyDetectedInTrackerWindow % only in Tracker
- if ~Par.ToggleHideStim
- Par.ToggleHideStim = true;
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event='StimOff';
- Log.Events(Log.nEvents).t=Par.KeyTime-Par.ExpStart;
- Log.Events(Log.nEvents).info = 'Off';
- else
- Par.ToggleHideStim = false;
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event='StimOn';
- Log.Events(Log.nEvents).t=Par.KeyTime-Par.ExpStart;
- Log.Events(Log.nEvents).info = 'On';
- end
- end
- case Par.KeyFix
- if Par.KeyDetectedInTrackerWindow % only in Tracker
- if ~Par.ToggleHideFix
- Par.ToggleHideFix = true;
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event='FixOff';
- Log.Events(Log.nEvents).t=Par.KeyTime-Par.ExpStart;
- Log.Events(Log.nEvents).info = 'Off';
- else
- Par.ToggleHideFix = false;
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event='FixOn';
- Log.Events(Log.nEvents).t=Par.KeyTime-Par.ExpStart;
- Log.Events(Log.nEvents).info = 'On';
- end
- end
- case Par.KeyPause
- if Par.KeyDetectedInTrackerWindow && Par.Allow_Calls_To_PTB_win % only in Tracker
- if ~Par.Pause
- Par.Pause=true;
- fprintf('Time-out ON\n');
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event='PauseOn';
- Log.Events(Log.nEvents).t=Par.KeyTime-Par.ExpStart;
- Log.Events(Log.nEvents).info = 'On';
- Par.PauseStartTime=Par.KeyTime;
- else
- Par.Pause=false;
- Par.PauseStopTime=Par.KeyTime-Par.PauseStartTime;
- fprintf(['Time-out OFF (' num2str(Par.PauseStopTime) ' s)\n']);
- Log.TotalTimeOut = Log.TotalTimeOut+Par.PauseStopTime;
- Log.TimeOutThisRun=Log.TimeOutThisRun+Par.PauseStopTime;
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event='PauseOff';
- Log.Events(Log.nEvents).t=Par.KeyTime-Par.ExpStart;
- Log.Events(Log.nEvents).info = 'Off';
- end
- elseif ~Par.Allow_Calls_To_PTB_win
- fprintf('You cannot give a time-out during a vlc-movie...\n');
- end
- case Par.KeyRewTimeSet
- if Par.KeyDetectedInTrackerWindow % only in Tracker
- Par.RewardTime=Par.RewardTimeSet;
- Par.Times.Targ = Par.RewardFixHoldTime;
- fprintf('Reward schedule set as defined in ParSettings\n');
- end
- case Par.KeyShowRewTime
- if Par.KeyDetectedInTrackerWindow % only in Tracker
- fprintf('Reward amount (s):\n');
- Par.RewardTime
- fprintf('Fix time to get reward:\n' );
- Par.Times.Targ
- end
- case Par.KeyCyclePos
- if Par.KeyDetectedInTrackerWindow % only in Tracker
- if ~Par.PositionLocked
- if Par.ToggleCyclePos
- Par.ToggleCyclePos = false;
- fprintf('Toggle automatic position cycling: OFF\n');
- else
- Par.ToggleCyclePos = true;
- fprintf('Toggle automatic position cycling: ON\n');
- end
- end
- end
- case Par.KeyLockPos
- if Par.KeyDetectedInTrackerWindow % only in Tracker
- if ~Par.PositionLocked
- Par.PositionLocked=true;
- fprintf('Fix position LOCKED\n');
- else
- Par.PositionLocked=false;
- fprintf('Fix position UNLOCKED\n');
- end
- end
- case Par.Key1
- if Par.KeyDetectedInTrackerWindow % only in Tracker
- if ~Par.PositionLocked
- Par.SwitchPos = true;
- Par.WhichPos = '1';
- end
- end
- case Par.Key2
- if Par.KeyDetectedInTrackerWindow % only in Tracker
- if ~Par.PositionLocked
- Par.SwitchPos = true;
- Par.WhichPos = '2';
- end
- end
- case Par.Key3
- if Par.KeyDetectedInTrackerWindow % only in Tracker
- if ~Par.PositionLocked
- Par.SwitchPos = true;
- Par.WhichPos = '3';
- end
- end
- case Par.Key4
- if Par.KeyDetectedInTrackerWindow % only in Tracker
- if ~Par.PositionLocked
- Par.SwitchPos = true;
- Par.WhichPos = '4';
- end
- end
- case Par.Key5
- if Par.KeyDetectedInTrackerWindow % only in Tracker
- if ~Par.PositionLocked
- Par.SwitchPos = true;
- Par.WhichPos = '5';
- end
- end
- case Par.KeyNext
- if Par.KeyDetectedInTrackerWindow % only in Tracker
- if ~Par.PositionLocked
- Par.SwitchPos = true;
- Par.WhichPos = 'Next';
- % case Par.KeyPrevious
- % Par.SwitchPos = true;
- % Par.WhichPos = 'Prev';
- end
- end
- case Par.KeyLeftResp
- if Par.KeyDetectedInTrackerWindow % only in Tracker
- fprintf('LEFT response indicators only\n');
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event='LeftRespOnly';
- Log.Events(Log.nEvents).t=Par.KeyTime-Par.ExpStart;
- Log.Events(Log.nEvents).info = 'None';
- Par.RespProbSetting=1;
- Par.ForceRespSide = true;
- end
- case Par.KeyRightResp
- if Par.KeyDetectedInTrackerWindow % only in Tracker
- fprintf('RIGHT response indicators only\n');
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event='RightRespOnly';
- Log.Events(Log.nEvents).t=Par.KeyTime-Par.ExpStart;
- Log.Events(Log.nEvents).info = 'None';
- Par.RespProbSetting=2;
- Par.ForceRespSide = true;
- end
- case Par.KeyRandResp
- if Par.KeyDetectedInTrackerWindow % only in Tracker
- fprintf('PROBABLISTIC response indicators\n');
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event='RandRespInd';
- Log.Events(Log.nEvents).t=Par.KeyTime-Par.ExpStart;
- Log.Events(Log.nEvents).info = 'None';
- Par.RespProbSetting=0;
- Par.ForceRespSide = true;
- end
- case Par.KeyBeam
- if Par.KeyDetectedInTrackerWindow % only in Tracker
- Par.KeyBeamInd = Par.KeyBeamInd+1;
- if Par.KeyBeamInd > size(Par.KeyBeamStates,1)-1
- Par.KeyBeamInd = Par.KeyBeamInd - ...
- (size(Par.KeyBeamStates,1)-1);
- end
- switch Par.KeyBeamInd
- case 1
- fprintf(['BEAMSTATE: ' Par.KeyBeamStates{Par.KeyBeamInd+1,1} ...
- ' - ' Par.KeyBeamStates{Par.KeyBeamInd+1,2} ...
- ' - TRIAL & FIX need hand in\n']);
- case 2
- fprintf(['BEAMSTATE: ' Par.KeyBeamStates{Par.KeyBeamInd+1,1} ...
- ' - ' Par.KeyBeamStates{Par.KeyBeamInd+1,2} ...
- ' - ONLY TRIAL needs hand in\n']);
- case 3
- fprintf(['BEAMSTATE: ' Par.KeyBeamStates{Par.KeyBeamInd+1,1} ...
- ' - ' Par.KeyBeamStates{Par.KeyBeamInd+1,2} ...
- ' - ONLY FIX needs hand in\n']);
- case 4
- fprintf(['BEAMSTATE: ' Par.KeyBeamStates{Par.KeyBeamInd+1,1} ...
- ' - ' Par.KeyBeamStates{Par.KeyBeamInd+1,2} ...
- ' - TRIAL & FIX need hand in\n']);
- case 5
- fprintf(['BEAMSTATE: ' Par.KeyBeamStates{Par.KeyBeamInd+1,1} ...
- ' - ' Par.KeyBeamStates{Par.KeyBeamInd+1,2} ...
- ' - TRIAL & FIX need hand in\n']);
- case 6
- fprintf(['BEAMSTATE: ' Par.KeyBeamStates{Par.KeyBeamInd+1,1} ...
- ' - ' Par.KeyBeamStates{Par.KeyBeamInd+1,2} ...
- ' - ONLY TRIAL needs hand in\n']);
- case 7
- fprintf(['BEAMSTATE: ' Par.KeyBeamStates{Par.KeyBeamInd+1,1} ...
- ' - ' Par.KeyBeamStates{Par.KeyBeamInd+1,2} ...
- ' - ONLY FIX needs hand in\n']);
- end
- Par.HandInBothOrEither = Par.KeyBeamStates{Par.KeyBeamInd+1,2};
- Par.TrialNeeds.HandIsIn = Par.KeyBeamStates{Par.KeyBeamInd+1,3};
- Par.FixNeeds.HandIsIn = Par.KeyBeamStates{Par.KeyBeamInd+1,4};
-
- % set-up function to check whether to draw fixation
- if Par.FixNeeds.HandIsIn && strcmp(Par.HandInBothOrEither,'Both')
- Par.HideFix_BasedOnHandIn = @(Par) ~all(Par.HandIsIn);
- elseif Par.FixNeeds.HandIsIn && strcmp(Par.HandInBothOrEither,'Either')
- Par.HideFix_BasedOnHandIn = @(Par) ~any(Par.HandIsIn);
- else
- Par.HideFix_BasedOnHandIn = @(Par) false;
- end
-
- % functions for lever task
- if Par.TrialNeeds.HandIsIn && Par.TrialNeeds.LeversAreDown % hands in / levers down
- Par.CanStartTrial = @(Par) (all(Par.HandIsIn) && ~any(Par.LeverIsUp));
- elseif Par.TrialNeeds.HandIsIn % only hands in
- Par.CanStartTrial = @(Par) all(Par.HandIsIn);
- elseif Par.TrialNeeds.LeversAreDown % only levers down
- Par.CanStartTrial = @(Par) ~any(Par.LeverIsUp);
- else % independent of hand and lever position
- Par.CanStartTrial = @(Par) true;
- end
-
- end
- end
- Par.KeyWasDown=true;
- end
- elseif Par.KeyIsDown && Par.KeyWasDown
- Par.SwitchPos = false;
- elseif ~Par.KeyIsDown && Par.KeyWasDown
- % key is released
- Par.KeyWasDown = false;
- Par.SwitchPos = false;
- end
- % reset to false
- Par.KeyDetectedInTrackerWindow=false;
- end
- % check DAS for manual responses
- function CheckManual
- %check the incoming signal on DAS channel #3
- % NB dasgetlevel only starts counting at the third channel (#2)
- daspause(5);
- ChanLevels=dasgetlevel;
- Log.RespSignal = ChanLevels(Par.ConnectBox.PhotoAmp(:)-2);
- % dasgetlevel starts reporting at channel 3, so
- % subtract 2 from the channel you want (1 based)
- % Log.RespSignal is a vector with as many channels as are in use
- InterpretManual;
- end
- % interpret manual response signal
- function InterpretManual
- % levels are different for differnet das cards
- if strcmp(computer,'PCWIN64')
- Threshold=40000;
- elseif strcmp(computer,'PCWIN')
- Threshold=2750;
- end
-
- Par.BeamWasBlocked = Par.BeamIsBlocked;
- % vector that tells us for all used channels whether blocked
- Par.BeamIsBlocked = Log.RespSignal < Threshold;
-
- % Log any changes
- if any(Par.BeamWasBlocked(:) ~= Par.BeamIsBlocked(:))
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event=...
- strcat('BeamStateChange ', mat2str(Par.BeamIsBlocked));
- Log.Events(Log.nEvents).t=lft-Par.ExpStart;
- Par.HandIsIn =Par.BeamIsBlocked(Par.ConnectBox.PhotoAmp_HandIn);
- Par.LeverIsUp=Par.BeamIsBlocked(Par.ConnectBox.PhotoAmp_Levers);
- if any(Par.LeverIsUp ~= Par.LeverWasUp) && all(Par.LeverIsUp)
- % now both levers are up
- Par.BothLeversUp_time = GetSecs;
- Par.LeverWasUp = Par.LeverIsUp;
- elseif any(Par.LeverIsUp ~= Par.LeverWasUp) && ~all(Par.LeverIsUp)
- % something changed: both are not up
- Par.BothLeversUp_time = Inf;
- Par.LeverWasUp = Par.LeverIsUp;
- end
- end
-
- if ~strcmp(Par.ResponseBox.Task, 'DetectGoSignal')
- % interpret depending on response box type
- switch Par.ResponseBox.Type
- % case 'Beam'
- case 'Lift'
- if ~any(Par.HandWasIn) && any(Par.HandIsIn) % from none to any
- %fprintf('going from none to one\n')
- Par.HandInPrev_Moment = Par.HandInNew_Moment; % the previous hand-in moment
- Par.HandInNew_Moment = GetSecs; % current hand-in moment
- Par.HandWasIn = Par.HandIsIn;
- elseif any(Par.HandWasIn) && ~any(Par.HandIsIn)
- %fprintf('all out now\n')
- Par.HandInPrev_Moment = Par.HandInNew_Moment;
- Par.HandWasIn = Par.HandIsIn;
- elseif any(Par.HandWasIn) && any(Par.HandIsIn) && Par.RewardRunning
- Par.HandInPrev_Moment = Par.HandInNew_Moment;
- end
-
- if strcmp(Par.HandInBothOrEither, 'Both') && ...
- all(Par.HandIsIn) % both in
- if ~any(Par.HandWasIn)
- % only do this if 1 channel is used
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event='BothHandsIn';
- Log.Events(Log.nEvents).t=lft-Par.ExpStart;
- Par.HandWasIn=Par.HandIsIn;
- end
- elseif strcmp(Par.HandInBothOrEither, 'Either') && ...
- any(Par.HandIsIn) % both in % at least one blocked
- if ~all(Par.HandWasIn)
- % only do this if 1 channel is used
- Log.nEvents=Log.nEvents+1;
- if Par.HandIsIn(1)
- Log.Events(Log.nEvents).event='LeftHandIn';
- else
- Log.Events(Log.nEvents).event='RightHandIn';
- end
- Log.Events(Log.nEvents).t=lft-Par.ExpStart;
- Par.HandWasIn=Par.HandIsIn;
- end
- elseif ~all(Par.HandIsIn)
- if any(Par.HandWasIn)
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event='HandsOut';
- Log.Events(Log.nEvents).t=lft-Par.ExpStart;
- Par.HandWasIn=Par.HandIsIn;
- end
- end
- end
- end
- end
- % give automated reward for fixation
- function GiveRewardAutoFix
- % Get correct reward duration
- switch Par.RewardType
- case 0
- Par.RewardTimeCurrent = Par.RewardTime;
- case 1
- if size(Par.RewardTime,2)>1 % progressive schedule still active
- % Get number of consecutive correct trials
- rownr= find(Par.RewardTime(:,1)<Par.CorrStreakcount(2),1,'last');
- Par.RewardTimeCurrent = Par.RewardTime(rownr,2);
- else %schedule overruled by slider settings
- Par.RewardTimeCurrent = Par.RewardTime;
- end
- case 2
- Par.RewardTimeCurrent = 0;
- end
- if ~isempty(Par.RewardFixMultiplier)
- if ~all(Par.HandIsIn) && any(Par.HandIsIn) % one hand in
- hig = Par.FixReward_HandInGain(1);
- elseif all(Par.HandIsIn) % both hands in
- hig = Par.FixReward_HandInGain(2);
- else % no hands in
- hig = 1;
- end
- Par.RewardTimeCurrent = hig * Par.RewardFixMultiplier * Par.RewardTimeCurrent;
- if Par.RewardFixMultiplier <= 0 % no reward given if true
- return
- end
- end
-
- if size(Par.Times.Targ,2)>1
- rownr= find(Par.Times.Targ(:,1)<Par.CorrStreakcount(2),1,'last');
- Par.Times.TargCurrent=Par.Times.Targ(rownr,2);
- else
- Par.Times.TargCurrent=Par.Times.Targ;
- end
-
- % only give reward when Reward time >0
- if Par.RewardTimeCurrent>0
- % Give the reward
- Par.RewardStartTime=GetSecs;
- if strcmp(computer,'PCWIN64')
- dasjuice(10); % 64bit das card
- else
- dasjuice(5) %old card dasjuice(5)
- end
- Par.RewardRunning=true;
-
- % Play back a sound
- if Par.RewardSound
- RewT=0:1/Par.RewSndPar(1):Par.RewardTimeCurrent;
- RewY=Par.RewSndPar(3)*sin(2*pi*Par.RewSndPar(2)*RewT);
- sound(RewY,Par.RewSndPar(1));
- end
-
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event='RewardFix';
- Log.Events(Log.nEvents).t=GetSecs-Par.ExpStart;
- Log.Events(Log.nEvents).info = 'None';
- end
- end
- % stop reward delivery
- function StopRewardIfNeeded
- if Par.RewardRunning && GetSecs >= ...
- Par.RewardStartTime+Par.RewardTimeCurrent
- dasjuice(0);
- Par.RewardRunning=false;
- Log.TotalReward = Log.TotalReward+Par.RewardTimeCurrent;
- %Par.ResponseSide = 0;
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event='RewardStopped';
- Log.Events(Log.nEvents).t=GetSecs-Par.ExpStart;
- Log.Events(Log.nEvents).info = 'None';
- end
- end
- % give automated reward for task
- function GiveRewardAutoTask
- if Par.Rew_BasedOnHandIn(Par) && ~Par.Pause
- if ~isempty(Par.RewardTaskMultiplier)
- Par.RewardTimeCurrent = Par.RewardTaskMultiplier * Par.RewardTime;
- else
- Par.RewardTimeCurrent = Par.RewardTime;
- end
- % gain for which lever is used
- if isfield(Par,'RespLeverGain')
- if any(Par.LeverIsUp) && ~all(Par.LeverIsUp) % only one up
- Par.RewardTimeCurrent = Par.RespLeverGain(...
- logical(Par.LeverIsUp))*Par.RewardTimeCurrent;
- end
- end
- % gain for having hands in (when defined)
- if isfield(Par,'TaskReward_HandInGain')
- if any(Par.HandIsIn) && ~all(Par.HandIsIn) % only hand in
- Par.RewardTimeCurrent = Par.TaskReward_HandInGain(1)*Par.RewardTimeCurrent;
- elseif all(Par.HandIsIn) % both hands in
- Par.RewardTimeCurrent = Par.TaskReward_HandInGain(2)*Par.RewardTimeCurrent;
- end
- end
- % Give the reward
- if Par.RewardTimeCurrent>0
- Par.RewardStartTime=GetSecs;
- if strcmp(computer,'PCWIN64')
- dasjuice(5.1); % 64bit das card
- else
- dasjuice(5) %old card dasjuice(5)
- end
- Par.RewardRunning=true;
-
- % Play back a sound
- if Par.RewardSound
- RewT=0:1/Par.RewSndPar(1):Par.RewardTimeCurrent;
- RewY=Par.RewSndPar(3)*sin(2*pi*Par.RewSndPar(2)*RewT);
- sound(RewY,Par.RewSndPar(1));
- end
-
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event='RewardAutoTask';
- Log.Events(Log.nEvents).t=GetSecs-Par.ExpStart;
- Log.Events(Log.nEvents).info = 'None';
- end
- end
- end
- % give automated reward for hand in
- function GiveRewardAutoHandIn
- Par.RewardTimeCurrent = Par.RewardForHandsIn_Quant(sum(Par.HandIsIn));
- if ~all(Par.HandIsIn) && any(Par.HandIsIn) % only one hand in
- Par.RewardTimeCurrent = ...
- Par.RewardForHandsIn_MultiplierPerHand(Par.HandIsIn)*Par.RewardTimeCurrent;
- end
- % Give the reward
- if Par.RewardTimeCurrent>0
- Par.RewardStartTime=GetSecs;
- Par.RewHandStart=Par.RewardStartTime;
- if strcmp(computer,'PCWIN64')
- dasjuice(10); % 64bit das card
- else
- dasjuice(5) %old card dasjuice(5)
- end
- Par.RewardRunning=true;
-
- % Play back a sound
- if Par.RewardSound
- RewT=0:1/Par.RewSndPar(1):Par.RewardTimeCurrent;
- RewY=Par.RewSndPar(3)*sin(2*pi*Par.RewSndPar(2)*RewT);
- sound(RewY,Par.RewSndPar(1));
- end
-
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event='RewardAutoHand';
- Log.Events(Log.nEvents).t=GetSecs-Par.ExpStart;
- Log.Events(Log.nEvents).info = 'None';
- end
- end
- % give manual reward
- function GiveRewardManual
- Par.RewardTimeCurrent = Par.RewardTimeManual;
- % Give the reward
- Par.RewardStartTime=GetSecs;
- Par.RewardRunning=true;
- if strcmp(computer,'PCWIN64')
- dasjuice(10); % 64bit das card
- else
- dasjuice(5) %old card dasjuice(5)
- end
-
- % Play back a sound
- if Par.RewardSound
- RewT=0:1/Par.RewSndPar(1):Par.RewardTimeCurrent;
- RewY=Par.RewSndPar(3)*sin(2*pi*Par.RewSndPar(2)*RewT);
- sound(RewY,Par.RewSndPar(1));
- end
-
- Log.nEvents=Log.nEvents+1;
- Log.Events(Log.nEvents).event='RewardMan';
- Log.Events(Log.nEvents).t=GetSecs-Par.ExpStart;
- Log.Events(Log.nEvents).info = 'None';
- end
- % check eye-tracker recording status
- function CheckEyeRecStatus
- daspause(5);
- ChanLevels=dasgetlevel;
- Par.CheckRecLevel=ChanLevels(Par.ConnectBox.EyeRecStat-2);
- %Par.CheckRecLevel
- % dasgetlevel starts reporting at channel 3, so subtract 2 from the channel you want (1 based)
- if strcmp(computer,'PCWIN64') && Par.CheckRecLevel < 48000 % 64bit das card
- Par.EyeRecStatus = 1;
- elseif strcmp(computer,'PCWIN') && Par.CheckRecLevel < 2750 % old das card
- Par.EyeRecStatus = 1;
- else
- Par.EyeRecStatus = 0;
- end
- end
- % set eye-tracker recording status
- function SetEyeRecStatus(status)
- if status % switch on
- Par.EyeRecTriggerLevel=0;
- elseif ~status % switch off
- Par.EyeRecTriggerLevel=1;
- end
- tEyeRecSet = GetSecs;
- %Par.EyeRecTriggerLevel
- dasbit(0,Par.EyeRecTriggerLevel);
- Log.nEvents=Log.nEvents+1;
- if Par.EyeRecTriggerLevel
- Log.Events(Log.nEvents).event='EyeRecOff';
- else
- Log.Events(Log.nEvents).event='EyeRecOn';
- end
- Log.Events(Log.nEvents).t=tEyeRecSet-Par.ExpStart;
- Log.Events(Log.nEvents).info = 'None';
- end
- % create radial checkerboard
- function chkimg = RadialCheckerBoard(radius, sector, chsz)
- %img = RadialCheckerBoard(radius, sector, chsz, propel)
- % Returns a bitmap image of a radial checkerboard pattern.
- % The image is a square of 2*OuterRadius pixels.
- %
- % Parameters of wedge:
- % radius : eccentricity of radii in pixels = [outer, inner]
- % sector : polar angles in degrees = [start, end] from -180 to 180
- % chsz : size of checks in log factors & degrees respectively = [eccentricity, angle]
- % propel : Optional, if defined there are two wedges, one in each hemifield
- %
- checkerboard = [0 Par.ScrWhite; Par.ScrWhite 0];
- img = ones(2*radius(1), 2*radius(1)) * ceil(Par.ScrWhite/2);
-
- for x = -radius : radius
- for y = -radius : radius
- [th, r] = cart2pol(x,y);
- th = th * 180/pi;
- if th >= sector(1) && th < sector(2) && r < radius(1) && r > radius(2)
- img(y+radius(1)+1,x+radius(1)+1) = checkerboard(mod(floor(log(r)*chsz(1)),2) + 1, mod(floor((th + sector(1))/chsz(2)),2) + 1);
- end
- end
- end
- img = flipud(img);
-
- if nargin > 3
- rotimg = rot90(img,2);
- non_grey_pixels = find(rotimg ~= ceil(Par.ScrWhite/2));
- img(non_grey_pixels) = rotimg(non_grey_pixels);
- end
- img = uint8(img);
-
- width = radius(1)*2;
- [X, Y] = meshgrid([-width/2:-1 1:width/2], [-width/2:-1 1:width/2]);
- [T, R] = cart2pol(X,Y);
- circap = ones(width, width);
- circap(R > width/2) = 1;
- alphas = linspace(1, 0, 0);
- circap(R > width/2) = 0;
- circap(R < radius(2)) = 0;
- chkimg = img;
- chkimg(:,:,2) = uint8(abs(double(img)-Par.ScrWhite));
- chkimg(:,:,3)=circap.*Par.ScrWhite;
- end
- % check eye only (dascheck without tracker gui update)
- function [Hit, Time] = DasCheckEyeOnly %#ok<*DEFNU>
- Hit = LPStat(1); %Hit yes or no
- Time = LPStat(0); %time
- POS = dasgetposition();
- P = POS.*Par.ZOOM; %average position over window initialized in DasIni
- % eye position to global to allow logging
- Par.CurrEyePos = [POS(1) POS(2)];
- end
- % log eye info
- function LogEyeInfo
- % if nothing changes in calibration
- % only log position at 5 Hz
- if size(Log.Eye,2)==0 || ...
- (sum(Par.ScaleOff-Log.Eye(end).ScaleOff) ~= 0 || ...
- (GetSecs-Par.ExpStart) - Log.Eye(end).t > 1/5)
-
- eye_i = size(Log.Eye,2)+1;
- Log.Eye(eye_i).t = GetSecs-Par.ExpStart;
- Log.Eye(eye_i).CurrEyePos = Par.CurrEyePos;
- Log.Eye(eye_i).CurrEyeZoom = Par.ZOOM;
- Log.Eye(eye_i).ScaleOff = Par.ScaleOff;
- end
- end
- % Update hand task state
- function UpdateHandTaskState(NewState)
- Par.ResponseState = NewState;
- Par.ResponseStateChangeTime = GetSecs;
- Log.nEvents=Log.nEvents+1;
- switch NewState
- case Par.RESP_STATE_WAIT
- Log.Events(Log.nEvents).event=...
- 'HandTaskState-Wait';
- Par.PickRandomIndicatorPosition = true;
- case Par.RESP_STATE_GO
- Log.Events(Log.nEvents).event=...
- 'HandTaskState-Go';
- case Par.RESP_STATE_DONE
- Log.Events(Log.nEvents).event=...
- 'HandTaskState-Done';
- otherwise
- Log.Events(Log.nEvents).event=...
- strcat('HandTaskState-Unknown-',NewState);
- end
- Log.Events(Log.nEvents).t=Par.ResponseStateChangeTime;
- end
- % Close the current PTB window
- function Close_PTB_win
- Screen('Close', Par.window);
- Par.Allow_Calls_To_PTB_win = false;
- end
- % Re-open the default PTB window
- function Reopen_PTB_win
- [Par.window, Par.wrect] = PsychImaging('OpenWindow',...
- Par.ScrNr,0,[],[],2,[],[],1);
- [sourceFactorOld,destinationFactorOld,colorMaskOld] = ...
- Screen('BlendFunction',Par.window,...
- GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
- MaxPriority(Par.window);
- Par.Allow_Calls_To_PTB_win = true;
- end
- end
|