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