annotate multithreshold 1.46/Levitt2.m @ 38:c2204b18f4a2 tip

End nov big change
author Ray Meddis <rmeddis@essex.ac.uk>
date Mon, 28 Nov 2011 13:34:28 +0000
parents f233164f4c86
children
rev   line source
rmeddis@0 1 function [nextStep, msg]=Levitt2 (decision, currentValue)
rmeddis@0 2 global LevittControl withinRuns
rmeddis@0 3 % descision is a string: 'hit' or 'miss'
rmeddis@0 4 % current value is the value of the variable parameter (e.g. level)
rmeddis@0 5 % msg:
rmeddis@0 6 % msg='' indicates trial progressing successfully
rmeddis@0 7 % msg='done' indicates that a threshold estimate has been found
rmeddis@0 8 % msg='maximum level exceeded'
rmeddis@0 9 % msg='maximum no of trials exceeded'
rmeddis@0 10
rmeddis@0 11 % Initialize by running Levitt2 without arguments
rmeddis@0 12 % later LevittControl will be set in aReadAndCheckParameterBoxes in expGUI_MT
rmeddis@0 13 if nargin==0
rmeddis@0 14
rmeddis@0 15 LevittControl.peakTroughValues=[];
rmeddis@0 16 LevittControl.trialRunning=0;
rmeddis@0 17 LevittControl.sequence='****';
rmeddis@0 18 LevittControl.LevittValuesUsed=[NaN NaN NaN NaN];
rmeddis@0 19 LevittControl.TurnsToSmallSteps=4; % 2 peaks and 2 troughs
rmeddis@0 20 LevittControl.direction='same';
rmeddis@0 21 LevittControl.prevDirection='easier';
rmeddis@0 22 LevittControl.Nreversals=0;
rmeddis@0 23
rmeddis@0 24 LevittControl.trialRunning=1;
rmeddis@0 25 LevittControl.meanPeakTrough=NaN;
rmeddis@0 26 LevittControl.sd=NaN;
rmeddis@0 27 msg='';
rmeddis@0 28 return
rmeddis@0 29 end
rmeddis@0 30
rmeddis@0 31 % apply Levitt rules to find next stimulus value
rmeddis@0 32 rule=LevittControl.rule;
rmeddis@0 33 sequence=LevittControl.sequence;
rmeddis@0 34 meanPT=LevittControl.meanPeakTrough;
rmeddis@0 35 sdPT=LevittControl.sd;
rmeddis@0 36
rmeddis@0 37 % response sequence: '+' is a hit and '-' is a miss.
rmeddis@0 38 if strcmp(decision,'hit')
rmeddis@0 39 sequence=[sequence '+'];
rmeddis@0 40 else
rmeddis@0 41 sequence=[sequence '-'];
rmeddis@0 42 end
rmeddis@0 43 LevittControl.LevittValuesUsed=[LevittControl.LevittValuesUsed withinRuns.levelList(end)];
rmeddis@0 44
rmeddis@0 45 switch rule
rmeddis@0 46 case '++'
rmeddis@0 47 peakCriterion='-++';
rmeddis@0 48 troughCriteria={'++ -', '++ +-'};
rmeddis@0 49 case '+++'
rmeddis@0 50 peakCriterion='-+++';
rmeddis@0 51 troughCriteria={'+++ -', '+++ +-', '+++ ++-'};
rmeddis@0 52 otherwise
rmeddis@0 53 error('Levitt:')
rmeddis@0 54 end
rmeddis@0 55
rmeddis@0 56 troughs=[]; allTroughPtrs=[];
rmeddis@0 57 for i=1:length(troughCriteria) % do all trough criteria
rmeddis@0 58 troughCriterion=char(troughCriteria(i));% one criterion at a time
rmeddis@0 59 % identify the location of a trough
rmeddis@0 60 troughPtrs=findstr(sequence, troughCriterion) + length(troughCriterion)-1;
rmeddis@0 61 % identify the level at which it occurred
rmeddis@0 62 troughLevels=LevittControl.LevittValuesUsed(troughPtrs);
rmeddis@0 63 % archive the list
rmeddis@0 64 withinRuns.troughs=troughLevels;
rmeddis@0 65 troughs=[troughs troughLevels];
rmeddis@0 66 allTroughPtrs=[allTroughPtrs troughPtrs];
rmeddis@0 67 end
rmeddis@0 68 % only one peak criterion used
rmeddis@0 69 withinRuns.troughs=troughs;
rmeddis@0 70 peakPtrs=findstr(sequence,peakCriterion)+length(peakCriterion)-1;
rmeddis@0 71 peakLevels=LevittControl.LevittValuesUsed(peakPtrs);
rmeddis@0 72 withinRuns.peaks=peakLevels;
rmeddis@0 73
rmeddis@0 74 % almagamate and sort into date order
rmeddis@0 75 peakTroughList=[peakLevels troughs];
rmeddis@0 76 peakTroughPtrs=[peakPtrs allTroughPtrs];
rmeddis@0 77 [peakTroughPtrs idx]=sort(peakTroughPtrs);
rmeddis@0 78 % it needs to be sequenced so that the algorithm can take the last peaks
rmeddis@0 79 % and troughs
rmeddis@0 80 peakTroughList=peakTroughList(idx);
rmeddis@0 81
rmeddis@0 82 % adjust step size as the trial progresses
rmeddis@0 83 % a positive step size indicates the 'harder' direction
rmeddis@0 84 if length(peakTroughList)>=LevittControl.TurnsToSmallSteps
rmeddis@0 85 currentStep=LevittControl.steadyLevittStep;
rmeddis@0 86 else
rmeddis@0 87 currentStep=LevittControl.startLevelStep;
rmeddis@0 88 end
rmeddis@0 89
rmeddis@0 90 % base next stimulus on the basis of the sequence
rmeddis@0 91 % any miss requires an 'easier' stimulus next time.
rmeddis@0 92 if strcmp(sequence(end),'-')
rmeddis@0 93 nextStep= -currentStep;
rmeddis@0 94
rmeddis@0 95 % success requires 2 or more successive hits
rmeddis@0 96 elseif strcmp(sequence(end-length(rule)+1:end),rule)
rmeddis@0 97 sequence=[sequence ' ']; % add space to prevent success on successive trials
rmeddis@0 98 LevittControl.LevittValuesUsed=[LevittControl.LevittValuesUsed NaN];
rmeddis@0 99 nextStep=currentStep;
rmeddis@0 100
rmeddis@0 101 % not enough hits to provoke a change
rmeddis@0 102 else
rmeddis@0 103 nextStep=0;
rmeddis@0 104 end
rmeddis@0 105
rmeddis@0 106 LevittControl.sequence=sequence;
rmeddis@0 107
rmeddis@0 108 LevittControl.Nreversals=length(peakTroughList);
rmeddis@0 109 % compute threshold estimate
rmeddis@0 110 % only if minReversals exceeded and even number of peaks and troughs
rmeddis@0 111 if LevittControl.Nreversals>=LevittControl.minReversals && rem(length(peakTroughList),2)==0
rmeddis@0 112 % use only the peaks and troughs at the end of the sequence
rmeddis@0 113 peaksAndTroughs=peakTroughList(end-LevittControl.useLastNturns+1:end);
rmeddis@0 114 disp(['peak/trough sequence= ' num2str(peaksAndTroughs, '%6.0f') ] )
rmeddis@0 115
rmeddis@0 116 meanPT=mean(peaksAndTroughs);
rmeddis@0 117 sdPT=std(peaksAndTroughs);
rmeddis@0 118 LevittControl.meanPeakTrough=meanPT;
rmeddis@0 119 LevittControl.sd=sdPT;
rmeddis@0 120 fprintf('Levitt, mean, sd= %6.1f,%6.1f\n', meanPT, sdPT)
rmeddis@0 121 % final check that the sd is low enough
rmeddis@0 122 if sdPT<LevittControl.targetsdPT
rmeddis@0 123 nextValue=currentValue;
rmeddis@0 124 msg='done';
rmeddis@0 125 return
rmeddis@0 126 end
rmeddis@0 127 end
rmeddis@0 128
rmeddis@0 129 nextValue=currentValue + nextStep;
rmeddis@0 130 if nextValue>LevittControl.maxLevittValue
rmeddis@0 131 msg='maximum level exceeded'
rmeddis@0 132 return
rmeddis@0 133 end
rmeddis@0 134
rmeddis@0 135 % required for later use
rmeddis@0 136 LevittControl.trialRunning=LevittControl.trialRunning+1;
rmeddis@0 137 LevittControl.peakTroughValues=peakTroughList;
rmeddis@0 138
rmeddis@0 139 if LevittControl.trialRunning>LevittControl.maxTrials
rmeddis@0 140 msg='maximum no of trials exceeded'
rmeddis@0 141 return
rmeddis@0 142 end
rmeddis@0 143
rmeddis@0 144 % Trial continues
rmeddis@0 145 msg='';