annotate multithreshold 1.46/subjGUI_MT.m @ 7:573c75007cf4

new intpow functions
author Ray Meddis <rmeddis@essex.ac.uk>
date Fri, 27 May 2011 14:29:28 +0100
parents f233164f4c86
children ecad0ea62b43
rev   line source
rmeddis@0 1 function varargout = subjGUI_MT(varargin)
rmeddis@0 2
rmeddis@0 3 % Begin initialization code - DO NOT EDIT
rmeddis@0 4 gui_Singleton = 1;
rmeddis@0 5 gui_State = struct('gui_Name', mfilename, ...
rmeddis@0 6 'gui_Singleton', gui_Singleton, ...
rmeddis@0 7 'gui_OpeningFcn', @subjGUI_MT_OpeningFcn, ...
rmeddis@0 8 'gui_OutputFcn', @subjGUI_MT_OutputFcn, ...
rmeddis@0 9 'gui_LayoutFcn', [] , ...
rmeddis@0 10 'gui_Callback', []);
rmeddis@0 11 if nargin && isstr(varargin{1})
rmeddis@0 12 gui_State.gui_Callback = str2func(varargin{1});
rmeddis@0 13 end
rmeddis@0 14
rmeddis@0 15 if nargout
rmeddis@0 16 [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
rmeddis@0 17 else
rmeddis@0 18 gui_mainfcn(gui_State, varargin{:});
rmeddis@0 19 end
rmeddis@0 20 % End initialization code - DO NOT EDIT
rmeddis@0 21
rmeddis@0 22 % --- Executes just before subjGUI_MT is made visible.
rmeddis@0 23 function subjGUI_MT_OpeningFcn(hObject, eventdata, handles, varargin)
rmeddis@0 24
rmeddis@0 25 % Choose default command line output for subjGUI_MT
rmeddis@0 26 handles.output = hObject;
rmeddis@0 27 initializeGUI(handles)
rmeddis@0 28 guidata(hObject, handles);
rmeddis@0 29
rmeddis@0 30 function varargout = subjGUI_MT_OutputFcn(hObject, eventdata, handles)
rmeddis@0 31 % Get default command line output from handles structure
rmeddis@0 32 varargout{1} = handles.output;
rmeddis@0 33
rmeddis@0 34 % -----------------------------------------------------initializeGUI
rmeddis@0 35 function initializeGUI(handles)
rmeddis@0 36 global experiment
rmeddis@0 37 global subjectGUIHandles expGUIhandles
rmeddis@0 38 addpath (['..' filesep 'MAP'], ['..' filesep 'utilities'], ...
rmeddis@0 39 ['..' filesep 'parameterStore'], ['..' filesep 'wavFileStore'],...
rmeddis@0 40 ['..' filesep 'testPrograms'])
rmeddis@0 41
rmeddis@0 42 dbstop if error
rmeddis@0 43
rmeddis@0 44 % subjectGUI size and location % [left bottom width height]
rmeddis@0 45 scrnsize=get(0,'screensize');
rmeddis@0 46 set(0, 'units','pixels')
rmeddis@0 47 switch experiment.ear
rmeddis@0 48 % use default size unless...
rmeddis@0 49 case {'MAPmodel', 'MAPmodelMultich', 'MAPmodelSingleCh', ...
rmeddis@0 50 'statsModelLogistic','statsModelRareEvent'}
rmeddis@0 51 % subjectGUI not needed for modelling so minimize subject GUI
rmeddis@0 52 set(gcf, 'units','pixels')
rmeddis@0 53 y=[0*scrnsize(3) 0.8*scrnsize(4) 0.1*scrnsize(3) 0.2*scrnsize(4)];
rmeddis@0 54 set(gcf,'position',y, 'color',[.871 .961 .996])
rmeddis@0 55
rmeddis@0 56
rmeddis@0 57
rmeddis@0 58 case 'MAPmodelListen',
rmeddis@0 59 % subjectGUI is needed for display purposes. Make it large
rmeddis@0 60 set(gcf, 'units','pixels')
rmeddis@0 61 y=[.665*scrnsize(3) 0.02*scrnsize(4) ...
rmeddis@0 62 0.33*scrnsize(3) 0.5*scrnsize(4)]; % alongside
rmeddis@0 63 set(gcf,'position',y, 'color',[.871 .961 .996])
rmeddis@0 64 end
rmeddis@0 65
rmeddis@0 66 switch experiment.ear
rmeddis@0 67 case{'left', 'right','diotic', 'dichoticLeft','dichoticRight'}
rmeddis@0 68 % Look to see if the button box exists and, if so, initialise it
rmeddis@0 69 buttonBoxIntitialize % harmless if no button box attached
rmeddis@0 70 end
rmeddis@0 71
rmeddis@0 72 % function varargout = subjGUI_MT(varargin)
rmeddis@0 73 %
rmeddis@0 74 % % Begin initialization code - DO NOT EDIT
rmeddis@0 75 % gui_Singleton = 1;
rmeddis@0 76 % gui_State = struct('gui_Name', mfilename, ...
rmeddis@0 77 % 'gui_Singleton', gui_Singleton, ...
rmeddis@0 78 % 'gui_OpeningFcn', @subjGUI_MT_OpeningFcn, ...
rmeddis@0 79 % 'gui_OutputFcn', @subjGUI_MT_OutputFcn, ...
rmeddis@0 80 % 'gui_LayoutFcn', [] , ...
rmeddis@0 81 % 'gui_Callback', []);
rmeddis@0 82 % if nargin && isstr(varargin{1})
rmeddis@0 83 % gui_State.gui_Callback = str2func(varargin{1});
rmeddis@0 84 % end
rmeddis@0 85 %
rmeddis@0 86 % if nargout
rmeddis@0 87 % [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
rmeddis@0 88 % else
rmeddis@0 89 % gui_mainfcn(gui_State, varargin{:});
rmeddis@0 90 % end
rmeddis@0 91 % % End initialization code - DO NOT EDIT
rmeddis@0 92 %
rmeddis@0 93 % % --- Executes just before subjGUI_MT is made visible.
rmeddis@0 94 % function subjGUI_MT_OpeningFcn(hObject, eventdata, handles, varargin)
rmeddis@0 95 %
rmeddis@0 96 % % Choose default command line output for subjGUI_MT
rmeddis@0 97 % handles.output = hObject;
rmeddis@0 98 % initializeGUI(handles)
rmeddis@0 99 % guidata(hObject, handles);
rmeddis@0 100 %
rmeddis@0 101 % function varargout = subjGUI_MT_OutputFcn(hObject, eventdata, handles)
rmeddis@0 102 % % Get default command line output from handles structure
rmeddis@0 103 % varargout{1} = handles.output;
rmeddis@0 104 %
rmeddis@0 105 % % -----------------------------------------------------initializeGUI
rmeddis@0 106 % function initializeGUI(handles)
rmeddis@0 107 % global experiment
rmeddis@0 108 % global subjectGUIHandles expGUIhandles
rmeddis@0 109 %
rmeddis@0 110 % dbstop if error
rmeddis@0 111 %
rmeddis@0 112 % % subjectGUI size and location % [left bottom width height]
rmeddis@0 113 % scrnsize=get(0,'screensize');
rmeddis@0 114 % set(0, 'units','pixels')
rmeddis@0 115 % switch experiment.ear
rmeddis@0 116 % % use default size unless...
rmeddis@0 117 % case {'MAPmodel', 'MAPmodelMultiCh','MAPmodelSingleCh', ...
rmeddis@0 118 % 'statsModelLogistic','statsModelRareEvent'}
rmeddis@0 119 % % subjectGUI not needed for modelling so minimize subject GUI
rmeddis@0 120 % set(gcf, 'units','pixels')
rmeddis@0 121 % y=[0*scrnsize(3) 0.8*scrnsize(4) 0.1*scrnsize(3) 0.2*scrnsize(4)];
rmeddis@0 122 % set(gcf,'position',y, 'color',[.871 .961 .996])
rmeddis@0 123 %
rmeddis@0 124 % case 'MAPmodelListen',
rmeddis@0 125 % % subjectGUI is needed for display purposes. Make it large
rmeddis@0 126 % set(gcf, 'units','pixels')
rmeddis@0 127 % y=[.665*scrnsize(3) 0.02*scrnsize(4) ...
rmeddis@0 128 % 0.33*scrnsize(3) 0.5*scrnsize(4)]; % alongside
rmeddis@0 129 % set(gcf,'position',y, 'color',[.871 .961 .996])
rmeddis@0 130 % end
rmeddis@0 131 %
rmeddis@0 132 % switch experiment.ear
rmeddis@0 133 % case{'left', 'right','diotic', 'dichoticLeft','dichoticRight'}
rmeddis@0 134 % % Look to see if the button box exists and, if so, initialise it
rmeddis@0 135 % buttonBoxIntitialize % harmless if no button box attached
rmeddis@0 136 % end
rmeddis@0 137
rmeddis@0 138 % clear display of previous mean values. This is a new measurement series
rmeddis@0 139 axes(expGUIhandles.axes4), cla
rmeddis@0 140 reset (expGUIhandles.axes4)
rmeddis@0 141
rmeddis@0 142 % handles needed in non-callback routines below
rmeddis@0 143 subjectGUIHandles=handles;
rmeddis@0 144
rmeddis@0 145 % start immediately
rmeddis@0 146 startNewExperiment(handles, expGUIhandles)
rmeddis@0 147 % This is the end of the experiment. Exit here and return to ExpGUI.
rmeddis@0 148
rmeddis@0 149 % ----------------------------------------------------- startNewExperiment
rmeddis@0 150 function startNewExperiment(handles, expGUIhandles)
rmeddis@0 151 % An experiment consists of a series of 'runs'.
rmeddis@0 152 % Resets all relevant variables at the beginning of a new experiment.
rmeddis@0 153 global experiment stimulusParameters betweenRuns
rmeddis@0 154
rmeddis@0 155 % 'start new experiment' button is the only valid action now
rmeddis@0 156 experiment.status='waitingForStart';
rmeddis@0 157
rmeddis@0 158 switch experiment.threshEstMethod
rmeddis@0 159 % add appropriate labels to subject GUI buttons
rmeddis@0 160 case {'2I2AFC++', '2I2AFC+++'}
rmeddis@0 161 set(handles.pushbutton3,'string','')
rmeddis@0 162 set(handles.pushbutton2,'string','2')
rmeddis@0 163 set(handles.pushbutton1,'string','1')
rmeddis@0 164 set(handles.pushbutton0,'string','0')
rmeddis@0 165 case {'MaxLikelihood', 'oneIntervalUpDown'}
rmeddis@0 166 if stimulusParameters.includeCue
rmeddis@0 167 set(handles.pushbutton3,'string','')
rmeddis@0 168 set(handles.pushbutton2,'string','2')
rmeddis@0 169 set(handles.pushbutton1,'string','1')
rmeddis@0 170 set(handles.pushbutton0,'string','0')
rmeddis@0 171 else
rmeddis@0 172 set(handles.pushbutton3,'string','')
rmeddis@0 173 set(handles.pushbutton2,'string','YES')
rmeddis@0 174 set(handles.pushbutton1,'string','NO')
rmeddis@0 175 set(handles.pushbutton0,'string','')
rmeddis@0 176 end
rmeddis@0 177 end
rmeddis@0 178
rmeddis@0 179 switch experiment.paradigm
rmeddis@0 180 case 'discomfort'
rmeddis@0 181 set(handles.pushbutton3,'string','')
rmeddis@0 182 set(handles.pushbutton2,'string','uncomfortable')
rmeddis@0 183 set(handles.pushbutton1,'string','loud')
rmeddis@0 184 set(handles.pushbutton0,'string','comfortable')
rmeddis@0 185 experiment.allowCatchTrials=0;
rmeddis@0 186 end
rmeddis@0 187
rmeddis@0 188 % experiment.subjGUIfontSize is set on expGUI
rmeddis@0 189 set(handles.pushbutton3,'FontSize',experiment.subjGUIfontSize)
rmeddis@0 190 set(handles.pushbutton2,'FontSize',experiment.subjGUIfontSize)
rmeddis@0 191 set(handles.pushbutton1,'FontSize',experiment.subjGUIfontSize)
rmeddis@0 192 set(handles.pushbutton0,'FontSize',experiment.subjGUIfontSize)
rmeddis@0 193 set(handles.pushbuttoNotSure,'FontSize',experiment.subjGUIfontSize)
rmeddis@0 194 set(handles.pushbuttonGO,'FontSize',experiment.subjGUIfontSize)
rmeddis@0 195 set(handles.textMSG,'FontSize',experiment.subjGUIfontSize)
rmeddis@0 196
rmeddis@0 197 set(handles.pushbutton19,'visible','off') % unused button
rmeddis@0 198
rmeddis@0 199 % start command window summary of progress
rmeddis@0 200 fprintf(' \n ----------- NEW MEASUREMENTS\n')
rmeddis@0 201 disp(['paradigm: ' experiment.paradigm])
rmeddis@0 202 cla(expGUIhandles.axes1)
rmeddis@0 203 cla(expGUIhandles.axes2)
rmeddis@0 204 cla(expGUIhandles.axes4)
rmeddis@0 205 cla(expGUIhandles.axes5)
rmeddis@0 206
rmeddis@0 207 experiment.stop=0; % status of 'stop' button
rmeddis@0 208 experiment.pleaseRepeat=0; % status of 'repeat' button
rmeddis@0 209 experiment.buttonBoxStatus='not busy';
rmeddis@0 210
rmeddis@0 211 % date and time and replace ':' with '_'
rmeddis@0 212 date=datestr(now);idx=findstr(':',date);date(idx)='_';
rmeddis@0 213 experiment.date=date;
rmeddis@0 214 timeNow=clock; betweenRuns.timeNow= timeNow;
rmeddis@0 215 experiment.timeAtStart=[num2str(timeNow(4)) ':' num2str(timeNow(5))];
rmeddis@0 216 experiment.minElapsed=0;
rmeddis@0 217
rmeddis@0 218 % unpack catch trial rates. The rate declines from the start rate
rmeddis@0 219 % to the base rate using a time constant.
rmeddis@0 220 stimulusParameters.catchTrialRate=stimulusParameters.catchTrialRates(1);
rmeddis@0 221 stimulusParameters.catchTrialBaseRate=...
rmeddis@0 222 stimulusParameters.catchTrialRates(2);
rmeddis@0 223 stimulusParameters.catchTrialTimeConstant=...
rmeddis@0 224 stimulusParameters.catchTrialRates(3);
rmeddis@0 225 if stimulusParameters.catchTrialBaseRate==0
rmeddis@0 226 stimulusParameters.catchTrialRate=0;
rmeddis@0 227 end
rmeddis@0 228
rmeddis@0 229 % for human measurements only, identify the start catch trial rate
rmeddis@0 230 switch experiment.ear
rmeddis@0 231 case{'left', 'right','diotic', 'dichoticLeft','dichoticRight'}
rmeddis@0 232 fprintf('stimulusParameters.catchTrialRate= %6.3f\n', ...
rmeddis@0 233 stimulusParameters.catchTrialRate)
rmeddis@0 234 end
rmeddis@0 235
rmeddis@0 236 % Reset betweenRuns parameters. this occurs only at experiment start
rmeddis@0 237 % withinRuns values are reset in 'startNewRun'
rmeddis@0 238 % this approach creates a more readable structure summary printout.
rmeddis@0 239 betweenRuns.thresholds=[];
rmeddis@0 240 betweenRuns.thresholds_mean=[];
rmeddis@0 241 betweenRuns.thresholds_median=[];
rmeddis@0 242 betweenRuns.forceThresholds=[];
rmeddis@0 243 betweenRuns.observationCount=[];
rmeddis@0 244 betweenRuns.catchTrials=[];
rmeddis@0 245 betweenRuns.timesOfFirstReversals=[];
rmeddis@0 246 betweenRuns.bestThresholdTracks=[];
rmeddis@0 247 betweenRuns.bestThresholdMeanTracks=[];
rmeddis@0 248 betweenRuns.bestThresholdMedianTracks=[];
rmeddis@0 249 betweenRuns.levelTracks=[];
rmeddis@0 250 betweenRuns.responseTracks=[];
rmeddis@0 251 betweenRuns.slopeKTracks=[];
rmeddis@0 252 betweenRuns.gainTracks=[];
rmeddis@0 253 betweenRuns.VminTracks=[];
rmeddis@0 254 betweenRuns.bestGain=[];
rmeddis@0 255 betweenRuns.bestVMin=[];
rmeddis@0 256 betweenRuns.bestPaMin=[];
rmeddis@0 257 betweenRuns.bestLogisticM=[];
rmeddis@0 258 betweenRuns.bestLogisticK=[];
rmeddis@0 259 betweenRuns.resets=0;
rmeddis@0 260 betweenRuns.runNumber=0;
rmeddis@0 261
rmeddis@0 262 % Up to two parameters can be changed between runs
rmeddis@0 263 % Find the variable parameters and randomize them
rmeddis@0 264 % e.g. 'variableList1 = stimulusParameters.targetFrequency;'
rmeddis@0 265 eval(['variableList1=stimulusParameters.' betweenRuns.variableName1 ';']);
rmeddis@0 266 eval(['variableList2=stimulusParameters.' betweenRuns.variableName2 ';']);
rmeddis@0 267 nVar1=length(variableList1);
rmeddis@0 268 nVar2=length(variableList2);
rmeddis@0 269
rmeddis@0 270 % Create two sequence vectors to represent the sequence of var1 and var2
rmeddis@0 271 % values. 'var1' changes most rapidly.
rmeddis@0 272 switch betweenRuns.randomizeSequence
rmeddis@0 273 case 'fixed sequence'
rmeddis@0 274 var1Sequence=repmat(betweenRuns.variableList1, 1,nVar2);
rmeddis@0 275 var2Sequence=reshape(repmat(betweenRuns.variableList2, ...
rmeddis@0 276 nVar1,1),1,nVar1*nVar2);
rmeddis@0 277 case 'randomize within blocks'
rmeddis@0 278 % the blocks are not randomized
rmeddis@0 279 var1Sequence=betweenRuns.variableList1;
rmeddis@0 280 ranNums=rand(1, length(var1Sequence)); [x idx]=sort(ranNums);
rmeddis@0 281 var1Sequence=var1Sequence(idx);
rmeddis@0 282 betweenRuns.variableList1=variableList1(idx);
rmeddis@0 283 var1Sequence=repmat(var1Sequence, 1,nVar2);
rmeddis@0 284 var2Sequence=reshape(repmat(betweenRuns.variableList2, nVar1,1)...
rmeddis@0 285 ,1,nVar1*nVar2);
rmeddis@0 286 case 'randomize across blocks'
rmeddis@0 287 var1Sequence=repmat(betweenRuns.variableList1, 1,nVar2);
rmeddis@0 288 var2Sequence=reshape(repmat(betweenRuns.variableList2, nVar1,1),...
rmeddis@0 289 1,nVar1*nVar2);
rmeddis@0 290 ranNums=rand(1, nVar1*nVar2);
rmeddis@0 291 [x idx]=sort(ranNums);
rmeddis@0 292 var1Sequence=var1Sequence(idx);
rmeddis@0 293 var2Sequence=var2Sequence(idx);
rmeddis@0 294 % there should be one start value for every combination
rmeddis@0 295 % of var1/ var2. In principle this allows these values to be
rmeddis@0 296 % programmed. Not currently in use.
rmeddis@0 297 stimulusParameters.WRVstartValues=...
rmeddis@0 298 stimulusParameters.WRVstartValues(idx);
rmeddis@0 299 end
rmeddis@0 300 betweenRuns.var1Sequence=var1Sequence;
rmeddis@0 301 betweenRuns.var2Sequence=var2Sequence;
rmeddis@0 302
rmeddis@0 303 % caught out vector needs to be linked to the length of the whole sequence
rmeddis@0 304 betweenRuns.caughtOut=zeros(1,length(var1Sequence));
rmeddis@0 305
rmeddis@0 306 disp('planned sequence:')
rmeddis@0 307 if min(var1Sequence)>1
rmeddis@0 308 % use decidaml places only if necessary
rmeddis@0 309 disp([betweenRuns.variableName1 ': ' num2str(var1Sequence,'%6.0f') ])
rmeddis@0 310 else
rmeddis@0 311 disp([betweenRuns.variableName1 ': ' num2str(var1Sequence,'%8.3f') ])
rmeddis@0 312 end
rmeddis@0 313 if min(var1Sequence)>1
rmeddis@0 314 disp([betweenRuns.variableName2 ': ' num2str(var2Sequence,'%6.0f') ])
rmeddis@0 315 else
rmeddis@0 316 disp([betweenRuns.variableName2 ': ' num2str(var2Sequence,'%8.3f') ])
rmeddis@0 317 end
rmeddis@0 318
rmeddis@0 319 fprintf('\nvariable1 \t variable2\t \n')
rmeddis@0 320 fprintf('%s \t %s\t Threshold \n',betweenRuns.variableName1,...
rmeddis@0 321 betweenRuns.variableName2)
rmeddis@0 322
rmeddis@0 323 % Light up 'GO' on subjGUI and advise.
rmeddis@0 324 set(handles.editdigitInput,'visible','off')
rmeddis@0 325 switch experiment.ear
rmeddis@0 326 case {'statsModelLogistic', 'statsModelRareEvent',...
rmeddis@0 327 'MAPmodel', 'MAPmodelMultiCh','MAPmodelSingleCh'}
rmeddis@0 328 % no changes required if model used
rmeddis@0 329 otherwise
rmeddis@0 330 set(handles.pushbuttonGO,'backgroundcolor','y')
rmeddis@0 331 set(handles.pushbuttonGO,'visible','on')
rmeddis@0 332 set(handles.frame1,'visible','off')
rmeddis@0 333 set(handles.textMSG,'backgroundcolor', 'w')
rmeddis@0 334 msg=[{'Ready to start new Experiment'}, {' '}, {'Please, click on the GO button'}];
rmeddis@0 335 set(handles.textMSG,'string', msg)
rmeddis@0 336
rmeddis@0 337 set(handles.pushbuttoNotSure,'visible','off')
rmeddis@0 338 set(handles.pushbuttonWrongButton,'visible','off')
rmeddis@0 339 set(handles.pushbutton3,'visible','off')
rmeddis@0 340 set(handles.pushbutton2,'visible','off')
rmeddis@0 341 set(handles.pushbutton1,'visible','off')
rmeddis@0 342 set(handles.pushbutton0,'visible','off')
rmeddis@0 343 pause(.1) % to allow display to be drawn
rmeddis@0 344 end
rmeddis@0 345
rmeddis@0 346 % Selecting the 'GO' button is the only valid operation action now
rmeddis@0 347 experiment.status='waitingForGO'; % i.e. waiting for new run
rmeddis@0 348
rmeddis@0 349 % control is now either manual, model (MAP) or randomization
rmeddis@0 350 switch experiment.ear
rmeddis@0 351 case {'MAPmodel','MAPmodelMultiCh','MAPmodelSingleCh','MAPmodelListen'} % MAP model is now the subject
rmeddis@0 352 stimulusParameters.calibrationdB=0; % Pascals required!
rmeddis@0 353 MAPmodelRunsGUI(handles)
rmeddis@0 354 % model is now the subject
rmeddis@0 355 case {'statsModelLogistic', 'statsModelRareEvent'}
rmeddis@0 356 % no catch trials for the statistical model
rmeddis@0 357 stimulusParameters.catchTrialBaseRate=0;
rmeddis@0 358 stimulusParameters.catchTrialRate=0;
rmeddis@0 359 statsModelRunsGUI(handles)
rmeddis@0 360 otherwise
rmeddis@0 361 %manual operation; wait for user to click on 'GO'
rmeddis@0 362 end
rmeddis@0 363
rmeddis@0 364 % Experiment complete (after MAP or randomization)
rmeddis@0 365 % return to 'initializeGUI' and then back to expGUI
rmeddis@0 366 % Manual control finds its own way home. Program control assumed when
rmeddis@0 367 % the user hits the GO button
rmeddis@0 368
rmeddis@0 369 % ----------------------------------------------------------------- startNewRun
rmeddis@0 370 function startNewRun(handles)
rmeddis@0 371 % There are many ways to arrive here.
rmeddis@0 372 % Under manual control this is achieved by hitting the GO button
rmeddis@0 373 % either via the button box or a mouse click
rmeddis@0 374 % MAP and randomization methods call this too
rmeddis@0 375
rmeddis@0 376 global experiment stimulusParameters betweenRuns withinRuns expGUIhandles
rmeddis@0 377 global LevittControl rareEvent
rmeddis@0 378
rmeddis@0 379 figure(handles.figure1) % guarantee subject GUI visibility
rmeddis@0 380
rmeddis@0 381 % ignore call if program is not ready
rmeddis@0 382 if ~strcmp(experiment.status,'waitingForGO'), return, end
rmeddis@0 383
rmeddis@0 384 set(handles.pushbuttonGO,'visible','off')
rmeddis@0 385
rmeddis@0 386 % append message to expGUI message box to alert experimenter that the user
rmeddis@0 387 % is active
rmeddis@0 388 addToMsg('Starting new trial',0)
rmeddis@0 389
rmeddis@0 390 cla(expGUIhandles.axes1), title(''); % stimulus
rmeddis@0 391 cla(expGUIhandles.axes2), title(''); % WRV track
rmeddis@0 392 drawnow
rmeddis@0 393
rmeddis@0 394 betweenRuns.runNumber=betweenRuns.runNumber + 1;
rmeddis@0 395
rmeddis@0 396 withinRuns.trialNumber=1;
rmeddis@0 397 withinRuns.variableValue=...
rmeddis@0 398 stimulusParameters.WRVstartValues(betweenRuns.runNumber);
rmeddis@0 399 % add random jitter to start level
rmeddis@0 400 if ~experiment.singleShot
rmeddis@0 401 % SS or single shot allows the user to precisely set the WRV
rmeddis@0 402 withinRuns.variableValue=withinRuns.variableValue +...
rmeddis@0 403 (rand-0.5)*stimulusParameters.jitterStartdB;
rmeddis@0 404 end
rmeddis@0 405
rmeddis@0 406 withinRuns.peaks=[];
rmeddis@0 407 withinRuns.troughs=[];
rmeddis@0 408 withinRuns.levelList=[];
rmeddis@0 409 withinRuns.meanEstTrack=[];
rmeddis@0 410 withinRuns.bestSlopeK=[];
rmeddis@0 411 withinRuns.bestGain=[];
rmeddis@0 412 withinRuns.bestVMin=[];
rmeddis@0 413 withinRuns.forceThreshold=NaN;
rmeddis@0 414 withinRuns.responseList=[];
rmeddis@0 415 withinRuns.caughtOut=0;
rmeddis@0 416 withinRuns.wrongButton=0;
rmeddis@0 417 withinRuns.catchTrialCount=0;
rmeddis@0 418 withinRuns.thresholdEstimateTrack=[];
rmeddis@0 419
rmeddis@0 420 withinRuns.beginningOfPhase2=0;
rmeddis@0 421 withinRuns.nowInPhase2=0;
rmeddis@0 422 withinRuns.thisIsRepeatTrial=0;
rmeddis@0 423
rmeddis@0 424 rareEvent.Euclid=NaN;
rmeddis@0 425 rareEvent.bestGain=NaN;
rmeddis@0 426 rareEvent.bestVMin=NaN;
rmeddis@0 427 rareEvent.thresholddB=0;
rmeddis@0 428 rareEvent.bestPaMindB=NaN;
rmeddis@0 429 rareEvent.predictionLevels=[];
rmeddis@0 430 rareEvent.predictionsRE=[];
rmeddis@0 431
rmeddis@0 432 LevittControl.sequence=[];
rmeddis@0 433
rmeddis@0 434 % on-screen count of number of runs still to complete
rmeddis@0 435 trialsToGo=length(betweenRuns.var1Sequence)-betweenRuns.runNumber;
rmeddis@0 436 set(handles.toGoCounter,'string', trialsToGo);
rmeddis@0 437
rmeddis@0 438 switch experiment.threshEstMethod
rmeddis@0 439 case {'2I2AFC++', '2I2AFC+++'}
rmeddis@0 440 % For 2I2AFC the buttons need to be on the screen ab initio
rmeddis@0 441 Levitt2 % inititalize Levitt2 procedure
rmeddis@0 442 end
rmeddis@0 443
rmeddis@0 444 switch experiment.ear
rmeddis@0 445 case{'left', 'right','diotic', 'dichoticLeft','dichoticRight'}
rmeddis@0 446 % allow subject time to recover from 'go' press
rmeddis@0 447 pause(experiment.clickToStimulusPause)
rmeddis@0 448 end
rmeddis@0 449
rmeddis@0 450 errormsg=nextStimulus(handles); % get the show on the road
rmeddis@0 451
rmeddis@0 452 % switch experiment.paradigm
rmeddis@0 453 % case 'SRT'
rmeddis@0 454 % set(handles.editdigitInput,'visible','on')
rmeddis@0 455 % uicontrol(handles.editdigitInput)
rmeddis@0 456 % end
rmeddis@0 457
rmeddis@0 458 % terminate if there is any kind of problem
rmeddis@0 459 if ~isempty(errormsg)
rmeddis@0 460 % e.g. limits exceeded, clipping
rmeddis@0 461 disp(errormsg)
rmeddis@0 462 runCompleted(handles)
rmeddis@0 463 return
rmeddis@0 464 end
rmeddis@0 465
rmeddis@0 466 % return route is variable (see intro to this function)
rmeddis@0 467
rmeddis@0 468 % -----------------------------------------------------buttonBox_callback
rmeddis@0 469 function buttonBox_callback(obj, info)
rmeddis@0 470 global experiment
rmeddis@0 471 global serobj
rmeddis@0 472 global subjectGUIHandles
rmeddis@0 473
rmeddis@0 474 % do not accept callback if one is already in process
rmeddis@0 475 if strcmp(experiment.buttonBoxStatus,'busy')
rmeddis@0 476 disp(' ignored button press')
rmeddis@0 477 return
rmeddis@0 478 end
rmeddis@0 479 experiment.buttonBoxStatus='busy';
rmeddis@0 480 % fclose(serobj)
rmeddis@0 481
rmeddis@0 482 % identify the code of the button pressed
rmeddis@0 483 buttonPressedNo = fscanf(serobj,'%c',1);
rmeddis@0 484
rmeddis@0 485 % This is the map from the button to the Cedrus codes
rmeddis@0 486 switch experiment.buttonBoxType
rmeddis@0 487 case 'horizontal'
rmeddis@0 488 pbGo='7'; pb0='1';
rmeddis@0 489 pb1='2'; pb2='3';
rmeddis@0 490 pbRepeat='4'; pbWrong='6'; pbBlank='5';
rmeddis@0 491 case 'square'
rmeddis@0 492 pbGo='7'; pb0='1';
rmeddis@0 493 pb1='3'; pb2='4';
rmeddis@0 494 pbRepeat='8'; pbWrong='6'; pbBlank='5';
rmeddis@0 495 end
rmeddis@0 496
rmeddis@0 497 % decide what to do
rmeddis@0 498 switch experiment.status
rmeddis@0 499 case {'presentingStimulus', 'waitingForStart', 'trialcompleted', ...
rmeddis@0 500 'endOfExperiment'}
rmeddis@0 501 disp(' ignored button press')
rmeddis@0 502
rmeddis@0 503 case 'waitingForGO'
rmeddis@0 504 % i.e. waiting for new run
rmeddis@0 505 if strcmp(buttonPressedNo,pbGo) % only GO button accepted
rmeddis@0 506 startNewRun(subjectGUIHandles)
rmeddis@0 507 else
rmeddis@0 508 disp(' ignored button press')
rmeddis@0 509 end
rmeddis@0 510
rmeddis@0 511 case 'waitingForResponse'
rmeddis@0 512 % response to stimuli
rmeddis@0 513 switch buttonPressedNo
rmeddis@0 514 case pb0 % button 0 (top left)
rmeddis@0 515 switch experiment.threshEstMethod
rmeddis@0 516 case {'2I2AFC++', '2I2AFC+++'}
rmeddis@0 517 disp(' ignored button press')
rmeddis@0 518 otherwise
rmeddis@0 519 set(subjectGUIHandles.pushbutton0,...
rmeddis@0 520 'backgroundcolor','r')
rmeddis@0 521 pause(.1)
rmeddis@0 522 set(subjectGUIHandles.pushbutton0,...
rmeddis@0 523 'backgroundcolor',get(0,...
rmeddis@0 524 'defaultUicontrolBackgroundColor'))
rmeddis@0 525 userSelects0or1(subjectGUIHandles)
rmeddis@0 526 end
rmeddis@0 527
rmeddis@0 528 case pb1 % button 1 (bottom left)
rmeddis@0 529 switch experiment.threshEstMethod
rmeddis@0 530 case {'2I2AFC++', '2I2AFC+++'}
rmeddis@0 531 userSelects0or1(subjectGUIHandles)
rmeddis@0 532 otherwise
rmeddis@0 533 set(subjectGUIHandles.pushbutton1,...
rmeddis@0 534 'backgroundcolor','r')
rmeddis@0 535 pause(.1)
rmeddis@0 536 set(subjectGUIHandles.pushbutton1,...
rmeddis@0 537 'backgroundcolor',get(0,...
rmeddis@0 538 'defaultUicontrolBackgroundColor'))
rmeddis@0 539 userSelects0or1(subjectGUIHandles)
rmeddis@0 540 end
rmeddis@0 541
rmeddis@0 542 case pb2 % button 2 (bottom right)
rmeddis@0 543 switch experiment.threshEstMethod
rmeddis@0 544 case {'2I2AFC++', '2I2AFC+++'}
rmeddis@0 545 userSelects2 (subjectGUIHandles)
rmeddis@0 546 otherwise
rmeddis@0 547 set(subjectGUIHandles.pushbutton2,...
rmeddis@0 548 'backgroundcolor','r')
rmeddis@0 549 pause(.1)
rmeddis@0 550 set(subjectGUIHandles.pushbutton2,...
rmeddis@0 551 'backgroundcolor',get(0,...
rmeddis@0 552 'defaultUicontrolBackgroundColor'))
rmeddis@0 553 userSelects2 (subjectGUIHandles)
rmeddis@0 554 end
rmeddis@0 555
rmeddis@0 556 case pbRepeat % extreme right button
rmeddis@0 557 switch experiment.threshEstMethod
rmeddis@0 558 case {'2I2AFC++', '2I2AFC+++'}
rmeddis@0 559 disp(' ignored button press')
rmeddis@0 560 otherwise
rmeddis@0 561
rmeddis@0 562 set(subjectGUIHandles.pushbuttoNotSure,...
rmeddis@0 563 'backgroundcolor','r')
rmeddis@0 564 pause(.1)
rmeddis@0 565 set(subjectGUIHandles.pushbuttoNotSure,...
rmeddis@0 566 'backgroundcolor',get(0,...
rmeddis@0 567 'defaultUicontrolBackgroundColor'))
rmeddis@0 568 userSelectsPleaseRepeat (subjectGUIHandles)
rmeddis@0 569 end
rmeddis@0 570
rmeddis@0 571 case {pbWrong, pbBlank}
rmeddis@0 572 disp(' ignored button press')
rmeddis@0 573
rmeddis@0 574 otherwise % unrecognised button
rmeddis@0 575 disp('ignored button press')
rmeddis@0 576 end % end (button press number)
rmeddis@0 577 otherwise
rmeddis@0 578 disp('ignored button press')
rmeddis@0 579 end % experiment status
rmeddis@0 580
rmeddis@0 581 % All processing returns through here.
rmeddis@0 582 % fopen(serobj); % flushes the input buffer
rmeddis@0 583
rmeddis@0 584 % buttonPressedNo = fscanf(serobj,'%c',1);
rmeddis@0 585
rmeddis@0 586 % button box remains 'busy' until after the stimulus has been presented
rmeddis@0 587 experiment.buttonBoxStatus='not busy';
rmeddis@0 588
rmeddis@0 589 % -------------------------------------------------- pushbuttonGO_Callback
rmeddis@0 590 function pushbuttonGO_Callback(hObject, eventdata, handles)
rmeddis@0 591 % This is a mouse click path
rmeddis@0 592 % GO function is also called directly from button box
rmeddis@0 593 % and from MAP model and stats model
rmeddis@0 594
rmeddis@0 595 set(handles.pushbuttonGO,'visible','off')
rmeddis@0 596 startNewRun(handles)
rmeddis@0 597
rmeddis@0 598 % ---------------------------------------------------pushbutton0_Callback
rmeddis@0 599 function pushbutton0_Callback(hObject, eventdata, handles)
rmeddis@0 600 global experiment
rmeddis@0 601 % This is a mouse click path
rmeddis@0 602
rmeddis@0 603 % ignore 0 button if 2I2AFC used
rmeddis@0 604 if findstr(experiment.threshEstMethod,'2I2AFC'), return, end
rmeddis@0 605
rmeddis@0 606 % userDoesNotHearTarget(handles) % only possible interpretation
rmeddis@0 607 userDecides(handles, false)
rmeddis@0 608
rmeddis@0 609 % -------------------------------------------------- pushbutton1_Callback
rmeddis@0 610 function pushbutton1_Callback(hObject, eventdata, handles)
rmeddis@0 611 userSelects0or1(handles) % also called from buttonBox
rmeddis@0 612
rmeddis@0 613 % ---------------------------------------------------pushbutton2_Callback
rmeddis@0 614 function pushbutton2_Callback(hObject, eventdata, handles)
rmeddis@0 615 userSelects2(handles) % also called from buttonBox
rmeddis@0 616
rmeddis@0 617 % --------------------------------------------- pushbuttoNotSure_Callback
rmeddis@0 618 function pushbuttoNotSure_Callback(hObject, eventdata, handles)
rmeddis@0 619 userSelectsPleaseRepeat(handles) % also called from buttonBox
rmeddis@0 620
rmeddis@0 621 % -------------------------------------------------- pushbutton3_Callback
rmeddis@0 622 function pushbutton3_Callback(hObject, eventdata, handles)
rmeddis@0 623
rmeddis@0 624 % ------------------------------------------------- pushbutton19_Callback
rmeddis@0 625 function pushbutton19_Callback(hObject, eventdata, handles)
rmeddis@0 626 % should be invisible (ignore)
rmeddis@0 627
rmeddis@0 628 % --------------------------------------- pushbuttonWrongButton_Callback
rmeddis@0 629 function pushbuttonWrongButton_Callback(hObject, eventdata, handles)
rmeddis@0 630 userSelectsWrongButton(handles)
rmeddis@0 631
rmeddis@0 632 % --------------------------------------- editdigitInput_Callback
rmeddis@0 633 function editdigitInput_Callback(hObject, eventdata, handles)
rmeddis@0 634 userSelects0or1(handles) % after digit string input
rmeddis@0 635
rmeddis@0 636
rmeddis@0 637
rmeddis@0 638 % ----------------------------------------------------- userSelects0or1
rmeddis@0 639 function userSelects0or1(handles)
rmeddis@0 640 global experiment withinRuns
rmeddis@0 641
rmeddis@0 642 switch experiment.threshEstMethod
rmeddis@0 643 case {'2I2AFC++', '2I2AFC+++'}
rmeddis@0 644 switch withinRuns.stimulusOrder
rmeddis@0 645 case 'targetFirst';
rmeddis@0 646 % userHearsTarget(handles)
rmeddis@0 647 userDecides(handles, true)
rmeddis@0 648 otherwise
rmeddis@0 649 % userDoesNotHearTarget(handles)
rmeddis@0 650 userDecides(handles, false)
rmeddis@0 651 end
rmeddis@0 652 otherwise
rmeddis@0 653 % single interval
rmeddis@0 654 % 0 or 1 are treated as equivalent (i.e. target is not heard)
rmeddis@0 655 userDecides(handles, false)
rmeddis@0 656 end
rmeddis@0 657 % return to pushButton1 callback
rmeddis@0 658
rmeddis@0 659 % ----------------------------------------------------- userSelects2
rmeddis@0 660 function userSelects2(handles)
rmeddis@0 661 global experiment withinRuns
rmeddis@0 662 switch experiment.threshEstMethod
rmeddis@0 663 case {'2I2AFC++', '2I2AFC+++'}
rmeddis@0 664 switch withinRuns.stimulusOrder
rmeddis@0 665 case 'targetSecond';
rmeddis@0 666 % userDoesNotHearTarget(handles)
rmeddis@0 667 userDecides(handles, true)
rmeddis@0 668 otherwise
rmeddis@0 669 % userHearsTarget(handles)
rmeddis@0 670 userDecides(handles, false)
rmeddis@0 671 end
rmeddis@0 672 otherwise
rmeddis@0 673 % single interval (2 targets heard)
rmeddis@0 674 userDecides(handles, true)
rmeddis@0 675 end
rmeddis@0 676 % return to pushButton2 callback
rmeddis@0 677
rmeddis@0 678 % ----------------------------------------------------- ---- userDecides
rmeddis@0 679 function userDecides(handles, saidYes)
rmeddis@0 680 global experiment stimulusParameters betweenRuns withinRuns
rmeddis@0 681 global rareEvent logistic psy levelsBinVector
rmeddis@0 682
rmeddis@0 683 if experiment.singleShot
rmeddis@0 684 return
rmeddis@0 685 end
rmeddis@0 686
rmeddis@0 687 % ignore click if not 'waitingForResponse'
rmeddis@0 688 if ~strcmp(experiment.status,'waitingForResponse')
rmeddis@0 689 disp('ignored click')
rmeddis@0 690 return
rmeddis@0 691 end
rmeddis@0 692
rmeddis@0 693 % speech reception threshold
rmeddis@0 694 if strcmp(stimulusParameters.targetType,'digitStrings')
rmeddis@0 695 digitsInput=get(handles.editdigitInput,'string');
rmeddis@0 696 % must be three digits
rmeddis@0 697 if ~(length(digitsInput)==3)
rmeddis@0 698 addToMsg(['error message: Wrong no of digits'], 0, 1)
rmeddis@0 699 set(handles.textMSG,'string', 'Wrong no of digits', ...
rmeddis@0 700 'BackgroundColor','r', 'ForegroundColor', 'w')
rmeddis@0 701 set(handles.editdigitInput,'string','')
rmeddis@0 702
rmeddis@0 703 return
rmeddis@0 704 end
rmeddis@0 705 % obtain correct answer from file name
rmeddis@0 706 x=stimulusParameters.digitString;
rmeddis@0 707 idx=find(x=='O'); x(idx)='0'; % replace 'oh' with zero
rmeddis@0 708
rmeddis@0 709 disp([x ' ' digitsInput])
rmeddis@0 710
rmeddis@0 711 if x==digitsInput
rmeddis@0 712 saidYes=1;
rmeddis@0 713 else
rmeddis@0 714 saidYes=0;
rmeddis@0 715 end
rmeddis@0 716 set(handles.editdigitInput,'string','')
rmeddis@0 717 set(handles.editdigitInput,'visible','off')
rmeddis@0 718 pause(0.1)
rmeddis@0 719 end
rmeddis@0 720
rmeddis@0 721
rmeddis@0 722
rmeddis@0 723 % no button presses accepted while processing
rmeddis@0 724 experiment.status='processingResponse';
rmeddis@0 725
rmeddis@0 726 % catch trials. Restart trial if caught
rmeddis@0 727 if withinRuns.catchTrial
rmeddis@0 728 if saidYes
rmeddis@0 729 disp('catch trial - caught out')
rmeddis@0 730 withinRuns.caughtOut=withinRuns.caughtOut+1;
rmeddis@0 731
rmeddis@0 732 % special: estimate caught out rate by allowing the trial
rmeddis@0 733 % to continue after catch
rmeddis@0 734 if stimulusParameters.catchTrialBaseRate==0.5
rmeddis@0 735 % To use this facility, set the catchTrialRate and the
rmeddis@0 736 % catchTrialBaseRate both to 0.5
rmeddis@0 737 % update false positive rate
rmeddis@0 738 betweenRuns.caughtOut(betweenRuns.runNumber)=...
rmeddis@0 739 withinRuns.caughtOut;
rmeddis@0 740 plotProgressThisTrial(handles)
rmeddis@0 741 nextStimulus(handles);
rmeddis@0 742 return
rmeddis@0 743 end
rmeddis@0 744
rmeddis@0 745 % Punishment: restart the trial
rmeddis@0 746 set(handles.frame1,'backgroundColor','r')
rmeddis@0 747 set(handles.pushbuttonGO, ...
rmeddis@0 748 'visible','on', 'backgroundcolor','y') % and go again
rmeddis@0 749 msg=[{'Start again: catch trial error'}, {' '},...
rmeddis@0 750 {'Please,click on the GO button'}];
rmeddis@0 751 set(handles.textMSG,'string',msg)
rmeddis@0 752 [y,fs]=wavread('ding.wav');
rmeddis@0 753 wavplay(y/100,fs)
rmeddis@0 754
rmeddis@0 755 % raise catch trial rate temporarily.
rmeddis@0 756 % this is normally reduced on each new trial (see GO)
rmeddis@0 757 stimulusParameters.catchTrialRate=...
rmeddis@0 758 stimulusParameters.catchTrialRate+0.1;
rmeddis@0 759 if stimulusParameters.catchTrialRate>0.5
rmeddis@0 760 stimulusParameters.catchTrialRate=0.5;
rmeddis@0 761 end
rmeddis@0 762 fprintf('stimulusParameters.catchTrialRate= %6.3f\n', ...
rmeddis@0 763 stimulusParameters.catchTrialRate)
rmeddis@0 764
rmeddis@0 765 betweenRuns.caughtOut(betweenRuns.runNumber)=...
rmeddis@0 766 1+betweenRuns.caughtOut(betweenRuns.runNumber);
rmeddis@0 767 betweenRuns.runNumber=betweenRuns.runNumber-1;
rmeddis@0 768 experiment.status='waitingForGO';
rmeddis@0 769 return % unwind and wait for button press
rmeddis@0 770 else % (said No)
rmeddis@0 771 % user claims not to have heard target. fortunate as it was not
rmeddis@0 772 % present. So, repeat the stimulus (possibly with target)
rmeddis@0 773 % and behave as if the last trial did not occur
rmeddis@0 774 errormsg=nextStimulus(handles);
rmeddis@0 775
rmeddis@0 776 % terminate if there is any kind of problem
rmeddis@0 777 if ~isempty(errormsg)
rmeddis@0 778 % e.g. limits exceeded, clipping
rmeddis@0 779 disp(['Error nextStimulus: ' errormsg])
rmeddis@0 780 runCompleted(handles)
rmeddis@0 781 return
rmeddis@0 782 end
rmeddis@0 783 return % no further action - next trial
rmeddis@0 784 end
rmeddis@0 785 end
rmeddis@0 786
rmeddis@0 787 % This section analyses the responses, makes tracks and defines next stim.
rmeddis@0 788
rmeddis@0 789 % Define response and update response list
rmeddis@0 790 if saidYes
rmeddis@0 791 % target was heard, so response=1;
rmeddis@0 792 withinRuns.responseList=[withinRuns.responseList 1]; % 'heard it!'
rmeddis@0 793 else
rmeddis@0 794 % target was not hear heard, so response=0;
rmeddis@0 795 withinRuns.responseList=[withinRuns.responseList 0];
rmeddis@0 796 end
rmeddis@0 797 withinRuns.levelList=[withinRuns.levelList withinRuns.variableValue];
rmeddis@0 798 trialNumber=length(withinRuns.responseList);
rmeddis@0 799
rmeddis@0 800 % keep track of peaks and troughs;
rmeddis@0 801 % identify direction of change during initial period
rmeddis@0 802 if saidYes
rmeddis@0 803 % default step size before first reversal
rmeddis@0 804 WRVinitialStep=-stimulusParameters.WRVinitialStep;
rmeddis@0 805 WRVsmallStep=-stimulusParameters.WRVsmallStep;
rmeddis@0 806 % if the previous direction was 'less difficult', this must be a peak
rmeddis@0 807 if strcmp(withinRuns.direction,'less difficult') ...
rmeddis@0 808 && length(withinRuns.levelList)>1
rmeddis@0 809 withinRuns.peaks=[withinRuns.peaks withinRuns.variableValue];
rmeddis@0 810 end
rmeddis@0 811 withinRuns.direction='more difficult';
rmeddis@0 812
rmeddis@0 813 else
rmeddis@0 814 % said 'no'
rmeddis@0 815 % default step size before first reversal
rmeddis@0 816 WRVinitialStep=stimulusParameters.WRVinitialStep;
rmeddis@0 817 WRVsmallStep=stimulusParameters.WRVsmallStep;
rmeddis@0 818
rmeddis@0 819 % if the previous direction was 'up', this must be a peak
rmeddis@0 820 if strcmp(withinRuns.direction,'more difficult') ...
rmeddis@0 821 && length(withinRuns.levelList)>1
rmeddis@0 822 withinRuns.troughs=[withinRuns.troughs withinRuns.variableValue];
rmeddis@0 823 end
rmeddis@0 824 withinRuns.direction='less difficult';
rmeddis@0 825 end
rmeddis@0 826
rmeddis@0 827 % phase 2 is all the levels after and incuding the first reversal
rmeddis@0 828 % plus the level before that
rmeddis@0 829 if ~withinRuns.nowInPhase2 && length(withinRuns.peaks)+ ...
rmeddis@0 830 length(withinRuns.troughs)>0
rmeddis@0 831 % if ~withinRuns.nowInPhase2 && (~isempty(withinRuns.peaks) ...
rmeddis@0 832 % || ~isempty(withinRuns.troughs))
rmeddis@0 833 % define phase 2
rmeddis@0 834 withinRuns.beginningOfPhase2=trialNumber-1;
rmeddis@0 835 withinRuns.nowInPhase2=1;
rmeddis@0 836 WRVsmallStep=WRVinitialStep/2;
rmeddis@0 837 end
rmeddis@0 838
rmeddis@0 839 if withinRuns.nowInPhase2
rmeddis@0 840 % keep a record of all levels and responses in phase 2 only
rmeddis@0 841 withinRuns.levelsPhaseTwo=...
rmeddis@0 842 withinRuns.levelList(withinRuns.beginningOfPhase2:end);
rmeddis@0 843 withinRuns.responsesPhaseTwo=...
rmeddis@0 844 withinRuns.responseList(withinRuns.beginningOfPhase2:end);
rmeddis@0 845 else
rmeddis@0 846 withinRuns.levelsPhaseTwo=[];
rmeddis@0 847 end
rmeddis@0 848
rmeddis@0 849
rmeddis@0 850 % get (or substitute) threshold estimate
rmeddis@0 851 switch experiment.threshEstMethod
rmeddis@0 852 case {'2I2AFC++', '2I2AFC+++'}
rmeddis@0 853 % for plotting psychometric function only
rmeddis@0 854 if withinRuns.beginningOfPhase2>0
rmeddis@0 855 [psy, levelsBinVector, logistic, rareEvent]= ...
rmeddis@0 856 bestFitPsychometicFunctions...
rmeddis@0 857 (withinRuns.levelsPhaseTwo, withinRuns.responsesPhaseTwo);
rmeddis@0 858 end
rmeddis@0 859
rmeddis@0 860 if ~isempty(withinRuns.peaks) && ~isempty(withinRuns.troughs)
rmeddis@0 861 thresholdEstimate= ...
rmeddis@0 862 mean([mean(withinRuns.peaks) mean(withinRuns.troughs)]);
rmeddis@0 863 else
rmeddis@0 864 thresholdEstimate=NaN;
rmeddis@0 865 end
rmeddis@0 866 otherwise
rmeddis@0 867 % single interval methods
rmeddis@0 868 try
rmeddis@0 869 % using the s trial after the first reversal
rmeddis@0 870 [psy, levelsBinVector, logistic, rareEvent]= ...
rmeddis@0 871 bestFitPsychometicFunctions(withinRuns.levelsPhaseTwo,...
rmeddis@0 872 withinRuns.responsesPhaseTwo);
rmeddis@0 873 catch
rmeddis@0 874 logistic.bestThreshold=NaN;
rmeddis@0 875 end
rmeddis@0 876 end
rmeddis@0 877
rmeddis@0 878 if withinRuns.nowInPhase2
rmeddis@0 879 % save tracks of threshold estimates for plotting andprinting
rmeddis@0 880 switch experiment.functionEstMethod
rmeddis@0 881 case {'logisticLS', 'logisticML'}
rmeddis@0 882 if withinRuns.nowInPhase2
rmeddis@0 883 withinRuns.meanEstTrack=...
rmeddis@0 884 [withinRuns.meanEstTrack ...
rmeddis@0 885 mean(withinRuns.levelsPhaseTwo)];
rmeddis@0 886 withinRuns.thresholdEstimateTrack=...
rmeddis@0 887 [withinRuns.thresholdEstimateTrack ...
rmeddis@0 888 logistic.bestThreshold];
rmeddis@0 889 end
rmeddis@0 890 case 'rareEvent'
rmeddis@0 891 withinRuns.meanEstTrack=...
rmeddis@0 892 [withinRuns.meanEstTrack rareEvent.thresholddB];
rmeddis@0 893 withinRuns.thresholdEstimateTrack=...
rmeddis@0 894 [withinRuns.thresholdEstimateTrack logistic.bestThreshold];
rmeddis@0 895 case 'peaksAndTroughs'
rmeddis@0 896 withinRuns.meanEstTrack=...
rmeddis@0 897 [withinRuns.meanEstTrack thresholdEstimate];
rmeddis@0 898 withinRuns.thresholdEstimateTrack=...
rmeddis@0 899 [withinRuns.thresholdEstimateTrack thresholdEstimate];
rmeddis@0 900 end
rmeddis@0 901 end
rmeddis@0 902
rmeddis@0 903 % special discomfort condition
rmeddis@0 904 % run is completed when subject hits '2' button
rmeddis@0 905 switch experiment.paradigm
rmeddis@0 906 case 'discomfort'
rmeddis@0 907 if saidYes
rmeddis@0 908 runCompleted(handles)
rmeddis@0 909 return
rmeddis@0 910 end
rmeddis@0 911 end
rmeddis@0 912
rmeddis@0 913 % choose the next level for the stimulus
rmeddis@0 914 switch experiment.threshEstMethod
rmeddis@0 915 case {'2I2AFC++', '2I2AFC+++'}
rmeddis@0 916 if saidYes
rmeddis@0 917 [WRVinitialStep, msg]=Levitt2('hit', withinRuns.variableValue);
rmeddis@0 918 else
rmeddis@0 919 [WRVinitialStep, msg]=Levitt2('miss',withinRuns.variableValue);
rmeddis@0 920 end
rmeddis@0 921
rmeddis@0 922 % empty message means continue as normal
rmeddis@0 923 if ~isempty(msg)
rmeddis@0 924 runCompleted(handles)
rmeddis@0 925 return
rmeddis@0 926 end
rmeddis@0 927 newWRVvalue=withinRuns.variableValue-WRVinitialStep;
rmeddis@0 928
rmeddis@0 929 case {'MaxLikelihood', 'oneIntervalUpDown'}
rmeddis@0 930 % run completed by virtue of number of trials
rmeddis@0 931 % or restart because listener is in trouble
rmeddis@0 932 if length(withinRuns.levelsPhaseTwo)== experiment.maxTrials
rmeddis@0 933 % Use bonomial test to decide if there is an imbalance in the
rmeddis@0 934 % number of 'yes'es and 'no's
rmeddis@0 935 yesCount=sum(withinRuns.responseList);
rmeddis@0 936 noCount=length(withinRuns.responseList)-yesCount;
rmeddis@0 937 z=abs(yesCount-noCount)/(yesCount+noCount)^0.5;
rmeddis@0 938 if z>1.96
rmeddis@0 939 betweenRuns.resets=betweenRuns.resets+1;
rmeddis@0 940 disp([ 'reset / z= ' num2str( z) ...
rmeddis@0 941 ' Nresets= ' num2str( betweenRuns.resets) ] )
rmeddis@0 942 withinRuns.peaks=[];
rmeddis@0 943 withinRuns.troughs=[];
rmeddis@0 944 withinRuns.levelList=withinRuns.levelList(end);
rmeddis@0 945 withinRuns.meanEstTrack=withinRuns.meanEstTrack(end);
rmeddis@0 946 withinRuns.forceThreshold=NaN;
rmeddis@0 947 withinRuns.responseList=withinRuns.responseList(end);
rmeddis@0 948 withinRuns.beginningOfPhase2=0;
rmeddis@0 949 withinRuns.nowInPhase2=0;
rmeddis@0 950 withinRuns.thresholdEstimateTrack=...
rmeddis@0 951 withinRuns.thresholdEstimateTrack(end);
rmeddis@0 952 else
rmeddis@0 953 runCompleted(handles)
rmeddis@0 954 return
rmeddis@0 955 end
rmeddis@0 956 end
rmeddis@0 957
rmeddis@0 958 % set new value for WRV
rmeddis@0 959 if withinRuns.nowInPhase2
rmeddis@0 960 % phase 2
rmeddis@0 961 currentMeanEst=withinRuns.thresholdEstimateTrack(end);
rmeddis@0 962 switch experiment.threshEstMethod
rmeddis@0 963 case 'MaxLikelihood'
rmeddis@0 964 newWRVvalue=currentMeanEst;
rmeddis@0 965 case {'oneIntervalUpDown'}
rmeddis@0 966 newWRVvalue=withinRuns.variableValue+WRVsmallStep;
rmeddis@0 967 end
rmeddis@0 968 else
rmeddis@0 969 % phase 1
rmeddis@0 970 if withinRuns.variableValue+2*WRVinitialStep>...
rmeddis@0 971 stimulusParameters.WRVlimits(2)
rmeddis@0 972 % use smaller steps when close to maximum
rmeddis@0 973 WRVinitialStep=WRVinitialStep/2;
rmeddis@0 974 end
rmeddis@0 975 newWRVvalue=withinRuns.variableValue+WRVinitialStep;
rmeddis@0 976 end
rmeddis@0 977 otherwise
rmeddis@0 978 error( 'assessment method not recognised')
rmeddis@0 979 end
rmeddis@0 980
rmeddis@0 981 switch experiment.paradigm
rmeddis@0 982 % prevent unrealistic gap durations 'gapDetection' tasks.
rmeddis@0 983 % Note that the gap begins when the ramp ends not when stimulus ends
rmeddis@0 984 case 'gapDetection'
rmeddis@0 985 if newWRVvalue<-2*stimulusParameters.rampDuration
rmeddis@0 986 newWRVvalue=-2*stimulusParameters.rampDuration;
rmeddis@0 987 addToMsg('gap duration fixed at - 2 * ramp!',1, 1)
rmeddis@0 988 end
rmeddis@0 989 end
rmeddis@0 990
rmeddis@0 991 withinRuns.variableValue=newWRVvalue;
rmeddis@0 992 withinRuns.trialNumber=withinRuns.trialNumber+1;
rmeddis@0 993
rmeddis@0 994 % Trial continues
rmeddis@0 995 plotProgressThisTrial(handles)
rmeddis@0 996
rmeddis@0 997 % next stimulus and so the cycle continues
rmeddis@0 998 errormsg=nextStimulus(handles);
rmeddis@0 999 % after the stimulus is presented, control returns here and the system
rmeddis@0 1000 % waits for user action.
rmeddis@0 1001
rmeddis@0 1002 % terminate if there is any kind of problem
rmeddis@0 1003 if ~isempty(errormsg)
rmeddis@0 1004 % e.g. limits exceeded, clipping
rmeddis@0 1005 disp(['Error nextStimulus: ' errormsg])
rmeddis@0 1006 runCompleted(handles)
rmeddis@0 1007 return
rmeddis@0 1008 end
rmeddis@0 1009
rmeddis@0 1010 % ------------------------------------------------ userSelectsPleaseRepeat
rmeddis@0 1011 function userSelectsPleaseRepeat(handles)
rmeddis@0 1012 global experiment withinRuns
rmeddis@0 1013 % ignore click if not 'waitingForResponse'
rmeddis@0 1014 if ~strcmp(experiment.status,'waitingForResponse')
rmeddis@0 1015 disp('ignored click')
rmeddis@0 1016 return
rmeddis@0 1017 end
rmeddis@0 1018 % Take no action other than to make a
rmeddis@0 1019 % tally of repeat requests
rmeddis@0 1020 experiment.pleaseRepeat=experiment.pleaseRepeat+1;
rmeddis@0 1021 withinRuns.thisIsRepeatTrial=1;
rmeddis@0 1022 nextStimulus(handles);
rmeddis@0 1023
rmeddis@0 1024 % ------------------------------------------------ userSelectsWrongButton
rmeddis@0 1025 function userSelectsWrongButton(handles)
rmeddis@0 1026 global withinRuns experiment
rmeddis@0 1027 % restart is the simplest solution for a 'wrong button' request
rmeddis@0 1028 withinRuns.wrongButton=withinRuns.wrongButton+1;
rmeddis@0 1029 set(handles.pushbuttonGO, 'visible','on', 'backgroundcolor','y')
rmeddis@0 1030 msg=[{'Start again: wrong button pressed'}, {' '},...
rmeddis@0 1031 {'Please,click on the GO button'}];
rmeddis@0 1032 set(handles.textMSG,'string',msg)
rmeddis@0 1033 experiment.status='waitingForGO';
rmeddis@0 1034
rmeddis@0 1035 % ------------------------------------------------- plotProgressThisTrial
rmeddis@0 1036 function plotProgressThisTrial(handles)
rmeddis@0 1037
rmeddis@0 1038 % used for all responses
rmeddis@0 1039 global experiment stimulusParameters betweenRuns withinRuns expGUIhandles
rmeddis@0 1040 global psy levelsBinVector binFrequencies rareEvent logistic statsModel
rmeddis@0 1041
rmeddis@0 1042
rmeddis@0 1043 % plot the levelTrack and the threshold track
rmeddis@0 1044
rmeddis@0 1045 % Panel 2
rmeddis@0 1046 % plot the levelList
rmeddis@0 1047 axes(expGUIhandles.axes2); cla
rmeddis@0 1048 plot( withinRuns.levelList,'o','markerFaceColor','k'), hold on
rmeddis@0 1049 % plot the best threshold estimate tracks
rmeddis@0 1050 if length(withinRuns.meanEstTrack)>=1
rmeddis@0 1051 % The length of the levelList is 2 greater than number of thresholds
rmeddis@0 1052 ptr=withinRuns.beginningOfPhase2+1;
rmeddis@0 1053 plot(ptr: ptr+length(withinRuns.meanEstTrack)-1, ...
rmeddis@0 1054 withinRuns.meanEstTrack, 'r')
rmeddis@0 1055 plot( ptr: ptr+length(withinRuns.thresholdEstimateTrack)-1, ...
rmeddis@0 1056 withinRuns.thresholdEstimateTrack, 'g')
rmeddis@0 1057 hold off
rmeddis@0 1058 estThresh=withinRuns.thresholdEstimateTrack(end);
rmeddis@0 1059 switch experiment.threshEstMethod
rmeddis@0 1060 % add appropriate labels to subject GUI buttons
rmeddis@0 1061 case {'2I2AFC++', '2I2AFC+++'}
rmeddis@0 1062 title([stimulusParameters.WRVname ' = ' ...
rmeddis@0 1063 num2str(withinRuns.variableValue, '%5.1f')])
rmeddis@0 1064 otherwise
rmeddis@0 1065 title([stimulusParameters.WRVname ' = ' ...
rmeddis@0 1066 num2str(withinRuns.variableValue, '%5.1f') ...
rmeddis@0 1067 '; TH= ' num2str(estThresh, '%5.1f')])
rmeddis@0 1068 end
rmeddis@0 1069 end
rmeddis@0 1070 xlim([0 experiment.maxTrials+withinRuns.beginningOfPhase2]);
rmeddis@0 1071 ylim(stimulusParameters.WRVlimits)
rmeddis@0 1072 grid on
rmeddis@0 1073
rmeddis@0 1074 % Panel 4: Summary of threshold estimates (not used here)
rmeddis@0 1075 % Earlier estimates are set in 'runCompleted'
rmeddis@0 1076 % However, title shows runs/trials remaining
rmeddis@0 1077
rmeddis@0 1078 axes(expGUIhandles.axes4)
rmeddis@0 1079 runsToGo=length(betweenRuns.var1Sequence)-betweenRuns.runNumber;
rmeddis@0 1080 if withinRuns.beginningOfPhase2>0
rmeddis@0 1081 trialsToGo= experiment.singleIntervalMaxTrials(1) ...
rmeddis@0 1082 + withinRuns.beginningOfPhase2- withinRuns.trialNumber;
rmeddis@0 1083 title(['trials remaining = ' num2str(trialsToGo) ...
rmeddis@0 1084 ': runs to go= ' num2str(runsToGo)])
rmeddis@0 1085 end
rmeddis@0 1086
rmeddis@0 1087 % plot psychometric function - panel 5
rmeddis@0 1088 axes(expGUIhandles.axes5), cla
rmeddis@0 1089 plot(withinRuns.levelList, withinRuns.responseList,'b.'), hold on
rmeddis@0 1090 ylim([0 1])
rmeddis@0 1091 title('')
rmeddis@0 1092
rmeddis@0 1093 switch experiment.threshEstMethod
rmeddis@0 1094 case {'MaxLikelihood', 'oneIntervalUpDown'}
rmeddis@0 1095 if withinRuns.beginningOfPhase2>0
rmeddis@0 1096 % display only when in phase 2.
rmeddis@0 1097 withinRuns.levelsPhaseTwo=...
rmeddis@0 1098 withinRuns.levelList(withinRuns.beginningOfPhase2:end);
rmeddis@0 1099 withinRuns.responsesPhaseTwo=...
rmeddis@0 1100 withinRuns.responseList(withinRuns.beginningOfPhase2:end);
rmeddis@0 1101
rmeddis@0 1102 % organise data as psychometric function
rmeddis@0 1103 [psy, levelsBinVector, binFrequencies]= ...
rmeddis@0 1104 psychometricFunction(withinRuns.levelsPhaseTwo,...
rmeddis@0 1105 withinRuns.responsesPhaseTwo, experiment.psyBinWidth);
rmeddis@0 1106
rmeddis@0 1107 % Plot the function
rmeddis@0 1108 % point by point with circles of appropiate weighted size
rmeddis@0 1109 hold on,
rmeddis@0 1110 for i=1:length(psy)
rmeddis@0 1111 plot(levelsBinVector(i), psy(i), 'ro', ...
rmeddis@0 1112 'markersize', 50*binFrequencies(i)/sum(binFrequencies))
rmeddis@0 1113 end
rmeddis@0 1114 % save info for later
rmeddis@0 1115 betweenRuns.psychometicFunction{betweenRuns.runNumber}=...
rmeddis@0 1116 [levelsBinVector; psy];
rmeddis@0 1117
rmeddis@0 1118 % fitPsychometric functions is computed in 'userDecides'
rmeddis@0 1119 % plot(rareEvent.predictionLevels, rareEvent.predictionsRE,'k')
rmeddis@0 1120 plot(logistic.predictionLevels, logistic.predictionsLOG, 'r')
rmeddis@0 1121 plot(rareEvent.predictionLevels, rareEvent.predictionsRE, 'k')
rmeddis@0 1122 if ~isnan(logistic.bestThreshold )
rmeddis@0 1123 % xlim([ (logistic.bestThreshold -20) ...
rmeddis@0 1124 % (logistic.bestThreshold +20) ])
rmeddis@0 1125 xlim([ 0 100 ])
rmeddis@0 1126 % if logistic.bestK< max(experiment.possLogSlopes)
rmeddis@0 1127 title(['k= ' num2str(logistic.bestK, '%6.2f') ' g= '...
rmeddis@0 1128 num2str(rareEvent.bestGain,'%6.3f') ' A=' ...
rmeddis@0 1129 num2str(rareEvent.bestVMin,'%8.1f')])
rmeddis@0 1130 % title('')
rmeddis@0 1131 % end
rmeddis@0 1132 else
rmeddis@0 1133 title(' ')
rmeddis@0 1134 end
rmeddis@0 1135
rmeddis@0 1136 switch experiment.ear
rmeddis@0 1137 %plot green line for statsModel a priori model
rmeddis@0 1138 case 'statsModelLogistic'
rmeddis@0 1139 % plot proTem logistic (green) used by stats model
rmeddis@0 1140 p= 1./(1+exp(-statsModel.logisticSlope...
rmeddis@0 1141 *(levelsBinVector-logistic.bestThreshold)));
rmeddis@0 1142 if experiment.psyFunSlope<0, p=1-p;end
rmeddis@0 1143 titleText=[ ', statsModel: logistic'];
rmeddis@0 1144 hold on, plot(levelsBinVector, p,'g')
rmeddis@0 1145 case 'statsModelRareEvent'
rmeddis@0 1146 pressure=28*10.^(levelsBinVector/20);
rmeddis@0 1147 p=1-exp(-stimulusParameters.targetDuration...
rmeddis@0 1148 *(statsModel.rareEvenGain...
rmeddis@0 1149 * pressure-statsModel.rareEventVmin));
rmeddis@0 1150 p(p<0)=0;
rmeddis@0 1151 if experiment.psyFunSlope<0, p=1-p;end
rmeddis@0 1152 hold on, plot(levelsBinVector, p,'g')
rmeddis@0 1153 end %(estMethod)
rmeddis@0 1154 end
rmeddis@0 1155 otherwise % 2A2IFC
rmeddis@0 1156
rmeddis@0 1157 message3= ...
rmeddis@0 1158 ([ 'peaks=' num2str(withinRuns.peaks) ...
rmeddis@0 1159 'troughs=' num2str(withinRuns.troughs)]);
rmeddis@0 1160 ylimRM([-0.1 1.1]) % 0=no / 1=yes
rmeddis@0 1161 set(gca,'ytick',[0 1], 'yTickLabel', {'no';'yes'})
rmeddis@0 1162 ylabel('psychometric function'), xlabel('target level')
rmeddis@0 1163 if length(levelsBinVector)>1
rmeddis@0 1164 xlim([ min(levelsBinVector) max(levelsBinVector)])
rmeddis@0 1165 xlim([ 0 100])
rmeddis@0 1166 end
rmeddis@0 1167 end
rmeddis@0 1168
rmeddis@0 1169 % command window summary
rmeddis@0 1170 % Accumulate things to say in the message window
rmeddis@0 1171 message1= (['responses: ' num2str(withinRuns.responseList,'%9.0f')]);
rmeddis@0 1172 switch experiment.paradigm
rmeddis@0 1173 % more decimal places needed on GUI
rmeddis@0 1174 case { 'gapDetection', 'frequencyDiscrimination', 'forwardMaskingD'}
rmeddis@0 1175 message2= ([stimulusParameters.WRVname ...
rmeddis@0 1176 ': ' num2str(withinRuns.levelList,'%7.3f')]);
rmeddis@0 1177 message3= (['Thresh (logistic mean): ' ...
rmeddis@0 1178 num2str(withinRuns.thresholdEstimateTrack,'%7.3f')]);
rmeddis@0 1179 otherwise
rmeddis@0 1180 message2= ([stimulusParameters.WRVname ': ' ...
rmeddis@0 1181 num2str(withinRuns.levelList,'%7.1f')]);
rmeddis@0 1182 message3= (['Thresh (logistic mean): ' ...
rmeddis@0 1183 num2str(withinRuns.thresholdEstimateTrack,'%7.1f')]);
rmeddis@0 1184 end
rmeddis@0 1185
rmeddis@0 1186 addToMsg(str2mat(message1, message2, message3), 0)
rmeddis@0 1187
rmeddis@0 1188 % -----------------------------------------------------runCompleted
rmeddis@0 1189 function runCompleted(handles)
rmeddis@0 1190 % Used at the end of each run
rmeddis@0 1191 global experiment stimulusParameters betweenRuns withinRuns
rmeddis@0 1192 global rareEvent expGUIhandles
rmeddis@0 1193 % disp('run completed')
rmeddis@0 1194
rmeddis@0 1195 experiment.status='runCompleted';
rmeddis@0 1196
rmeddis@0 1197 plotProgressThisTrial(handles)
rmeddis@0 1198
rmeddis@0 1199 switch experiment.ear
rmeddis@0 1200 case {'statsModelLogistic', 'statsModelRareEvent','MAPmodel', ...
rmeddis@0 1201 'MAPmodelMultiCh','MAPmodelSingleCh', 'MAPmodelListen'}
rmeddis@0 1202 % no changes required if model used
rmeddis@0 1203 otherwise
rmeddis@0 1204 set(handles.frame1,'visible','off')
rmeddis@0 1205 set(handles.pushbuttoNotSure,'visible','off')
rmeddis@0 1206 set(handles.pushbuttonWrongButton,'visible','off')
rmeddis@0 1207 set(handles.pushbutton3,'visible','off')
rmeddis@0 1208 set(handles.pushbutton2,'visible','off')
rmeddis@0 1209 set(handles.pushbutton1,'visible','off')
rmeddis@0 1210 set(handles.pushbutton0,'visible','off')
rmeddis@0 1211 set(handles.pushbuttonGO,'visible','off')
rmeddis@0 1212 end
rmeddis@0 1213
rmeddis@0 1214 if isnan(withinRuns.forceThreshold)
rmeddis@0 1215 % the experiment has been aborted for some reason
rmeddis@0 1216 threshold=withinRuns.forceThreshold;
rmeddis@0 1217 stdev=NaN;
rmeddis@0 1218 logistic.bestK=NaN;
rmeddis@0 1219 logistic.bestThreshold=NaN;
rmeddis@0 1220 medianThreshold=NaN;
rmeddis@0 1221 meanThreshold=NaN;
rmeddis@0 1222 else
rmeddis@0 1223 % use only phase 2 levels and responses for calculating thresholds
rmeddis@0 1224 withinRuns.levelsPhaseTwo=...
rmeddis@0 1225 withinRuns.levelList(withinRuns.beginningOfPhase2:end);
rmeddis@0 1226 withinRuns.responsesPhaseTwo=...
rmeddis@0 1227 withinRuns.responseList(withinRuns.beginningOfPhase2:end);
rmeddis@0 1228 [psy, levelsPhaseTwoBinVector, logistic, rareEvent]= ...
rmeddis@0 1229 bestFitPsychometicFunctions...
rmeddis@0 1230 (withinRuns.levelsPhaseTwo, withinRuns.responsesPhaseTwo);
rmeddis@0 1231
rmeddis@0 1232 % plot final psychometric function
rmeddis@0 1233 axes(expGUIhandles.axes5),cla
rmeddis@0 1234 hold on, plot(rareEvent.predictionLevels, rareEvent.predictionsRE, 'k')
rmeddis@0 1235 hold on, plot(logistic.predictionLevels, logistic.predictionsLOG, 'r')
rmeddis@0 1236 % organise data as psychometric function
rmeddis@0 1237 [psy, levelsBinVector, binFrequencies]= ...
rmeddis@0 1238 psychometricFunction(withinRuns.levelsPhaseTwo,...
rmeddis@0 1239 withinRuns.responsesPhaseTwo, experiment.psyBinWidth);
rmeddis@0 1240 % point by point with circles of appropiate weighted size
rmeddis@0 1241 hold on,
rmeddis@0 1242 for i=1:length(psy)
rmeddis@0 1243 plot(levelsBinVector(i), psy(i), 'ro', ...
rmeddis@0 1244 'markersize', 50*binFrequencies(i)/sum(binFrequencies))
rmeddis@0 1245 end
rmeddis@0 1246
rmeddis@0 1247
rmeddis@0 1248 % experimental
rmeddis@0 1249 medianThreshold=median(withinRuns.levelsPhaseTwo);
rmeddis@0 1250 warning off
rmeddis@0 1251 meanThreshold=mean(withinRuns.levelsPhaseTwo);
rmeddis@0 1252
rmeddis@0 1253 % identify the current threshold estimate
rmeddis@0 1254 switch experiment.paradigm
rmeddis@0 1255 case 'discomfort'
rmeddis@0 1256 % most recent value (not truely a mean value)
rmeddis@0 1257 threshold=withinRuns.levelList(end);
rmeddis@0 1258 stdev=NaN;
rmeddis@0 1259 otherwise
rmeddis@0 1260 switch experiment.threshEstMethod
rmeddis@0 1261 case {'MaxLikelihood', 'oneIntervalUpDown'}
rmeddis@0 1262 % last value in the list
rmeddis@0 1263 threshold=withinRuns.meanEstTrack(end);
rmeddis@0 1264 threshold=withinRuns.thresholdEstimateTrack(end);
rmeddis@0 1265 stdev=NaN;
rmeddis@0 1266
rmeddis@0 1267 case {'2I2AFC++', '2I2AFC+++'}
rmeddis@0 1268 % use peaks and troughs
rmeddis@0 1269 try % there may not be enough values to use
rmeddis@0 1270 peaksUsed=experiment.peaksUsed;
rmeddis@0 1271 threshold=...
rmeddis@0 1272 mean(...
rmeddis@0 1273 [withinRuns.peaks(end-peaksUsed+1:end) ...
rmeddis@0 1274 withinRuns.troughs(end-peaksUsed+1:end)]);
rmeddis@0 1275 stdev=...
rmeddis@0 1276 std([withinRuns.peaks(end-peaksUsed +1:end) ...
rmeddis@0 1277 withinRuns.troughs(end-peaksUsed:end)]);
rmeddis@0 1278 catch
rmeddis@0 1279 threshold=NaN;
rmeddis@0 1280 stdev=NaN;
rmeddis@0 1281 end
rmeddis@0 1282 end
rmeddis@0 1283 end
rmeddis@0 1284 end
rmeddis@0 1285
rmeddis@0 1286 % Store thresholds
rmeddis@0 1287 betweenRuns.thresholds=[betweenRuns.thresholds threshold];
rmeddis@0 1288 betweenRuns.thresholds_mean=[betweenRuns.thresholds_mean meanThreshold];
rmeddis@0 1289 betweenRuns.thresholds_median=...
rmeddis@0 1290 [betweenRuns.thresholds_median medianThreshold];
rmeddis@0 1291 betweenRuns.forceThresholds=...
rmeddis@0 1292 [betweenRuns.forceThresholds withinRuns.forceThreshold];
rmeddis@0 1293
rmeddis@0 1294 % count observations after the startup phase for record keeping
rmeddis@0 1295 betweenRuns.observationCount=...
rmeddis@0 1296 [betweenRuns.observationCount length(withinRuns.levelList)];
rmeddis@0 1297 betweenRuns.timesOfFirstReversals=...
rmeddis@0 1298 [betweenRuns.timesOfFirstReversals withinRuns.beginningOfPhase2];
rmeddis@0 1299 betweenRuns.catchTrials=...
rmeddis@0 1300 [betweenRuns.catchTrials withinRuns.catchTrialCount];
rmeddis@0 1301
rmeddis@0 1302 % add variable length tracks to cell arrays
rmeddis@0 1303 if withinRuns.beginningOfPhase2>0
rmeddis@0 1304 betweenRuns.bestThresholdTracks{length(betweenRuns.thresholds)}=...
rmeddis@0 1305 withinRuns.thresholdEstimateTrack;
rmeddis@0 1306 betweenRuns.bestThresholdMeanTracks...
rmeddis@0 1307 {length(betweenRuns.thresholds_mean)}=...
rmeddis@0 1308 withinRuns.thresholdEstimateTrack;
rmeddis@0 1309 betweenRuns.bestThresholdMedianTracks...
rmeddis@0 1310 {length(betweenRuns.thresholds_median)}=...
rmeddis@0 1311 withinRuns.thresholdEstimateTrack;
rmeddis@0 1312
rmeddis@0 1313 betweenRuns.levelTracks{length(betweenRuns.thresholds)}=...
rmeddis@0 1314 withinRuns.levelList(withinRuns.beginningOfPhase2:end);
rmeddis@0 1315 betweenRuns.responseTracks{length(betweenRuns.thresholds)}=...
rmeddis@0 1316 withinRuns.responseList(withinRuns.beginningOfPhase2:end);
rmeddis@0 1317 else
rmeddis@0 1318 betweenRuns.bestThresholdTracks{length(betweenRuns.thresholds)}=[];
rmeddis@0 1319 betweenRuns.bestThresholdMeanTracks{length(betweenRuns.thresholds)}=[];
rmeddis@0 1320 betweenRuns.bestThresholdMedianTracks{length(betweenRuns.thresholds)}=...
rmeddis@0 1321 [];
rmeddis@0 1322 betweenRuns.levelTracks{length(betweenRuns.thresholds)}=[];
rmeddis@0 1323 betweenRuns.responseTracks{length(betweenRuns.thresholds)}=[];
rmeddis@0 1324 end
rmeddis@0 1325
rmeddis@0 1326 betweenRuns.bestGain=[betweenRuns.bestGain rareEvent.bestGain];
rmeddis@0 1327 betweenRuns.bestVMin=[betweenRuns.bestVMin rareEvent.bestVMin];
rmeddis@0 1328 betweenRuns.bestPaMin=[betweenRuns.bestPaMin rareEvent.bestPaMindB];
rmeddis@0 1329 betweenRuns.bestLogisticM=...
rmeddis@0 1330 [betweenRuns.bestLogisticM logistic.bestThreshold];
rmeddis@0 1331 betweenRuns.bestLogisticK=[betweenRuns.bestLogisticK logistic.bestK];
rmeddis@0 1332
rmeddis@0 1333 resultsSoFar=[betweenRuns.var1Sequence(betweenRuns.runNumber)'...
rmeddis@0 1334 betweenRuns.var2Sequence(betweenRuns.runNumber)'...
rmeddis@0 1335 betweenRuns.thresholds(betweenRuns.runNumber)'
rmeddis@0 1336 ];
rmeddis@0 1337
rmeddis@0 1338 fprintf('%10.3f \t%10.3f \t%10.1f \n', resultsSoFar')
rmeddis@0 1339
rmeddis@0 1340 switch experiment.ear
rmeddis@0 1341 case {'left', 'right', 'diotic', 'dichoticLeft','dichoticRight'}
rmeddis@0 1342 disp(['caught out= ' num2str(betweenRuns.caughtOut)])
rmeddis@0 1343 end
rmeddis@0 1344
rmeddis@0 1345 % plot history of thresholds in panel 4
rmeddis@0 1346 axes(expGUIhandles.axes4), cla
rmeddis@0 1347 plotColors='rgbmckywrgbmckyw';
rmeddis@0 1348 for i=1:length(betweenRuns.thresholds)
rmeddis@0 1349 faceColor=plotColors(floor(i/length(betweenRuns.variableList1)-.01)+1);
rmeddis@0 1350 switch betweenRuns.variableName1
rmeddis@0 1351 case {'targetFrequency', 'maskerRelativeFrequency'}
rmeddis@0 1352 if min(betweenRuns.var1Sequence)>0
rmeddis@0 1353 % semilogx(betweenRuns.var1Sequence(1:betweenRuns.runNumber), ...
rmeddis@0 1354 % betweenRuns.thresholds, 'o', ...
rmeddis@0 1355 % 'markerSize', 5,'markerFaceColor',faceColor)
rmeddis@0 1356 semilogx(betweenRuns.var1Sequence(i), ...
rmeddis@0 1357 betweenRuns.thresholds(i), 'o', ...
rmeddis@0 1358 'markerSize', 5,'markerFaceColor',faceColor)
rmeddis@0 1359 else
rmeddis@0 1360 plot(betweenRuns.var1Sequence(1:betweenRuns.runNumber), ...
rmeddis@0 1361 betweenRuns.thresholds, 'o', ...
rmeddis@0 1362 'markerSize', 5,'markerFaceColor',faceColor)
rmeddis@0 1363 plot(betweenRuns.var1Sequence(i), ...
rmeddis@0 1364 betweenRuns.thresholds(i), 'o', ...
rmeddis@0 1365 'markerSize', 5,'markerFaceColor',faceColor)
rmeddis@0 1366 end
rmeddis@0 1367 otherwise
rmeddis@0 1368 % plot(betweenRuns.var1Sequence(1:betweenRuns.runNumber), ...
rmeddis@0 1369 % betweenRuns.thresholds, 'o', 'markerSize', 5,...
rmeddis@0 1370 % 'markerFaceColor',faceColor)
rmeddis@0 1371 plot(betweenRuns.var1Sequence(i), ...
rmeddis@0 1372 betweenRuns.thresholds(i), 'o', 'markerSize', 5,...
rmeddis@0 1373 'markerFaceColor',faceColor)
rmeddis@0 1374 end
rmeddis@0 1375 hold on
rmeddis@0 1376 end
rmeddis@0 1377 xlimRM([ min(betweenRuns.variableList1) max(betweenRuns.variableList1) ])
rmeddis@0 1378 ylim(stimulusParameters.WRVlimits)
rmeddis@0 1379 ylabel('thresholds')
rmeddis@0 1380 xlabel(betweenRuns.variableName1)
rmeddis@0 1381 set(gca,'ytick', [0 20 40 60 80 100])
rmeddis@0 1382 try
rmeddis@0 1383 % problems if only one x value
rmeddis@0 1384 set(gca,'XTick', sort(betweenRuns.variableList1))
rmeddis@0 1385 catch
rmeddis@0 1386 end
rmeddis@0 1387 grid on, set(gca,'XMinorGrid', 'off')
rmeddis@0 1388
rmeddis@0 1389 % If comparison data is available in pearmeter file, plot it now
rmeddis@0 1390 if ~isempty (experiment.comparisonData)
rmeddis@0 1391 comparisonData=experiment.comparisonData(:,1:end-1); % ignore final BF
rmeddis@0 1392 [x, ncols]=size(comparisonData);
rmeddis@0 1393 if length(betweenRuns.variableList1)==ncols
rmeddis@0 1394 hold on
rmeddis@0 1395 plot (sort(betweenRuns.variableList1), comparisonData, 'r')
rmeddis@0 1396 hold off
rmeddis@0 1397 end
rmeddis@0 1398 end
rmeddis@0 1399
rmeddis@0 1400 % End of the Experiment also?
rmeddis@0 1401 if betweenRuns.runNumber==length(betweenRuns.var1Sequence)
rmeddis@0 1402 % yes, end of experiment
rmeddis@0 1403 fileName=['savedData/' experiment.name experiment.date ...
rmeddis@0 1404 experiment.paradigm];
rmeddis@0 1405 % save (fileName, 'experiment', 'stimulusParameters', 'betweenRuns', 'withinRuns', 'variableNames', 'paradigmNames', 'LevittControl')
rmeddis@0 1406 disp('Experiment completed')
rmeddis@0 1407
rmeddis@0 1408 % update subject GUI to acknowledge end of run
rmeddis@0 1409 subjGUImsg=[{'Experiment completed'}, {' '}, {'Thank you!'}];
rmeddis@0 1410 set(handles.textMSG,'string', subjGUImsg )
rmeddis@0 1411 % play 'Tada'
rmeddis@0 1412 [y,fs,nbits]=wavread('TADA.wav');
rmeddis@0 1413 musicGain=10^(stimulusParameters.musicLeveldB/20);
rmeddis@0 1414 y=y*musicGain;
rmeddis@0 1415 wavplay(y/100,fs, 'async')
rmeddis@0 1416
rmeddis@0 1417 % update experimenter GUI
rmeddis@0 1418 addToMsg('Experiment completed.',1)
rmeddis@0 1419
rmeddis@0 1420 printReport
rmeddis@0 1421 experiment.status='endOfExperiment';
rmeddis@0 1422 return
rmeddis@0 1423 else
rmeddis@0 1424 % No, hang on.
rmeddis@0 1425 switch experiment.ear
rmeddis@0 1426 case {'statsModelLogistic', 'statsModelRareEvent','MAPmodel', ...
rmeddis@0 1427 'MAPmodelMultiCh','MAPmodelSingleCh', 'MAPmodelListen'}
rmeddis@0 1428 % no changes required if model used
rmeddis@0 1429 otherwise
rmeddis@0 1430 % decrement catchTrialRate towards baseRate
rmeddis@0 1431 stimulusParameters.catchTrialRate=...
rmeddis@0 1432 stimulusParameters.catchTrialBaseRate + ...
rmeddis@0 1433 (stimulusParameters.catchTrialRate...
rmeddis@0 1434 -stimulusParameters.catchTrialBaseRate)...
rmeddis@0 1435 *(1-exp(-stimulusParameters.catchTrialTimeConstant));
rmeddis@0 1436 fprintf('stimulusParameters.catchTrialRate= %6.3f\n', ...
rmeddis@0 1437 stimulusParameters.catchTrialRate)
rmeddis@0 1438
rmeddis@0 1439 % and go again
rmeddis@0 1440 set(handles.pushbuttonGO,'backgroundcolor','y')
rmeddis@0 1441 set(handles.frame1,'visible','off')
rmeddis@0 1442 set(handles.pushbuttonGO,'visible','on')
rmeddis@0 1443 msg=[{'Ready to start new trial'}, {' '},...
rmeddis@0 1444 {'Please,click on the GO button'}];
rmeddis@0 1445 set(handles.textMSG,'string',msg)
rmeddis@0 1446 end
rmeddis@0 1447 experiment.status='waitingForGO';
rmeddis@0 1448 % fprintf('\n')
rmeddis@0 1449
rmeddis@0 1450 [y,fs,nbits]=wavread('CHIMES.wav');
rmeddis@0 1451 musicGain=10^(stimulusParameters.musicLeveldB/20);
rmeddis@0 1452 y=y*musicGain;
rmeddis@0 1453 wavplay(y/100,fs,'async')
rmeddis@0 1454 end
rmeddis@0 1455
rmeddis@0 1456 % -----------------------------------------------------MAPmodelRunsGUI
rmeddis@0 1457 % The computer presses the buttons
rmeddis@0 1458 function MAPmodelRunsGUI(handles)
rmeddis@0 1459 global experiment stimulusParameters method expGUIhandles
rmeddis@0 1460 global AN_IHCsynapseParams
rmeddis@0 1461 method=[];
rmeddis@0 1462
rmeddis@0 1463 while strcmp(experiment.status,'waitingForGO')
rmeddis@0 1464 % no catch trials for MAP model
rmeddis@0 1465 experiment.allowCatchTrials=0;
rmeddis@0 1466
rmeddis@0 1467 % initiates run and plays first stimulus and it returns
rmeddis@0 1468 % without waiting for button press
rmeddis@0 1469 startNewRun(handles)
rmeddis@0 1470
rmeddis@0 1471 if sum(strcmp(experiment.ear,...
rmeddis@0 1472 {'MAPmodelMultiCh', 'MAPmodelListen'}))
rmeddis@0 1473 % use BFlist specified in MAPparams file
rmeddis@0 1474 BFlist= -1;
rmeddis@0 1475 else
rmeddis@0 1476 BFlist=stimulusParameters.targetFrequency;
rmeddis@0 1477 end
rmeddis@0 1478 showParams=0;
rmeddis@0 1479 % find model parameters using the 'name' box (e.g. CTa ->MAPparamsCTa)
rmeddis@0 1480 paramFunctionName=['method=MAPparams' experiment.name ...
rmeddis@0 1481 '(BFlist, stimulusParameters.sampleRate, showParams);'];
rmeddis@0 1482 eval(paramFunctionName) % go and fetch the parameters
rmeddis@0 1483
rmeddis@0 1484
rmeddis@0 1485 % show sample Rate on GUI; it must be set in MAPparams
rmeddis@0 1486 set(expGUIhandles.textsampleRate,'string',...
rmeddis@0 1487 num2str(stimulusParameters.sampleRate))
rmeddis@0 1488
rmeddis@0 1489 if experiment.singleShot
rmeddis@0 1490 % AN_IHCsynapseParams.showSummaryStatistics=1;
rmeddis@0 1491 method.showSummaryStatistics=1;
rmeddis@0 1492 AN_IHCsynapseParams.plotSynapseContents=1;
rmeddis@0 1493 else
rmeddis@0 1494 method.showSummaryStatistics=0;
rmeddis@0 1495 AN_IHCsynapseParams.plotSynapseContents=0;
rmeddis@0 1496 end
rmeddis@0 1497
rmeddis@0 1498 if strcmp(experiment.ear, 'MAPmodelSingleCh')
rmeddis@0 1499 method.MGmembranePotentialSave=1;
rmeddis@0 1500 end
rmeddis@0 1501
rmeddis@0 1502 % continuous loop until the program stops itself
rmeddis@0 1503 while strcmp(experiment.status,'waitingForResponse')
rmeddis@0 1504 % NB at this point the stimulus has been played
rmeddis@0 1505 pause(0.1) % to allow interrupt with CTRL/C
rmeddis@0 1506
rmeddis@0 1507 switch experiment.ear
rmeddis@0 1508 case { 'MAPmodelListen'}
rmeddis@0 1509 set(handles.pushbutton1,'backgroundcolor','y','visible','on')
rmeddis@0 1510 set(handles.pushbutton2,'backgroundcolor','y','visible','on')
rmeddis@0 1511 end
rmeddis@0 1512
rmeddis@0 1513 AN_IHCsynapseParams.mode= 'spikes';
rmeddis@0 1514
rmeddis@0 1515 % Analayse the current stimulus using MAP
rmeddis@0 1516 [modelResponse earObject]= MAPmodel( experiment.MAPplot, method);
rmeddis@0 1517
rmeddis@0 1518 if experiment.stop || experiment.singleShot
rmeddis@0 1519 % trap for single trial or user interrupt using 'stop' button.
rmeddis@0 1520 experiment.status= 'waitingForStart';
rmeddis@0 1521 experiment.stop=0;
rmeddis@0 1522 addToMsg('manually stopped',1);
rmeddis@0 1523 return
rmeddis@0 1524 end
rmeddis@0 1525
rmeddis@0 1526 switch modelResponse
rmeddis@0 1527 case 1
rmeddis@0 1528 % userDoesNotHearTarget(handles)
rmeddis@0 1529 switch experiment.ear
rmeddis@0 1530 case {'MAPmodelListen'}
rmeddis@0 1531 % illuminate appropriate button
rmeddis@0 1532 set(handles.pushbutton1,...
rmeddis@0 1533 'backgroundcolor','r','visible','on')
rmeddis@0 1534 set(handles.pushbutton2,'backgroundcolor','y')
rmeddis@0 1535 end
rmeddis@0 1536 userDecides(handles, false)
rmeddis@0 1537 if experiment.singleShot, return, end
rmeddis@0 1538
rmeddis@0 1539 case 2
rmeddis@0 1540 % userHearsTarget(handles)
rmeddis@0 1541 switch experiment.ear
rmeddis@0 1542 case {'MAPmodelListen'}
rmeddis@0 1543 % illuminate appropriate button (DEMO only)
rmeddis@0 1544 set(handles.pushbutton2,'backgroundcolor',...
rmeddis@0 1545 'r','visible','on')
rmeddis@0 1546 set(handles.pushbutton1,'backgroundcolor','y')
rmeddis@0 1547 end
rmeddis@0 1548
rmeddis@0 1549 switch experiment.paradigm
rmeddis@0 1550 case 'discomfort'
rmeddis@0 1551 % always treat discomfort as 'not heard'
rmeddis@0 1552 userDecides(handles, false)
rmeddis@0 1553 otherwise
rmeddis@0 1554 userDecides(handles, true)
rmeddis@0 1555 end
rmeddis@0 1556 otherwise
rmeddis@0 1557 % probably an abort
rmeddis@0 1558 return
rmeddis@0 1559 end
rmeddis@0 1560 end
rmeddis@0 1561 end
rmeddis@0 1562
rmeddis@0 1563
rmeddis@0 1564 % -----------------------------------------------------statsModelRunsGUI
rmeddis@0 1565 % The computer presses the buttons
rmeddis@0 1566 function statsModelRunsGUI(handles)
rmeddis@0 1567 % Decision are made at random using a prescribe statistical function
rmeddis@0 1568 % to set probabilities as a function of signal level.
rmeddis@0 1569 global experiment
rmeddis@0 1570
rmeddis@0 1571 experiment.allowCatchTrials=0;
rmeddis@0 1572
rmeddis@0 1573 while strcmp(experiment.status,'waitingForGO')
rmeddis@0 1574 % i.e. waiting for new run
rmeddis@0 1575 if experiment.stop
rmeddis@0 1576 % user has requested an abort
rmeddis@0 1577 experiment.status= 'waitingForStart';
rmeddis@0 1578 addToMsg('manually stopped',1)
rmeddis@0 1579 return
rmeddis@0 1580 end
rmeddis@0 1581
rmeddis@0 1582 % initiates run and plays first stimulus and it returns
rmeddis@0 1583 % without waiting for button press
rmeddis@0 1584 % NB stimulus is not actually generated (for speed)
rmeddis@0 1585 startNewRun(handles)
rmeddis@0 1586
rmeddis@0 1587 while strcmp(experiment.status,'waitingForResponse')
rmeddis@0 1588 % create artificial response here
rmeddis@0 1589 modelResponse=statsModelGetResponse;
rmeddis@0 1590 switch modelResponse
rmeddis@0 1591 case 1
rmeddis@0 1592 % userDoesNotHearTarget(handles)
rmeddis@0 1593 userDecides(handles, false)
rmeddis@0 1594 case 2
rmeddis@0 1595 % userHearsTarget(handles)
rmeddis@0 1596 userDecides(handles, true)
rmeddis@0 1597 end
rmeddis@0 1598 end
rmeddis@0 1599 end
rmeddis@0 1600
rmeddis@0 1601 % -----------------------------------------------------statsModelGetResponse
rmeddis@0 1602 function modelResponse=statsModelGetResponse(handles)
rmeddis@0 1603 global experiment withinRuns statsModel stimulusParameters
rmeddis@0 1604 % use the generating function to decide if a detection occurs or not
rmeddis@0 1605
rmeddis@0 1606 % pause(0.1) % to allow stopping with CTRL/C but slows things down
rmeddis@0 1607
rmeddis@0 1608 % first compute the probability that a detection occurs
rmeddis@0 1609 switch experiment.ear
rmeddis@0 1610 case {'statsModelLogistic'}
rmeddis@0 1611 prob= 1./(1+exp(-statsModel.logisticSlope.*(withinRuns.variableValue-statsModel.logisticMean)));
rmeddis@0 1612 % if experiment.psyFunSlope<0,
rmeddis@0 1613 % prob=1-prob;
rmeddis@0 1614 % end
rmeddis@0 1615
rmeddis@0 1616 case 'statsModelRareEvent'
rmeddis@0 1617 if experiment.psyFunSlope<0
rmeddis@0 1618 addToMsg('statsModelRareEvent cannot be used with negative slope',0)
rmeddis@0 1619 error('statsModelRareEvent cannot be used with negative slope')
rmeddis@0 1620 end
rmeddis@0 1621
rmeddis@0 1622 % standard formula is prob = 1 – exp(-d (g P – A))
rmeddis@0 1623 % here A->A; To find Pmin use A/gain
rmeddis@0 1624 pressure=28*10^(withinRuns.variableValue/20);
rmeddis@0 1625 gain=statsModel.rareEvenGain;
rmeddis@0 1626 A=statsModel.rareEventVmin;
rmeddis@0 1627 d=stimulusParameters.targetDuration;
rmeddis@0 1628 gP_Vmin=gain*pressure-A;
rmeddis@0 1629 if gP_Vmin>0
rmeddis@0 1630 prob=1-exp(-d*(gP_Vmin));
rmeddis@0 1631 else
rmeddis@0 1632 prob=0;
rmeddis@0 1633 end
rmeddis@0 1634 end
rmeddis@0 1635
rmeddis@0 1636 % Use the probability to choose whether or not a detection has occurred
rmeddis@0 1637 switch experiment.threshEstMethod
rmeddis@0 1638 case {'MaxLikelihood', 'oneIntervalUpDown'}
rmeddis@0 1639 if rand<prob
rmeddis@0 1640 modelResponse=2; %bingo
rmeddis@0 1641 else
rmeddis@0 1642 modelResponse=1; %nothing heard
rmeddis@0 1643 end
rmeddis@0 1644
rmeddis@0 1645 case {'2I2AFC++', '2I2AFC+++'}
rmeddis@0 1646 if rand<prob
rmeddis@0 1647 modelResponse=2; %bingo
rmeddis@0 1648 else %if the stimulus is not audible, take a 50:50 chance of getting it right
rmeddis@0 1649 if rand<0.5
rmeddis@0 1650 modelResponse=2; %bingo
rmeddis@0 1651 else
rmeddis@0 1652 modelResponse=1; %nothing heard
rmeddis@0 1653 end
rmeddis@0 1654 end
rmeddis@0 1655 end
rmeddis@0 1656
rmeddis@0 1657
rmeddis@0 1658 % ------------------------------------------------------- printTabTable
rmeddis@0 1659 function printTabTable(M, headers)
rmeddis@0 1660 % printTabTable prints a matrix as a table with tabs
rmeddis@0 1661 %headers are optional
rmeddis@0 1662 %headers=strvcat('firstname', 'secondname')
rmeddis@0 1663 % printTabTable([1 2; 3 4],strvcat('a1','a2'));
rmeddis@0 1664
rmeddis@0 1665 if nargin>1
rmeddis@0 1666 [r c]=size(headers);
rmeddis@0 1667 for no=1:r
rmeddis@0 1668 fprintf('%s\t',headers(no,:))
rmeddis@0 1669 end
rmeddis@0 1670 fprintf('\n')
rmeddis@0 1671 end
rmeddis@0 1672
rmeddis@0 1673 [r c]=size(M);
rmeddis@0 1674
rmeddis@0 1675 for row=1:r
rmeddis@0 1676 for col=1:c
rmeddis@0 1677 if row==1 && col==1 && M(1,1)==-1000
rmeddis@0 1678 % Print nothing (tab follows below)
rmeddis@0 1679 else
rmeddis@0 1680 fprintf('%s',num2str(M(row,col)))
rmeddis@0 1681 end
rmeddis@0 1682 if col<c
rmeddis@0 1683 fprintf('\t')
rmeddis@0 1684 end
rmeddis@0 1685 end
rmeddis@0 1686 fprintf('\n')
rmeddis@0 1687 end
rmeddis@0 1688
rmeddis@0 1689 % ------------------------------------------------------- xlimRM
rmeddis@0 1690 function xlimRM(x)
rmeddis@0 1691 try
rmeddis@0 1692 xlim([x(1) x(2)])
rmeddis@0 1693 catch
rmeddis@0 1694 end
rmeddis@0 1695
rmeddis@0 1696 % ------------------------------------------------------- ylimRM
rmeddis@0 1697 function ylimRM(x)
rmeddis@0 1698 try
rmeddis@0 1699 ylim([x(1) x(2)])
rmeddis@0 1700 catch
rmeddis@0 1701 end
rmeddis@0 1702
rmeddis@0 1703
rmeddis@0 1704 function editdigitInput_CreateFcn(hObject, eventdata, handles)
rmeddis@0 1705
rmeddis@0 1706 % Hint: edit controls usually have a white background on Windows.
rmeddis@0 1707 % See ISPC and COMPUTER.
rmeddis@0 1708 if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
rmeddis@0 1709 set(hObject,'BackgroundColor','white');
rmeddis@0 1710 end
rmeddis@0 1711
rmeddis@0 1712
rmeddis@0 1713 % -----------------------------------------------------buttonBoxIntitialize
rmeddis@0 1714 function buttonBoxIntitialize
rmeddis@0 1715 % initialize button box
rmeddis@0 1716 global serobj
rmeddis@0 1717 try
rmeddis@0 1718 fclose(serobj);
rmeddis@0 1719 catch
rmeddis@0 1720 end
rmeddis@0 1721
rmeddis@0 1722 try
rmeddis@0 1723 serobj = serial('COM4') ; % Creating serial port object now its connected to COM4 !!! button boxes in booths are connected to COM2
rmeddis@0 1724 serobj.Baudrate = 9600; % Set the baud rate at the specific value
rmeddis@0 1725 set(serobj, 'Parity', 'none') ; % Set parity as none
rmeddis@0 1726 set(serobj, 'Databits', 8) ; % set the number of data bits
rmeddis@0 1727 set(serobj, 'StopBits', 1) ; % set number of stop bits as 1
rmeddis@0 1728 set(serobj, 'Terminator', 'CR') ; % set the terminator value to carriage return
rmeddis@0 1729 set(serobj, 'InputBufferSize', 512) ; % Buffer for read operation, default it is 512
rmeddis@0 1730 set(serobj,'timeout',10); % 10 sec timeout on button press
rmeddis@0 1731 set(serobj, 'ReadAsyncMode', 'continuous')
rmeddis@0 1732 set(serobj, 'BytesAvailableFcn', @buttonBox_callback)
rmeddis@0 1733 set(serobj, 'BytesAvailableFcnCount', 1)
rmeddis@0 1734 set(serobj, 'BytesAvailableFcnMode', 'byte')
rmeddis@0 1735 % set(serobj, 'BreakInterruptFcn', '@buttonBox_Calback')
rmeddis@0 1736
rmeddis@0 1737 fopen(serobj);
rmeddis@0 1738 buttonBoxStatus=get(serobj,'status');
rmeddis@0 1739 catch
rmeddis@0 1740 disp('** no button box found - use mouse **')
rmeddis@0 1741 end