Mercurial > hg > map
diff Copy_of_multithreshold 1.46/Levitt2.m @ 28:02aa9826efe0
mainly multiThreshold
author | Ray Meddis <rmeddis@essex.ac.uk> |
---|---|
date | Fri, 01 Jul 2011 12:59:47 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Copy_of_multithreshold 1.46/Levitt2.m Fri Jul 01 12:59:47 2011 +0100 @@ -0,0 +1,145 @@ +function [nextStep, msg]=Levitt2 (decision, currentValue) +global LevittControl withinRuns +% descision is a string: 'hit' or 'miss' +% current value is the value of the variable parameter (e.g. level) +% msg: +% msg='' indicates trial progressing successfully +% msg='done' indicates that a threshold estimate has been found +% msg='maximum level exceeded' +% msg='maximum no of trials exceeded' + +% Initialize by running Levitt2 without arguments +% later LevittControl will be set in aReadAndCheckParameterBoxes in expGUI_MT +if nargin==0 + + LevittControl.peakTroughValues=[]; + LevittControl.trialRunning=0; + LevittControl.sequence='****'; + LevittControl.LevittValuesUsed=[NaN NaN NaN NaN]; + LevittControl.TurnsToSmallSteps=4; % 2 peaks and 2 troughs + LevittControl.direction='same'; + LevittControl.prevDirection='easier'; + LevittControl.Nreversals=0; + + LevittControl.trialRunning=1; + LevittControl.meanPeakTrough=NaN; + LevittControl.sd=NaN; + msg=''; + return +end + +% apply Levitt rules to find next stimulus value +rule=LevittControl.rule; +sequence=LevittControl.sequence; +meanPT=LevittControl.meanPeakTrough; +sdPT=LevittControl.sd; + +% response sequence: '+' is a hit and '-' is a miss. +if strcmp(decision,'hit') + sequence=[sequence '+']; +else + sequence=[sequence '-']; +end +LevittControl.LevittValuesUsed=[LevittControl.LevittValuesUsed withinRuns.levelList(end)]; + +switch rule + case '++' + peakCriterion='-++'; + troughCriteria={'++ -', '++ +-'}; + case '+++' + peakCriterion='-+++'; + troughCriteria={'+++ -', '+++ +-', '+++ ++-'}; + otherwise + error('Levitt:') +end + +troughs=[]; allTroughPtrs=[]; +for i=1:length(troughCriteria) % do all trough criteria + troughCriterion=char(troughCriteria(i));% one criterion at a time + % identify the location of a trough + troughPtrs=findstr(sequence, troughCriterion) + length(troughCriterion)-1; + % identify the level at which it occurred + troughLevels=LevittControl.LevittValuesUsed(troughPtrs); + % archive the list + withinRuns.troughs=troughLevels; + troughs=[troughs troughLevels]; + allTroughPtrs=[allTroughPtrs troughPtrs]; +end +% only one peak criterion used +withinRuns.troughs=troughs; +peakPtrs=findstr(sequence,peakCriterion)+length(peakCriterion)-1; +peakLevels=LevittControl.LevittValuesUsed(peakPtrs); +withinRuns.peaks=peakLevels; + +% almagamate and sort into date order +peakTroughList=[peakLevels troughs]; +peakTroughPtrs=[peakPtrs allTroughPtrs]; +[peakTroughPtrs idx]=sort(peakTroughPtrs); +% it needs to be sequenced so that the algorithm can take the last peaks +% and troughs +peakTroughList=peakTroughList(idx); + +% adjust step size as the trial progresses +% a positive step size indicates the 'harder' direction +if length(peakTroughList)>=LevittControl.TurnsToSmallSteps + currentStep=LevittControl.steadyLevittStep; +else + currentStep=LevittControl.startLevelStep; +end + +% base next stimulus on the basis of the sequence +% any miss requires an 'easier' stimulus next time. +if strcmp(sequence(end),'-') + nextStep= -currentStep; + + % success requires 2 or more successive hits +elseif strcmp(sequence(end-length(rule)+1:end),rule) + sequence=[sequence ' ']; % add space to prevent success on successive trials + LevittControl.LevittValuesUsed=[LevittControl.LevittValuesUsed NaN]; + nextStep=currentStep; + + % not enough hits to provoke a change +else + nextStep=0; +end + +LevittControl.sequence=sequence; + +LevittControl.Nreversals=length(peakTroughList); +% compute threshold estimate +% only if minReversals exceeded and even number of peaks and troughs +if LevittControl.Nreversals>=LevittControl.minReversals && rem(length(peakTroughList),2)==0 + % use only the peaks and troughs at the end of the sequence + peaksAndTroughs=peakTroughList(end-LevittControl.useLastNturns+1:end); + disp(['peak/trough sequence= ' num2str(peaksAndTroughs, '%6.0f') ] ) + + meanPT=mean(peaksAndTroughs); + sdPT=std(peaksAndTroughs); + LevittControl.meanPeakTrough=meanPT; + LevittControl.sd=sdPT; + fprintf('Levitt, mean, sd= %6.1f,%6.1f\n', meanPT, sdPT) + % final check that the sd is low enough + if sdPT<LevittControl.targetsdPT + nextValue=currentValue; + msg='done'; + return + end +end + +nextValue=currentValue + nextStep; +if nextValue>LevittControl.maxLevittValue + msg='maximum level exceeded' + return +end + +% required for later use +LevittControl.trialRunning=LevittControl.trialRunning+1; +LevittControl.peakTroughValues=peakTroughList; + +if LevittControl.trialRunning>LevittControl.maxTrials + msg='maximum no of trials exceeded' + return +end + +% Trial continues +msg='';