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