changeset 0:f233164f4c86

first commit
author Ray Meddis <rmeddis@essex.ac.uk>
date Fri, 27 May 2011 13:19:21 +0100
parents
children 9eaf5759550e
files .gitignore MAP/MAP1_14.m MAP/filteredSACF.m MAP/intpow.c MAP/intpow.mexa64 MAP/intpow.mexglx MAP/intpow.mexw32 MAP/intpow.mexw64 MAP1_14 quick reference.doc multithreshold 1.46/CHIMES.WAV multithreshold 1.46/CedrusUSB/FTCOMMS.VXD multithreshold 1.46/CedrusUSB/FTDIBUS.CAT multithreshold 1.46/CedrusUSB/FTDIBUS.INF multithreshold 1.46/CedrusUSB/FTDIPORT.CAT multithreshold 1.46/CedrusUSB/FTDIPORT.INF multithreshold 1.46/CedrusUSB/FTDIUN2K.INI multithreshold 1.46/CedrusUSB/FTDIUNIN.EXE multithreshold 1.46/CedrusUSB/FTDIUNIN.INI multithreshold 1.46/CedrusUSB/FTSENUM.SYS multithreshold 1.46/CedrusUSB/FTSENUM.VXD multithreshold 1.46/CedrusUSB/FTSERIAL.SYS multithreshold 1.46/CedrusUSB/FTSERMOU.INF multithreshold 1.46/CedrusUSB/FTSERMOU.VXD multithreshold 1.46/CedrusUSB/FTSERUI.DLL multithreshold 1.46/CedrusUSB/Installing the Cedrus USB Button box.doc multithreshold 1.46/CedrusUSB/ftdibus.sys multithreshold 1.46/CedrusUSB/ftser2k.sys multithreshold 1.46/CedrusUSB/ftserui2.dll multithreshold 1.46/Levitt2.m multithreshold 1.46/MAP1_14variables.mat multithreshold 1.46/MAPmodel.m multithreshold 1.46/TADA.WAV multithreshold 1.46/Twister.wav multithreshold 1.46/addToMsg.m multithreshold 1.46/bestFitPsychometicFunctions.m multithreshold 1.46/compare.m multithreshold 1.46/compareMicrophonic.m multithreshold 1.46/ding.wav multithreshold 1.46/expGUI_MT.fig multithreshold 1.46/expGUI_MT.m multithreshold 1.46/hs_err_pid6084.log multithreshold 1.46/nextStimulus.m multithreshold 1.46/paradigms/paradigmList.mat multithreshold 1.46/paradigms/paradigm_GOM.m multithreshold 1.46/paradigms/paradigm_IFMC.m multithreshold 1.46/paradigms/paradigm_IFMC_16ms.m multithreshold 1.46/paradigms/paradigm_SRT.m multithreshold 1.46/paradigms/paradigm_TENtest.m multithreshold 1.46/paradigms/paradigm_TMC.m multithreshold 1.46/paradigms/paradigm_TMC_16ms.m multithreshold 1.46/paradigms/paradigm_TMCmodel.m multithreshold 1.46/paradigms/paradigm_absThreshold.m multithreshold 1.46/paradigms/paradigm_absThreshold_16.m multithreshold 1.46/paradigms/paradigm_absThreshold_8.m multithreshold 1.46/paradigms/paradigm_discomfort.m multithreshold 1.46/paradigms/paradigm_forwardMasking.m multithreshold 1.46/paradigms/paradigm_overShoot.m multithreshold 1.46/paradigms/paradigm_psychometric.m multithreshold 1.46/paradigms/paradigm_threshold_duration.m multithreshold 1.46/paradigms/paradigm_training.m multithreshold 1.46/paradigms/paradigm_trainingIFMC.m multithreshold 1.46/paradigms/reserve team/OHIOthresholds.m multithreshold 1.46/paradigms/reserve team/paradigm_OHIOabs.m multithreshold 1.46/paradigms/reserve team/paradigm_OHIOrand.m multithreshold 1.46/paradigms/reserve team/paradigm_OHIOspect.m multithreshold 1.46/paradigms/reserve team/paradigm_OHIOspectemp.m multithreshold 1.46/paradigms/reserve team/paradigm_OHIOtemp.m multithreshold 1.46/paradigms/stimulus.wav multithreshold 1.46/printReport.m multithreshold 1.46/psychoLogisticRareEvent.m multithreshold 1.46/psychometricFunction.m multithreshold 1.46/savedData/mostRecentResults.mat multithreshold 1.46/speech.wav multithreshold 1.46/stimulus.wav multithreshold 1.46/subjGUI_MT.fig multithreshold 1.46/subjGUI_MT.m multithreshold 1.46/testAN.m multithreshold 1.46/testBM.m multithreshold 1.46/testFM.m multithreshold 1.46/testOME.m multithreshold 1.46/testPeriphery.m multithreshold 1.46/testRF.m multithreshold 1.46/testRP.m multithreshold 1.46/testSynapse.m parameterStore/MAPparamsNormal.m testPrograms/showMAP.m testPrograms/test_MAP1_14.m utilities/UTIL_CV.m utilities/UTIL_PSTHmaker.m utilities/UTIL_makePSTH.m utilities/UTIL_paramsList.m utilities/UTIL_periodHistogram.m utilities/UTIL_plotMatrix.m utilities/UTIL_printTabTable.m utilities/UTIL_showStruct.m utilities/UTIL_showStructureSummary.m utilities/UTIL_vectorStrength.m utilities/stimulusCreate.m wavFileStore/new-ba-44khz.wav wavFileStore/new-da-44khz.wav wavFileStore/new-da-44khz_olde.wav wavFileStore/twister_44kHz.wav ~$P1_14 quick reference.doc
diffstat 103 files changed, 13421 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.gitignore	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,5 @@
+*.asv 		#ignore windows autosaves
+*.*~ 		#ignore mac autosaves
+.DS_Store 	#ignore some other Mac auto generated file
+*.doc 		#ignore MSword
+*.docx 		#ignore newer MSword
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MAP/MAP1_14.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,1106 @@
+
+function  MAP1_14(inputSignal, sampleRate, BFlist, MAPparamsName, ...
+    AN_spikesOrProbability, paramChanges)
+% To test this function use test_MAP1_14 in this folder
+%
+% All arguments are mandatory.
+%
+% BFlist is a list of BFs but can be '-1' to allow MAPparams to choose
+%
+
+%  MAPparamsName='Normal'; % source of model parameters
+%  AN_spikesOrProbability='spikes'; % or 'probability'
+%  paramChanges is a cell array of strings that can be used to make last
+%   minute parameter changes, e.g., to simulate OHC loss
+%   paramChanges{1}= 'DRNLParams.a=0;';
+
+% The model parameters are established in the MAPparams<***> file
+%  and stored as global
+
+restorePath=path;
+addpath (['..' filesep 'parameterStore'])
+
+global OMEParams DRNLParams IHC_cilia_RPParams IHCpreSynapseParams
+global AN_IHCsynapseParams MacGregorParams MacGregorMultiParams
+
+% All of the results of this function are stored as global
+global dt ANdt  savedBFlist saveAN_spikesOrProbability saveMAPparamsName...
+    savedInputSignal OMEextEarPressure TMoutput OMEoutput ARattenuation ...
+    DRNLoutput IHC_cilia_output IHCrestingCiliaCond IHCrestingV...
+    IHCoutput ANprobRateOutput ANoutput savePavailable tauCas  ...
+    CNoutput  ICoutput ICmembraneOutput ICfiberTypeRates MOCattenuation
+
+% Normally only ICoutput(logical spike matrix) or ANprobRateOutput will be
+% needed by the user; so the following will suffice
+%   global ANdt ICoutput ANprobRateOutput
+
+% Note that sampleRate has not changed from the original function call and
+%  ANprobRateOutput is sampled at this rate
+% However ANoutput, CNoutput and IC output are stored as logical
+%  'spike' matrices using a lower sample rate (see ANdt).
+
+% When AN_spikesOrProbability is set to probability,
+%  no spike matrices are computed.
+% When AN_spikesOrProbability is set to 'spikes',
+%  no probability output is computed
+
+% Efferent control variables are ARattenuation and MOCattenuation
+%  These are scalars between 1 (no attenuation) and 0.
+%  They are represented with dt=1/sampleRate (not ANdt)
+%  They are computed using either AN probability rate output
+%   or IC (spikes) output as approrpriate.
+% AR is computed using across channel activity
+% MOC is computed on a within-channel basis.
+
+
+% save as global for later plotting if required
+savedBFlist=BFlist;
+saveAN_spikesOrProbability=AN_spikesOrProbability;
+saveMAPparamsName=MAPparamsName;
+
+% Read parameters from MAPparams<***> file in 'parameterStore' folder
+cmd=['method=MAPparams' MAPparamsName ...
+    '(BFlist, sampleRate, 0);'];
+eval(cmd);
+
+% Beware, 'BFlist=-1' is a legitimate argument for MAPparams<>
+%  if the calling program allows MAPparams to specify the list
+BFlist=DRNLParams.nonlinCFs;
+
+% now accept last mintue parameter changes required by the calling program
+if nargin>5 && ~isempty(paramChanges)
+    nChanges=length(paramChanges);
+    for idx=1:nChanges
+        eval(paramChanges{idx})
+    end
+end
+
+dt=1/sampleRate;
+duration=length(inputSignal)/sampleRate;
+% segmentDuration is specified in parameter file (must be >efferent delay)
+segmentDuration=method.segmentDuration;
+segmentLength=round(segmentDuration/ dt);
+segmentTime=dt*(1:segmentLength); % used in debugging plots
+
+% all spiking activity is computed using longer epochs
+ANspeedUpFactor=5;  % 5 times longer
+
+% inputSignal must be  row vector
+[r c]=size(inputSignal);
+if r>c, inputSignal=inputSignal'; end       % transpose
+% ignore stereo signals
+inputSignal=inputSignal(1,:);               % drop any second channel
+savedInputSignal=inputSignal;
+
+% Segment the signal
+% The sgment length is given but the signal length must be adjusted to be a
+% multiple of both the segment length and the reduced segmentlength
+[nSignalRows signalLength]=size(inputSignal);
+segmentLength=ceil(segmentLength/ANspeedUpFactor)*ANspeedUpFactor;
+% Make the signal length a whole multiple of the segment length
+nSignalSegments=ceil(signalLength/segmentLength);
+padSize=nSignalSegments*segmentLength-signalLength;
+pad=zeros(nSignalRows,padSize);
+inputSignal=[inputSignal pad];
+[ignore signalLength]=size(inputSignal);
+
+% AN (spikes) is computed at a lower sample rate when spikes required
+%  so it has a reduced segment length (see 'ANspeeUpFactor' above)
+% AN CN and IC all use this sample interval
+ANdt=dt*ANspeedUpFactor;
+reducedSegmentLength=round(segmentLength/ANspeedUpFactor);
+reducedSignalLength= round(signalLength/ANspeedUpFactor);
+
+%% Initialise with respect to each stage before computing
+%  by allocating memory,
+%  by computing constants
+%  by establishing easy to read variable names
+% The computations are made in segments and boundary conditions must
+%  be established and stored. These are found in variables with
+%  'boundary' or 'bndry' in the name
+
+%% OME ---
+% external ear resonances
+OMEexternalResonanceFilters=OMEParams.externalResonanceFilters;
+[nOMEExtFilters c]=size(OMEexternalResonanceFilters);
+% details of external (outer ear) resonances
+OMEgaindBs=OMEexternalResonanceFilters(:,1);
+OMEgainScalars=10.^(OMEgaindBs/20);
+OMEfilterOrder=OMEexternalResonanceFilters(:,2);
+OMElowerCutOff=OMEexternalResonanceFilters(:,3);
+OMEupperCutOff=OMEexternalResonanceFilters(:,4);
+% external resonance coefficients
+ExtFilter_b=cell(nOMEExtFilters,1);
+ExtFilter_a=cell(nOMEExtFilters,1);
+for idx=1:nOMEExtFilters
+    Nyquist=sampleRate/2;
+    [b, a] = butter(OMEfilterOrder(idx), ...
+        [OMElowerCutOff(idx) OMEupperCutOff(idx)]...
+        /Nyquist);
+    ExtFilter_b{idx}=b;
+    ExtFilter_a{idx}=a;
+end
+OMEExtFilterBndry=cell(2,1);
+OMEextEarPressure=zeros(1,signalLength); % pressure at tympanic membrane
+
+% pressure to velocity conversion using smoothing filter (50 Hz cutoff)
+tau=1/(2*pi*50);
+a1=dt/tau-1; a0=1;
+b0=1+ a1;
+TMdisp_b=b0; TMdisp_a=[a0 a1];
+% figure(9), freqz(TMdisp_b, TMdisp_a)
+OME_TMdisplacementBndry=[];
+
+% OME high pass (simulates poor low frequency stapes response)
+OMEhighPassHighCutOff=OMEParams.OMEstapesLPcutoff;
+Nyquist=sampleRate/2;
+[stapesDisp_b,stapesDisp_a] = butter(1, OMEhighPassHighCutOff/Nyquist, 'high');
+% figure(10), freqz(stapesDisp_b, stapesDisp_a)
+
+OMEhighPassBndry=[];
+
+% OMEampStapes might be reducdant (use OMEParams.stapesScalar)
+stapesScalar= OMEParams.stapesScalar;
+
+% Acoustic reflex
+efferentDelayPts=round(OMEParams.ARdelay/dt);
+% smoothing filter
+% Nyquist=(1/ANdt)/2;
+% [ARfilt_b,ARfilt_a] = butter(1, (1/(2*pi*OMEParams.ARtau))/Nyquist, 'low');
+a1=dt/OMEParams.ARtau-1; a0=1;
+b0=1+ a1;
+ARfilt_b=b0; ARfilt_a=[a0 a1];
+
+ARattenuation=ones(1,signalLength);
+ARrateThreshold=OMEParams.ARrateThreshold; % may not be used
+ARrateToAttenuationFactor=OMEParams.rateToAttenuationFactor;
+ARrateToAttenuationFactorProb=OMEParams.rateToAttenuationFactorProb;
+ARboundary=[];
+ARboundaryProb=0;
+
+% save complete OME record (stapes displacement)
+OMEoutput=zeros(1,signalLength);
+TMoutput=zeros(1,signalLength);
+
+%% BM ---
+% BM is represented as a list of locations identified by BF
+DRNL_BFs=BFlist;
+nBFs= length(DRNL_BFs);
+
+% DRNLchannelParameters=DRNLParams.channelParameters;
+DRNLresponse= zeros(nBFs, segmentLength);
+
+MOCrateToAttenuationFactor=DRNLParams.rateToAttenuationFactor;
+rateToAttenuationFactorProb=DRNLParams.rateToAttenuationFactorProb;
+MOCrateThreshold=DRNLParams.MOCrateThreshold;
+
+% smoothing filter for MOC
+% Nyquist=(1/ANdt)/2;
+% [MOCfilt_b,MOCfilt_a] = ...
+%     butter(1, (1/(2*pi*DRNLParams.MOCtau))/Nyquist, 'low');
+% figure(10), freqz(stapesDisp_b, stapesDisp_a)
+a1=dt/DRNLParams.MOCtau-1; a0=1;
+b0=1+ a1;
+MOCfilt_b=b0; MOCfilt_a=[a0 a1];
+% figure(9), freqz(stapesDisp_b, stapesDisp_a)
+MOCboundary=cell(nBFs,1);
+MOCprobBoundary=cell(nBFs,1);
+
+MOCattSegment=zeros(nBFs,reducedSegmentLength);
+MOCattenuation=ones(nBFs,signalLength);
+
+if DRNLParams.a>0
+    DRNLcompressionThreshold=10^((1/(1-DRNLParams.c))* ...
+    log10(DRNLParams.b/DRNLParams.a));
+else
+    DRNLcompressionThreshold=inf;
+end
+
+DRNLlinearOrder= DRNLParams.linOrder;
+DRNLnonlinearOrder= DRNLParams.nonlinOrder;
+
+DRNLa=DRNLParams.a;
+DRNLb=DRNLParams.b;
+DRNLc=DRNLParams.c;
+linGAIN=DRNLParams.g;
+%
+% gammatone filter coefficients for linear pathway
+bw=DRNLParams.linBWs';
+phi = 2 * pi * bw * dt;
+cf=DRNLParams.linCFs';
+theta = 2 * pi * cf * dt;
+cos_theta = cos(theta);
+sin_theta = sin(theta);
+alpha = -exp(-phi).* cos_theta;
+b0 = ones(nBFs,1);
+b1 = 2 * alpha;
+b2 = exp(-2 * phi);
+z1 = (1 + alpha .* cos_theta) - (alpha .* sin_theta) * i;
+z2 = (1 + b1 .* cos_theta) - (b1 .* sin_theta) * i;
+z3 = (b2 .* cos(2 * theta)) - (b2 .* sin(2 * theta)) * i;
+tf = (z2 + z3) ./ z1;
+a0 = abs(tf);
+a1 = alpha .* a0;
+GTlin_a = [b0, b1, b2];
+GTlin_b = [a0, a1];
+GTlinOrder=DRNLlinearOrder;
+GTlinBdry=cell(nBFs,GTlinOrder);
+
+% nonlinear gammatone filter coefficients 
+bw=DRNLParams.nlBWs';
+phi = 2 * pi * bw * dt;
+cf=DRNLParams.nonlinCFs';
+theta = 2 * pi * cf * dt;
+cos_theta = cos(theta);
+sin_theta = sin(theta);
+alpha = -exp(-phi).* cos_theta;
+b0 = ones(nBFs,1);
+b1 = 2 * alpha;
+b2 = exp(-2 * phi);
+z1 = (1 + alpha .* cos_theta) - (alpha .* sin_theta) * i;
+z2 = (1 + b1 .* cos_theta) - (b1 .* sin_theta) * i;
+z3 = (b2 .* cos(2 * theta)) - (b2 .* sin(2 * theta)) * i;
+tf = (z2 + z3) ./ z1;
+a0 = abs(tf);
+a1 = alpha .* a0;
+GTnonlin_a = [b0, b1, b2];
+GTnonlin_b = [a0, a1];
+GTnonlinOrder=DRNLnonlinearOrder;
+GTnonlinBdry1=cell(nBFs, GTnonlinOrder);
+GTnonlinBdry2=cell(nBFs, GTnonlinOrder);
+
+% complete BM record (BM displacement)
+DRNLoutput=zeros(nBFs, signalLength);
+
+
+%% IHC ---
+% IHC cilia activity and receptor potential
+% viscous coupling between BM and stereocilia displacement
+% Nyquist=sampleRate/2;
+% IHCcutoff=1/(2*pi*IHC_cilia_RPParams.tc);
+% [IHCciliaFilter_b,IHCciliaFilter_a]=...
+%     butter(1, IHCcutoff/Nyquist, 'high');
+a1=dt/IHC_cilia_RPParams.tc-1; a0=1;
+b0=1+ a1;
+% high pass (i.e. low pass reversed)
+IHCciliaFilter_b=[a0 a1]; IHCciliaFilter_a=b0;
+% figure(9), freqz(IHCciliaFilter_b, IHCciliaFilter_a)
+
+IHCciliaBndry=cell(nBFs,1);
+
+% IHC apical conductance (Boltzman function)
+IHC_C= IHC_cilia_RPParams.C;
+IHCu0= IHC_cilia_RPParams.u0;
+IHCu1= IHC_cilia_RPParams.u1;
+IHCs0= IHC_cilia_RPParams.s0;
+IHCs1= IHC_cilia_RPParams.s1;
+IHCGmax= IHC_cilia_RPParams.Gmax;
+IHCGu0= IHC_cilia_RPParams.Gu0; % (leakage)
+IHCGa= IHCGmax./(1+exp(-(0-IHCu0)/IHCs0).*(1+exp(-(0-IHCu1)/IHCs1)));
+IHCrestingCiliaCond=IHCGa+IHCGu0;
+
+% Receptor potential
+IHC_Cab= IHC_cilia_RPParams.Cab;
+IHC_Gk= IHC_cilia_RPParams.Gk;
+IHC_Et= IHC_cilia_RPParams.Et;
+IHC_Ek= IHC_cilia_RPParams.Ek;
+IHC_Ekp= IHC_Ek+IHC_Et*IHC_cilia_RPParams.Rpc;
+
+IHCrestingV= -0.06;
+IHC_Vnow= IHCrestingV*ones(nBFs,1); % initial voltage
+IHC_RP= zeros(nBFs,segmentLength);
+
+% complete record of IHC receptor potential (V)
+IHCciliaDisplacement= zeros(nBFs,segmentLength);
+IHCoutput= zeros(nBFs,signalLength);
+IHC_cilia_output= zeros(nBFs,signalLength);
+
+
+%% pre-synapse ---
+% Each BF is replicated using a different fiber type to make a 'channel'
+% The number of channels is nBFs x nANfiberTypes
+% Fiber types are specified in terms of tauCa
+nANfiberTypes= length(IHCpreSynapseParams.tauCa);
+tauCas= IHCpreSynapseParams.tauCa;
+nChannels= nANfiberTypes*nBFs;
+synapticCa= zeros(nChannels,segmentLength);
+
+% Calcium control (more calcium, greater release rate)
+ECa=IHCpreSynapseParams.ECa;
+gamma=IHCpreSynapseParams.gamma;
+beta=IHCpreSynapseParams.beta;
+tauM=IHCpreSynapseParams.tauM;
+mICa=zeros(nChannels,segmentLength);
+GmaxCa=IHCpreSynapseParams.GmaxCa;
+synapse_z= IHCpreSynapseParams.z;
+synapse_power=IHCpreSynapseParams.power;
+
+% tauCa vector is established across channels to allow vectorization
+%  (one tauCa per channel). Do not confuse with tauCas (one pre fiber type)
+tauCa=repmat(tauCas, nBFs,1);
+tauCa=reshape(tauCa, nChannels, 1);
+
+% presynapse startup values (vectors, length:nChannels)
+% proportion (0 - 1) of Ca channels open at IHCrestingV
+mICaCurrent=((1+beta^-1 * exp(-gamma*IHCrestingV))^-1)...
+    *ones(nBFs*nANfiberTypes,1);
+% corresponding startup currents
+ICaCurrent= (GmaxCa*mICaCurrent.^3) * (IHCrestingV-ECa);
+CaCurrent= ICaCurrent.*tauCa;
+
+% vesicle release rate at startup (one per channel)
+% kt0 is used only at initialisation
+kt0= -synapse_z * CaCurrent.^synapse_power;
+
+
+%% AN ---
+% each row of the AN matrices represents one AN fiber
+% The results computed either for probabiities *or* for spikes (not both)
+% Spikes are necessary if CN and IC are to be computed
+nFibersPerChannel= AN_IHCsynapseParams.numFibers;
+nANfibers= nChannels*nFibersPerChannel;
+
+y=AN_IHCsynapseParams.y;
+l=AN_IHCsynapseParams.l;
+x=AN_IHCsynapseParams.x;
+r=AN_IHCsynapseParams.r;
+M=round(AN_IHCsynapseParams.M);
+
+% probability            (NB initial 'P' on everything)
+PAN_ydt = repmat(AN_IHCsynapseParams.y*dt, nChannels,1);
+PAN_ldt = repmat(AN_IHCsynapseParams.l*dt, nChannels,1);
+PAN_xdt = repmat(AN_IHCsynapseParams.x*dt, nChannels,1);
+PAN_rdt = repmat(AN_IHCsynapseParams.r*dt, nChannels,1);
+PAN_rdt_plus_ldt = PAN_rdt + PAN_ldt;
+PAN_M=round(AN_IHCsynapseParams.M);
+
+% compute starting values
+Pcleft    = kt0* y* M ./ (y*(l+r)+ kt0* l);
+Pavailable    = Pcleft*(l+r)./kt0;
+Preprocess    = Pcleft*r/x; % canbe fractional
+
+ANprobability=zeros(nChannels,segmentLength);
+ANprobRateOutput=zeros(nChannels,signalLength);
+% special variables for monitoring synaptic cleft (specialists only)
+savePavailableSeg=zeros(nChannels,segmentLength);
+savePavailable=zeros(nChannels,signalLength);
+
+% spikes     % !  !  !    ! !        !   !  !
+AN_refractory_period= AN_IHCsynapseParams.refractory_period;
+lengthAbsRefractory= round(AN_refractory_period/ANdt);
+
+AN_ydt= repmat(AN_IHCsynapseParams.y*ANdt, nANfibers,1);
+AN_ldt= repmat(AN_IHCsynapseParams.l*ANdt, nANfibers,1);
+AN_xdt= repmat(AN_IHCsynapseParams.x*ANdt, nANfibers,1);
+AN_rdt= repmat(AN_IHCsynapseParams.r*ANdt, nANfibers,1);
+AN_rdt_plus_ldt= AN_rdt + AN_ldt;
+AN_M= round(AN_IHCsynapseParams.M);
+
+% kt0  is initial release rate
+% Establish as a vector (length=channel x number of fibers)
+kt0= repmat(kt0', nFibersPerChannel, 1);
+kt0=reshape(kt0, nANfibers,1);
+
+% starting values for reservoirs
+AN_cleft    = kt0* y* M ./ (y*(l+r)+ kt0* l);
+AN_available    = round(AN_cleft*(l+r)./kt0); %must be integer
+AN_reprocess    = AN_cleft*r/x;
+
+% output is in a logical array spikes = 1/ 0.
+ANspikes= false(nANfibers,reducedSegmentLength);
+ANoutput= false(nANfibers,reducedSignalLength);
+
+
+%% CN (first brain stem nucleus - could be any subdivision of CN)
+% Input to a CN neuorn is a random selection of AN fibers within a channel
+%  The number of AN fibers used is ANfibersFanInToCN
+ANfibersFanInToCN=MacGregorMultiParams.fibersPerNeuron;
+nCNneuronsPerChannel=MacGregorMultiParams.nNeuronsPerBF;
+% CNtauGk (Potassium time constant) determines the rate of firing of
+%  the unit when driven hard by a DC input (not normally >350 sp/s)
+CNtauGk=MacGregorMultiParams.tauGk;
+ANavailableFibersPerChan=AN_IHCsynapseParams.numFibers;
+nCNneurons=nCNneuronsPerChannel*nChannels;
+% nCNneuronsPerFiberType= nCNneurons/nANfiberTypes;
+
+CNmembranePotential=zeros(nCNneurons,reducedSegmentLength);
+
+% establish which ANfibers (by name) feed into which CN nuerons
+CNinputfiberLists=zeros(nChannels*nCNneuronsPerChannel, ANfibersFanInToCN);
+unitNo=1;
+for ch=1:nChannels
+    % Each channel contains a number of units =length(listOfFanInValues)
+    for idx=1:nCNneuronsPerChannel
+        fibersUsed=(ch-1)*ANavailableFibersPerChan + ...
+            ceil(rand(1,ANfibersFanInToCN)* ANavailableFibersPerChan);
+        CNinputfiberLists(unitNo,:)=fibersUsed;
+        unitNo=unitNo+1;
+    end
+end
+
+% input to CN units
+AN_PSTH=zeros(nCNneurons,reducedSegmentLength);
+
+% Generate CNalphaFunction function
+%  by which spikes are converted to post-synaptic currents
+CNdendriteLPfreq= MacGregorMultiParams.dendriteLPfreq;
+CNcurrentPerSpike=MacGregorMultiParams.currentPerSpike;
+CNspikeToCurrentTau=1/(2*pi*CNdendriteLPfreq);
+t=ANdt:ANdt:5*CNspikeToCurrentTau;
+CNalphaFunction=...
+    (CNcurrentPerSpike/CNspikeToCurrentTau)*t.*exp(-t/CNspikeToCurrentTau);
+% figure(98), plot(t,CNalphaFunction)
+% working memory for implementing convolution
+CNcurrentTemp=...
+    zeros(nCNneurons,reducedSegmentLength+length(CNalphaFunction)-1);
+% trailing alphas are parts of humps carried forward to the next segment
+CNtrailingAlphas=zeros(nCNneurons,length(CNalphaFunction));
+
+CN_tauM=MacGregorMultiParams.tauM;
+CN_tauTh=MacGregorMultiParams.tauTh;
+CN_cap=MacGregorMultiParams.Cap;
+CN_c=MacGregorMultiParams.c;
+CN_b=MacGregorMultiParams.dGkSpike;
+CN_Ek=MacGregorMultiParams.Ek;
+CN_Eb= MacGregorMultiParams.Eb;
+CN_Er=MacGregorMultiParams.Er;
+CN_Th0= MacGregorMultiParams.Th0;
+CN_E= zeros(nCNneurons,1);
+CN_Gk= zeros(nCNneurons,1);
+CN_Th= MacGregorMultiParams.Th0*ones(nCNneurons,1);
+CN_Eb=CN_Eb.*ones(nCNneurons,1);
+CN_Er=CN_Er.*ones(nCNneurons,1);
+CNtimeSinceLastSpike=zeros(nCNneurons,1);
+% tauGk is the main distinction between neurons
+%  in fact they are all the same in the standard model
+tauGk=repmat(CNtauGk,nChannels*nCNneuronsPerChannel,1);
+
+CN_PSTH=zeros(nChannels,reducedSegmentLength);
+CNoutput=false(nCNneurons,reducedSignalLength);
+
+
+%% MacGregor (IC - second nucleus) --------
+nICcells=nChannels;  % one cell per channel
+
+ICspikeWidth=0.00015;   % this may need revisiting
+epochsPerSpike=round(ICspikeWidth/ANdt);
+if epochsPerSpike<1
+    error(['MacGregorMulti: sample rate too low to support ' ...
+        num2str(ICspikeWidth*1e6) '  microsec spikes']);
+end
+
+% short names
+IC_tauM=MacGregorParams.tauM;
+IC_tauGk=MacGregorParams.tauGk;
+IC_tauTh=MacGregorParams.tauTh;
+IC_cap=MacGregorParams.Cap;
+IC_c=MacGregorParams.c;
+IC_b=MacGregorParams.dGkSpike;
+IC_Th0=MacGregorParams.Th0;
+IC_Ek=MacGregorParams.Ek;
+IC_Eb= MacGregorParams.Eb;
+IC_Er=MacGregorParams.Er;
+
+IC_E=zeros(nICcells,1);
+IC_Gk=zeros(nICcells,1);
+IC_Th=IC_Th0*ones(nICcells,1);
+
+% Dendritic filtering, all spikes are replaced by CNalphaFunction functions
+ICdendriteLPfreq= MacGregorParams.dendriteLPfreq;
+ICcurrentPerSpike=MacGregorParams.currentPerSpike;
+ICspikeToCurrentTau=1/(2*pi*ICdendriteLPfreq);
+t=ANdt:ANdt:3*ICspikeToCurrentTau;
+IC_CNalphaFunction= (ICcurrentPerSpike / ...
+    ICspikeToCurrentTau)*t.*exp(-t / ICspikeToCurrentTau);
+% figure(98), plot(t,IC_CNalphaFunction)
+
+% working space for implementing alpha function
+ICcurrentTemp=...
+    zeros(nICcells,reducedSegmentLength+length(IC_CNalphaFunction)-1);
+ICtrailingAlphas=zeros(nICcells, length(IC_CNalphaFunction));
+
+ICfiberTypeRates=zeros(nANfiberTypes,reducedSignalLength);
+ICoutput=false(nChannels,reducedSignalLength);
+
+ICmembranePotential=zeros(nICcells,reducedSegmentLength);
+ICmembraneOutput=zeros(nICcells,signalLength);
+
+
+%% Main program %%  %%  %%  %%  %%  %%  %%  %%  %%  %%  %%  %%  %%  %%
+
+%  Compute the entire model for each segment
+segmentStartPTR=1;
+reducedSegmentPTR=1; % when sampling rate is reduced
+while segmentStartPTR<signalLength
+    segmentEndPTR=segmentStartPTR+segmentLength-1;
+    % shorter segments after speed up.
+    shorterSegmentEndPTR=reducedSegmentPTR+reducedSegmentLength-1;
+
+    iputPressureSegment=inputSignal...
+        (:,segmentStartPTR:segmentStartPTR+segmentLength-1);
+
+    % segment debugging plots
+    % figure(98)
+    % plot(segmentTime,iputPressureSegment), title('signalSegment')
+
+
+    % OME ----------------------
+
+    % OME Stage 1: external resonances. Add to inputSignal pressure wave
+    y=iputPressureSegment;
+    for n=1:nOMEExtFilters
+        % any number of resonances can be used
+        [x  OMEExtFilterBndry{n}] = ...
+            filter(ExtFilter_b{n},ExtFilter_a{n},...
+            iputPressureSegment, OMEExtFilterBndry{n});
+        x= x* OMEgainScalars(n);
+        % This is a parallel resonance so add it
+        y=y+x;
+    end
+    iputPressureSegment=y;
+    OMEextEarPressure(segmentStartPTR:segmentEndPTR)= iputPressureSegment;
+    
+    % OME stage 2: convert input pressure (velocity) to
+    %  tympanic membrane(TM) displacement using low pass filter
+    [TMdisplacementSegment  OME_TMdisplacementBndry] = ...
+        filter(TMdisp_b,TMdisp_a,iputPressureSegment, ...
+        OME_TMdisplacementBndry);
+    % and save it
+    TMoutput(segmentStartPTR:segmentEndPTR)= TMdisplacementSegment;
+
+    % OME stage 3: middle ear high pass effect to simulate stapes inertia
+    [stapesDisplacement  OMEhighPassBndry] = ...
+        filter(stapesDisp_b,stapesDisp_a,TMdisplacementSegment, ...
+        OMEhighPassBndry);
+
+    % OME stage 4:  apply stapes scalar
+    stapesDisplacement=stapesDisplacement*stapesScalar;
+
+    % OME stage 5:    acoustic reflex stapes attenuation
+    %  Attenuate the TM response using feedback from LSR fiber activity
+    if segmentStartPTR>efferentDelayPts
+        stapesDisplacement= stapesDisplacement.*...
+            ARattenuation(segmentStartPTR-efferentDelayPts:...
+            segmentEndPTR-efferentDelayPts);
+    end
+
+    % segment debugging plots
+    % figure(98)
+    % plot(segmentTime, stapesDisplacement), title ('stapesDisplacement')
+
+    % and save
+    OMEoutput(segmentStartPTR:segmentEndPTR)= stapesDisplacement;
+
+
+    %% BM ------------------------------
+    % Each location is computed separately
+    for BFno=1:nBFs
+
+        %            *linear* path
+        linOutput = stapesDisplacement * linGAIN;  % linear gain
+        for order = 1 : GTlinOrder
+            [linOutput GTlinBdry{BFno,order}] = ...
+                filter(GTlin_b(BFno,:), GTlin_a(BFno,:), linOutput, GTlinBdry{BFno,order});
+        end
+
+        %           *nonLinear* path
+        % efferent attenuation (0 <> 1)
+        if segmentStartPTR>efferentDelayPts
+            MOC=MOCattenuation(BFno, segmentStartPTR-efferentDelayPts:...
+                segmentEndPTR-efferentDelayPts);
+        else    % no MOC available yet
+            MOC=ones(1, segmentLength);
+        end
+
+        %       first gammatone filter
+        for order = 1 : GTnonlinOrder
+            [nonlinOutput GTnonlinBdry1{BFno,order}] = ...
+                filter(GTnonlin_b(BFno,:), GTnonlin_a(BFno,:), ...
+                stapesDisplacement, GTnonlinBdry1{BFno,order});
+        end
+
+        %       broken stick instantaneous compression
+        % nonlinear gain is weakend by MOC before applied to BM response
+        y= nonlinOutput.*(MOC* DRNLa);  % linear section.
+        % compress those parts of the signal above the compression
+        % threshold
+        abs_x = abs(nonlinOutput);
+        idx=find(abs_x>DRNLcompressionThreshold);
+        if ~isempty(idx)>0
+            y(idx)=sign(nonlinOutput(idx)).*...
+                (DRNLb*abs_x(idx).^DRNLc);
+        end
+        nonlinOutput=y;
+
+        %       second filter removes distortion products
+        for order = 1 : GTnonlinOrder
+            [ nonlinOutput GTnonlinBdry2{BFno,order}] = ...
+                filter(GTnonlin_b(BFno,:), GTnonlin_a(BFno,:), nonlinOutput, GTnonlinBdry2{BFno,order});
+        end
+
+        %  combine the two paths to give the DRNL displacement
+        DRNLresponse(BFno,:)=linOutput+nonlinOutput;
+    end % BF
+
+    % segment debugging plots
+    % figure(98)
+    %     if size(DRNLresponse,1)>3
+    %         imagesc(DRNLresponse)  % matrix display
+    %         title('DRNLresponse'); % single or double channel response
+    %     else
+    %         plot(segmentTime, DRNLresponse)
+    %     end
+
+    % and save it
+    DRNLoutput(:, segmentStartPTR:segmentEndPTR)= DRNLresponse;
+
+
+    %% IHC ------------------------------------
+    %  BM displacement to IHCciliaDisplacement is  a high-pass filter
+    %   because of viscous coupling
+    for idx=1:nBFs
+        [IHCciliaDisplacement(idx,:)  IHCciliaBndry{idx}] = ...
+            filter(IHCciliaFilter_b,IHCciliaFilter_a, ...
+            DRNLresponse(idx,:), IHCciliaBndry{idx});
+    end
+    
+    % apply scalar
+    IHCciliaDisplacement=IHCciliaDisplacement* IHC_C;
+
+    % and save it
+    IHC_cilia_output(:,segmentStartPTR:segmentStartPTR+segmentLength-1)=...
+        IHCciliaDisplacement;
+
+    % compute apical conductance
+    G=1./(1+exp(-(IHCciliaDisplacement-IHCu0)/IHCs0).*...
+        (1+exp(-(IHCciliaDisplacement-IHCu1)/IHCs1)));
+    Gu=IHCGmax*G;
+    % add resting conductance to give apical conductance
+    Gu= Gu+IHCGu0;
+
+    % Compute receptor potential
+    for idx=1:segmentLength
+        IHC_Vnow=IHC_Vnow+ (-Gu(:, idx).*(IHC_Vnow-IHC_Et)-...
+            IHC_Gk*(IHC_Vnow-IHC_Ekp))*  dt/IHC_Cab;
+        IHC_RP(:,idx)=IHC_Vnow;
+    end
+
+    % segment debugging plots
+    %     if size(IHC_RP,1)>3
+    %         surf(IHC_RP), shading interp, title('IHC_RP')
+    %     else
+    %         plot(segmentTime, IHC_RP)
+    %     end
+
+    % and save it
+    IHCoutput(:, segmentStartPTR:segmentStartPTR+segmentLength-1)=IHC_RP;
+
+
+    %% synapse -----------------------------
+    % Compute the vesicle release rate for each fiber type at each BF
+    % replicate IHC_RP for each fiber type
+    Vsynapse=repmat(IHC_RP, nANfiberTypes,1);
+
+    % look-up table of target fraction channels open for a given IHC_RP
+    mICaINF=    1./( 1 + exp(-gamma  * Vsynapse)  /beta);
+    % fraction of channel open - apply time constant
+    for idx=1:segmentLength
+        % mICaINF is the current 'target' value of mICa
+        mICaCurrent=mICaCurrent+(mICaINF(:,idx)-mICaCurrent)*dt./tauM;
+        mICa(:,idx)=mICaCurrent;
+    end
+
+    ICa=   (GmaxCa* mICa.^3) .* (Vsynapse- ECa);
+
+    for idx=1:segmentLength
+        CaCurrent=CaCurrent +  ICa(:,idx)*dt - CaCurrent*dt./tauCa;
+        synapticCa(:,idx)=CaCurrent;
+    end
+    synapticCa=-synapticCa; % treat IHCpreSynapseParams as positive substance
+
+    % NB vesicleReleaseRate is /s and is independent of dt
+    vesicleReleaseRate = synapse_z * synapticCa.^synapse_power; % rate
+
+    % segment debugging plots
+    %     if size(vesicleReleaseRate,1)>3
+    %         surf(vesicleReleaseRate), shading interp, title('vesicleReleaseRate')
+    %     else
+    %         plot(segmentTime, vesicleReleaseRate)
+    %     end
+
+
+    %% AN
+    switch AN_spikesOrProbability
+        case 'probability'
+            % No refractory effect is applied
+            for t = 1:segmentLength;
+                M_Pq=PAN_M-Pavailable;
+                M_Pq(M_Pq<0)=0;
+                Preplenish = M_Pq .* PAN_ydt;
+                Pejected = Pavailable.* vesicleReleaseRate(:,t)*dt;
+                Preprocessed = M_Pq.*Preprocess.* PAN_xdt;
+
+                ANprobability(:,t)= min(Pejected,1);
+                reuptakeandlost= PAN_rdt_plus_ldt .* Pcleft;
+                reuptake= PAN_rdt.* Pcleft;
+
+                Pavailable= Pavailable+ Preplenish- Pejected+ Preprocessed;
+                Pcleft= Pcleft + Pejected - reuptakeandlost;
+                Preprocess= Preprocess + reuptake - Preprocessed;
+                Pavailable(Pavailable<0)=0;
+                savePavailableSeg(:,t)=Pavailable;    % synapse tracking
+            end
+            % and save it as *rate*
+            ANrate=ANprobability/dt;
+            ANprobRateOutput(:, segmentStartPTR:...
+                segmentStartPTR+segmentLength-1)=  ANrate;
+            % monitor synapse contents (only sometimes used)
+            savePavailable(:, segmentStartPTR:segmentStartPTR+segmentLength-1)=...
+                savePavailableSeg;
+
+            % Estimate efferent effects. ARattenuation (0 <> 1)
+            %  acoustic reflex
+            ARAttSeg=mean(ANrate(1:nBFs,:),1); %LSR channels are 1:nBF
+            % smooth
+            [ARAttSeg, ARboundaryProb] = ...
+                filter(ARfilt_b, ARfilt_a, ARAttSeg, ARboundaryProb);
+            ARAttSeg=ARAttSeg-ARrateThreshold;
+            ARAttSeg(ARAttSeg<0)=0;   % prevent negative strengths
+            ARattenuation(segmentStartPTR:segmentEndPTR)=...
+                (1-ARrateToAttenuationFactorProb.* ARAttSeg);
+
+            % MOC attenuation
+            % within-channel HSR response only
+            HSRbegins=nBFs*(nANfiberTypes-1)+1;
+            rates=ANrate(HSRbegins:end,:);
+            for idx=1:nBFs
+                [smoothedRates, MOCprobBoundary{idx}] = ...
+                    filter(MOCfilt_b, MOCfilt_a, rates(idx,:), ...
+                    MOCprobBoundary{idx});
+                smoothedRates=smoothedRates-MOCrateThreshold;
+                smoothedRates(smoothedRates<0)=0;
+                MOCattenuation(idx,segmentStartPTR:segmentEndPTR)= ...
+                    (1- smoothedRates* rateToAttenuationFactorProb);
+            end
+            MOCattenuation(MOCattenuation<0)=0.001;
+
+
+        case 'spikes'
+            ANtimeCount=0;
+            % implement speed upt
+            for t = ANspeedUpFactor:ANspeedUpFactor:segmentLength;
+                ANtimeCount=ANtimeCount+1;
+                % convert release rate to probabilities
+                releaseProb=vesicleReleaseRate(:,t)*ANdt;
+                % releaseProb is the release probability per channel
+                %  but each channel has many synapses
+                releaseProb=repmat(releaseProb',nFibersPerChannel,1);
+                releaseProb=reshape(releaseProb, nFibersPerChannel*nChannels,1);
+
+                % AN_available=round(AN_available); % vesicles must be integer, (?needed)
+                M_q=AN_M- AN_available;     % number of missing vesicles
+                M_q(M_q<0)= 0;              % cannot be less than 0
+
+                % AN_N1 converts probability to discrete events
+                %   it considers each event that might occur
+                %   (how many vesicles might be released)
+                %   and returns a count of how many were released
+
+                % slow line
+%                 probabilities= 1-(1-releaseProb).^AN_available;
+                probabilities= 1-intpow((1-releaseProb), AN_available);
+                ejected= probabilities> rand(length(AN_available),1);
+
+                reuptakeandlost = AN_rdt_plus_ldt .* AN_cleft;
+                reuptake = AN_rdt.* AN_cleft;
+
+                % slow line
+%                 probabilities= 1-(1-AN_reprocess.*AN_xdt).^M_q;
+                probabilities= 1-intpow((1-AN_reprocess.*AN_xdt), M_q);
+                reprocessed= probabilities>rand(length(M_q),1);
+
+                % slow line
+%                 probabilities= 1-(1-AN_ydt).^M_q;
+                 probabilities= 1-intpow((1-AN_ydt), M_q);
+
+                replenish= probabilities>rand(length(M_q),1);
+
+                AN_available = AN_available + replenish - ejected ...
+                    + reprocessed;
+                AN_cleft = AN_cleft + ejected - reuptakeandlost;
+                AN_reprocess = AN_reprocess + reuptake - reprocessed;
+
+                % ANspikes is logical record of vesicle release events>0
+                ANspikes(:, ANtimeCount)= ejected;
+            end % t
+
+            % zero any events that are preceded by release events ...
+            %  within the refractory period
+            % The refractory period consist of two periods
+            %  1) the absolute period where no spikes occur
+            %  2) a relative period where a spike may occur. This relative
+            %     period is realised as a variable length interval
+            %     where the length is chosen at random
+            %     (esentially a linear ramp up)
+
+            % Andreas has a fix for this
+            for t = 1:ANtimeCount-2*lengthAbsRefractory;
+                % identify all spikes across fiber array at time (t)
+                % idx is a list of channels where spikes occurred
+                % ?? try sparse matrices?
+                idx=find(ANspikes(:,t));
+                for j=idx  % consider each spike
+                    % specify variable refractory period
+                    %  between abs and 2*abs refractory period
+                    nPointsRefractory=lengthAbsRefractory+...
+                        round(rand*lengthAbsRefractory);
+                    % disable spike potential for refractory period
+                    % set all values in this range to 0
+                    ANspikes(j,t+1:t+nPointsRefractory)=0;
+                end
+            end  %t
+
+            % segment debugging
+            % plotInstructions.figureNo=98;
+            % plotInstructions.displaydt=ANdt;
+            %  plotInstructions.numPlots=1;
+            %  plotInstructions.subPlotNo=1;
+            % UTIL_plotMatrix(ANspikes, plotInstructions);
+
+            % and save it. NB, AN is now on 'speedUp' time
+            ANoutput(:, reducedSegmentPTR: shorterSegmentEndPTR)=ANspikes;
+
+
+            %% CN Macgregor first neucleus -------------------------------
+            % input is from AN so ANdt is used throughout
+            % Each CNneuron has a unique set of input fibers selected
+            %  at random from the available AN fibers (CNinputfiberLists)
+
+            % Create the dendritic current for that neuron
+            % First get input spikes to this neuron
+            synapseNo=1;
+            for ch=1:nChannels
+                for idx=1:nCNneuronsPerChannel
+                    % determine candidate fibers for this unit
+                    fibersUsed=CNinputfiberLists(synapseNo,:);
+                    % ANpsth has a bin width of dt
+                    %  (just a simple sum across fibers)
+                    AN_PSTH(synapseNo,:) = ...
+                        sum(ANspikes(fibersUsed,:), 1);
+                    synapseNo=synapseNo+1;
+                end
+            end
+
+            % One alpha function per spike
+            [alphaRows alphaCols]=size(CNtrailingAlphas);
+
+            for unitNo=1:nCNneurons
+                CNcurrentTemp(unitNo,:)= ...
+                    conv(AN_PSTH(unitNo,:),CNalphaFunction);
+            end
+            % add post-synaptic current  left over from previous segment
+            CNcurrentTemp(:,1:alphaCols)=...
+                CNcurrentTemp(:,1:alphaCols)+ CNtrailingAlphas;
+
+            % take post-synaptic current for this segment
+            CNcurrentInput= CNcurrentTemp(:, 1:reducedSegmentLength);
+
+            % trailingalphas are the ends of the alpha functions that
+            % spill over into the next segment
+            CNtrailingAlphas= ...
+                CNcurrentTemp(:, reducedSegmentLength+1:end);
+
+            if CN_c>0
+                % variable threshold condition (slow)
+                for t=1:reducedSegmentLength
+                    CNtimeSinceLastSpike=CNtimeSinceLastSpike-dts;
+                    s=CN_E>CN_Th & CNtimeSinceLastSpike<0 ;
+                    CNtimeSinceLastSpike(s)=0.0005;         % 0.5 ms for sodium spike
+                    dE =(-CN_E/CN_tauM + ...
+                        CNcurrentInput(:,t)/CN_cap+(CN_Gk/CN_cap).*(CN_Ek-CN_E))*dt;
+                    dGk=-CN_Gk*dt./tauGk + CN_b*s;
+                    dTh=-(CN_Th-CN_Th0)*dt/CN_tauTh + CN_c*s;
+                    CN_E=CN_E+dE;
+                    CN_Gk=CN_Gk+dGk;
+                    CN_Th=CN_Th+dTh;
+                    CNmembranePotential(:,t)=CN_E+s.*(CN_Eb-CN_E)+CN_Er;
+                end
+            else
+                % static threshold (faster)
+                for t=1:reducedSegmentLength
+                    CNtimeSinceLastSpike=CNtimeSinceLastSpike-dt;
+                    s=CN_E>CN_Th0 & CNtimeSinceLastSpike<0 ;  % =1 if both conditions met
+                    CNtimeSinceLastSpike(s)=0.0005;          % 0.5 ms for sodium spike
+                    dE = (-CN_E/CN_tauM + ...
+                        CNcurrentInput(:,t)/CN_cap+(CN_Gk/CN_cap).*(CN_Ek-CN_E))*dt;
+                    dGk=-CN_Gk*dt./tauGk +CN_b*s;
+                    CN_E=CN_E+dE;
+                    CN_Gk=CN_Gk+dGk;
+                    % add spike to CN_E and add resting potential (-60 mV)
+                    CNmembranePotential(:,t)=CN_E+s.*(CN_Eb-CN_E)+CN_Er;
+                end
+            end
+
+            % extract spikes.  A spike is a substantial upswing in voltage
+            CN_spikes=CNmembranePotential> -0.01;
+
+            % now remove any spike that is immediately followed by a spike
+            % NB 'find' works on columns (whence the transposing)
+            CN_spikes=CN_spikes';
+            idx=find(CN_spikes);
+            idx=idx(1:end-1);
+            CN_spikes(idx+1)=0;
+            CN_spikes=CN_spikes';
+
+            % segment debugging
+            % plotInstructions.figureNo=98;
+            % plotInstructions.displaydt=ANdt;
+            %  plotInstructions.numPlots=1;
+            %  plotInstructions.subPlotNo=1;
+            % UTIL_plotMatrix(CN_spikes, plotInstructions);
+
+            % and save it
+            CNoutput(:, reducedSegmentPTR:shorterSegmentEndPTR)=...
+                CN_spikes;
+
+
+            %% IC ----------------------------------------------
+                %  MacGregor or some other second order neurons
+
+                % combine CN neurons in same channel, i.e. same BF & same tauCa
+                %  to generate inputs to single IC unit
+                channelNo=0;
+                for idx=1:nCNneuronsPerChannel:nCNneurons-nCNneuronsPerChannel+1;
+                    channelNo=channelNo+1;
+                    CN_PSTH(channelNo,:)=...
+                        sum(CN_spikes(idx:idx+nCNneuronsPerChannel-1,:));
+                end
+
+                [alphaRows alphaCols]=size(ICtrailingAlphas);
+                for ICneuronNo=1:nICcells
+                    ICcurrentTemp(ICneuronNo,:)= ...
+                        conv(CN_PSTH(ICneuronNo,:),  IC_CNalphaFunction);
+                end
+
+                % add the unused current from the previous convolution
+                ICcurrentTemp(:,1:alphaCols)=ICcurrentTemp(:,1:alphaCols)...
+                    + ICtrailingAlphas;
+                % take what is required and keep the trailing part for next time
+                inputCurrent=ICcurrentTemp(:, 1:reducedSegmentLength);
+                ICtrailingAlphas=ICcurrentTemp(:, reducedSegmentLength+1:end);
+
+                if IC_c==0
+                    % faster computation when threshold is stable (C==0)
+                    for t=1:reducedSegmentLength
+                        s=IC_E>IC_Th0;
+                        dE = (-IC_E/IC_tauM + inputCurrent(:,t)/IC_cap +...
+                            (IC_Gk/IC_cap).*(IC_Ek-IC_E))*dt;
+                        dGk=-IC_Gk*dt/IC_tauGk +IC_b*s;
+                        IC_E=IC_E+dE;
+                        IC_Gk=IC_Gk+dGk;
+                        ICmembranePotential(:,t)=IC_E+s.*(IC_Eb-IC_E)+IC_Er;
+                    end
+                else
+                    %  threshold is changing (IC_c>0; e.g. bushy cell)
+                    for t=1:reducedSegmentLength
+                        dE = (-IC_E/IC_tauM + ...
+                            inputCurrent(:,t)/IC_cap + (IC_Gk/IC_cap)...
+                            .*(IC_Ek-IC_E))*dt;
+                        IC_E=IC_E+dE;
+                        s=IC_E>IC_Th;
+                        ICmembranePotential(:,t)=IC_E+s.*(IC_Eb-IC_E)+IC_Er;
+                        dGk=-IC_Gk*dt/IC_tauGk +IC_b*s;
+                        IC_Gk=IC_Gk+dGk;
+
+                        % After a spike, the threshold is raised
+                        % otherwise it settles to its baseline
+                        dTh=-(IC_Th-Th0)*dt/IC_tauTh +s*IC_c;
+                        IC_Th=IC_Th+dTh;
+                    end
+                end
+
+                ICspikes=ICmembranePotential> -0.01;
+                % now remove any spike that is immediately followed by a spike
+                % NB 'find' works on columns (whence the transposing)
+                ICspikes=ICspikes';
+                idx=find(ICspikes);
+                idx=idx(1:end-1);
+                ICspikes(idx+1)=0;
+                ICspikes=ICspikes';
+
+                nCellsPerTau= nICcells/nANfiberTypes;
+                firstCell=1;
+                lastCell=nCellsPerTau;
+                for tauCount=1:nANfiberTypes
+                    % separate rates according to fiber types
+                    ICfiberTypeRates(tauCount, ...
+                        reducedSegmentPTR:shorterSegmentEndPTR)=...
+                        sum(ICspikes(firstCell:lastCell, :))...
+                        /(nCellsPerTau*ANdt);
+                    firstCell=firstCell+nCellsPerTau;
+                    lastCell=lastCell+nCellsPerTau;
+                end
+                ICoutput(:, reducedSegmentPTR:shorterSegmentEndPTR)=ICspikes;
+
+                if nBFs==1  % single channel
+                    x= repmat(ICmembranePotential(1,:), ANspeedUpFactor,1);
+                    x= reshape(x,1,segmentLength);
+                    if nANfiberTypes>1  % save HSR and LSR
+                        y= repmat(ICmembranePotential(end,:), ANspeedUpFactor,1);
+                        y= reshape(y,1,segmentLength);
+                        x=[x; y];
+                    end
+                    ICmembraneOutput(:, segmentStartPTR:segmentEndPTR)= x;
+                end
+
+                % estimate efferent effects.
+                % ARis based on LSR units. LSR channels are 1:nBF
+                if nANfiberTypes>1  % AR is multi-channel only
+                    ARAttSeg=sum(ICspikes(1:nBFs,:),1)/ANdt;
+                    [ARAttSeg, ARboundary] = ...
+                        filter(ARfilt_b, ARfilt_a, ARAttSeg, ARboundary);
+                    ARAttSeg=ARAttSeg-ARrateThreshold;
+                    ARAttSeg(ARAttSeg<0)=0;   % prevent negative strengths
+                    % scale up to dt from ANdt
+                    x=    repmat(ARAttSeg, ANspeedUpFactor,1);
+                    x=reshape(x,1,segmentLength);
+                    ARattenuation(segmentStartPTR:segmentEndPTR)=...
+                        (1-ARrateToAttenuationFactor* x);
+                    ARattenuation(ARattenuation<0)=0.001;
+                else
+                    % single channel model; disable AR
+                    ARattenuation(segmentStartPTR:segmentEndPTR)=...
+                        ones(1,segmentLength);
+                end
+
+                % MOC attenuation using HSR response only
+                % Separate MOC effect for each BF
+                HSRbegins=nBFs*(nANfiberTypes-1)+1;
+                rates=ICspikes(HSRbegins:end,:)/ANdt;
+                for idx=1:nBFs
+                    [smoothedRates, MOCboundary{idx}] = ...
+                        filter(MOCfilt_b, MOCfilt_a, rates(idx,:), ...
+                        MOCboundary{idx});
+                    MOCattSegment(idx,:)=smoothedRates;
+                    % expand timescale back to model dt from ANdt
+                    x= repmat(MOCattSegment(idx,:), ANspeedUpFactor,1);
+                    x= reshape(x,1,segmentLength);
+                    MOCattenuation(idx,segmentStartPTR:segmentEndPTR)= ...
+                        (1- MOCrateToAttenuationFactor*  x);
+                end
+                MOCattenuation(MOCattenuation<0)=0.04;
+                % segment debugging
+                % plotInstructions.figureNo=98;
+                % plotInstructions.displaydt=ANdt;
+                %  plotInstructions.numPlots=1;
+                %  plotInstructions.subPlotNo=1;
+                % UTIL_plotMatrix(ICspikes, plotInstructions);
+
+    end     % AN_spikesOrProbability
+    segmentStartPTR=segmentStartPTR+segmentLength;
+    reducedSegmentPTR=reducedSegmentPTR+reducedSegmentLength;
+
+
+end  % segment
+
+path(restorePath)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MAP/filteredSACF.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,235 @@
+function [P, BFlist, sacf, boundaryValue] = ...
+    filteredSACF(inputSignalMatrix, method, params)
+% UTIL_filteredSACF computes within-channel, running autocorrelations (acfs)
+%  and finds the sum across channels (sacf).
+%  The SACF is smoothed to give the 'p function' (P).
+%
+% INPUT
+%  	inputSignalMatrix: a matrix (channel x time) of AN activity
+%  	method.dt:			the signal sampling interval in seconds
+%   method.segmentNo:
+%   method.nonlinCF
+%   
+% params: 	a list of parmeters to guide the computation:
+%   filteredSACFParams.lags: an array of lags to be computed (seconds)
+%   filteredSACFParams.acfTau: time constant (sec) of the running acf calculations
+%     if acfTau>1 it is assumed that Wiegrebe'sacf method
+%   	for calculating tau is to be used (see below)
+%   filteredSACFParams.Lambda: time constant  for smoothing thsacf to make P
+%   filteredSACFParams.lagsProcedure identifies a strategy for omitting some lags.
+%    Options are: 'useAllLags', 'omitShortLags', or 'useBernsteinLagWeights'
+%   filteredSACFParams.usePressnitzer applies lower weights longer lags
+%   parafilteredSACFParamsms.plotACFs (=1) creates movie of acf matrix (optional)
+%
+%
+% OUTPUT
+%  	P:	P function 	(time x lags), a low pass filtered version of sacf.
+%  method: updated version of input method (to include lags used)
+%   sacf:  	(time x lags)
+
+%%
+boundaryValue=[];
+[nChannels inputLength]= size(inputSignalMatrix);
+% list of BFs must be repeated is many fiber types used
+BFlist=method.nonlinCF;
+nfibertypes=nChannels/length(BFlist);
+BFlist=repmat(BFlist',2,1)';
+
+dt=method.dt;
+% adjust sample rate, if required
+if isfield(params,'dt')
+    [inputSignalMatrix dt]=UTIL_adjustDT(params.dt, method.dt, inputSignalMatrix);
+    method.dt=dt;
+end
+
+% create acf movie
+if isfield(params, 'plotACFs') && params.plotACFs==1
+    plotACF=1;
+else
+    plotACF=0;  % default
+end
+
+if isfield(params,'lags')
+    lags=params.lags;
+else
+    lags=params.minLag:params.lagStep:params.maxLag;
+end
+nLags=length(lags);
+
+% Establish lag weightsaccording to params.lagsProcedure
+%  lagWeights allow some lag computations to be ignored
+%  lagWeights is a (channel x lag) matrix;
+if isfield(params, 'lagsProcedure')
+    lagsProcedure=params.lagsProcedure;
+else
+    lagsProcedure='useAllLags';  % default
+end
+% disp(['lag procedure= ''' lagsProcedure ''''])
+lagWeights=ones(nChannels,nLags);
+switch lagsProcedure
+    case 'useAllLags'
+       % no action required lagWeights set above
+    case 'omitShortLags'
+        % remove lags that are short relative to CF
+        allLags=repmat(lags,nChannels,1);
+        allCFs=repmat(BFlist',1,nLags);
+        criterionForOmittingLags=1./(params.criterionForOmittingLags*allCFs);
+        idx= allLags < criterionForOmittingLags;	% ignore these lags
+        lagWeights(idx)=0;
+    case 'useBernsteinLagWeights'
+        lagWeights=BernsteinLags(BFlist, lags)';
+    otherwise
+        error ('acf: params.lagProcedure not recognised')
+end
+
+
+% Establish matrix of lag time constants 
+%   these are all the same if tau<1
+% if acfTau>1, it is assumed that we are using the Wiegrebe method
+%   and a different decay factor is applied to each lag
+%   ( i.e., longer lags have longer time constants)
+acfTau=params.acfTau;
+if acfTau<1          % all taus are the same
+    acfTaus=repmat(acfTau, 1, nLags);
+    acfDecayFactors=ones(size(lags)).*exp(-dt/acfTau);
+else                      % use Wiegrebe method: tau= 2*lag (for example)
+    WiegrebeFactor=acfTau;
+    acfTaus=WiegrebeFactor*lags;
+    idx= acfTaus<0.0025; acfTaus(idx)=0.0025;
+    acfDecayFactors= exp(-dt./(acfTaus));
+end
+% make acfDecayFactors into a (channels x lags) matrix for speedy computation
+acfDecayFactors=repmat(acfDecayFactors,nChannels, 1);
+
+% P function lowpass filter decay (only one value needed)
+pDecayFactor=exp(-dt/params.lambda);
+
+% ACF
+% lagPointers is a list of pointers relative to 'time now'
+lagPointers=round(lags/dt);
+if max(lagPointers)+1>inputLength
+    error([' filteredSACF: not enough signal to evaluate ACF. Max(lag)= ' num2str(max(lags))])
+end
+
+
+P=zeros(nLags,inputLength+1);   % P must match segment length +1
+sacf=zeros(nLags,inputLength);
+if   ~isfield(method,'segmentNumber') || method.segmentNumber==1
+    acf=zeros(nChannels,nLags);
+    % create a runup buffer of signal
+    buffer= zeros(nChannels, max(lagPointers));
+else
+    % boundaryValue picks up from a previous calculation
+    acf=params.boundaryValue{1};
+    P(: , 1)=params.boundaryValue{2}; % NB first value is last value of previous segment
+    buffer=params.boundaryValue{3};
+end
+inputSignalMatrix=[buffer inputSignalMatrix];
+[nChannels inputLength]= size(inputSignalMatrix);
+
+timeCounter=0; biggestSACF=0;
+for timePointer= max(lagPointers)+1:inputLength
+    % acf is a continuously changing channels x lags matrix
+    %   Only the current value is stored
+    % sacf is the vertical summary of acf ( a vector) and all values are kept and returned
+    % P is the smoothed version of sacf and all values are kept and returned
+    % lagWeights emphasise some BF/lag combinations and ignore others
+    % NB time now begins at the longest lag.
+    % E.g. if max(lags) is .04 then this is when the ACf will begin.
+    %            AN                                       AN delayed                             weights               filtering
+    
+    % This is the ACF calculation
+    timeCounter=timeCounter+1;
+    acf= (repmat(inputSignalMatrix(:, timePointer), 1, nLags) .* inputSignalMatrix(:, timePointer-lagPointers)).*lagWeights *dt + acf.* acfDecayFactors;
+    x=(mean(acf,1)./acfTaus)';
+%     disp(num2str(x'))
+    sacf(:,timeCounter)=x;
+    P(:,timeCounter+1)=sacf(:,timeCounter)*(1-pDecayFactor)+P(:,timeCounter)*pDecayFactor;
+    
+    % plot at intervals of 200 points
+    if plotACF && ~mod(timePointer,params.plotACFsInterval)
+        %       mark cursor on chart to signal progress
+        % this assumes that the user has already plotted
+        % the signal in subplot(2,1,1) of figure (13)
+        figure(13)
+        hold on
+        subplot(4,1,1)
+        time=timePointer*dt;
+        a =ylim;
+        plot([time time], [a(1) a(1)+(a(2)-a(1))/4]) % current signal point marker
+        
+        %         plot ACFs one per channel
+        subplot(2,1,2), cla
+        cascadePlot(acf, lags, BFlist)
+        xlim([min(lags) max(lags)])
+        %         set(gca,'xscale','log')
+        title(num2str(method.dt*timePointer))
+        ylabel('BF'), xlabel('period (lag)')
+        
+        %         plot SACF
+        subplot(4,1,2), hold off
+        plot(lags,sacf(:,timeCounter)-min(sacf(:,timeCounter)))
+        biggestSACF=max(biggestSACF, max(sacf(:,timeCounter)));
+        if biggestSACF>0, ylim([0 biggestSACF]), end
+        %         set(gca,'xscale','log')
+        title('SACF')
+        pause(params.plotMoviePauses)
+    end
+end
+P=P(:,1:end-1);  % correction for speed up above
+
+% Pressnitzer weights
+if ~isfield(params, 'usePressnitzer'),     params.usePressnitzer=0; end
+if params.usePressnitzer
+    [a nTimePoints]=size(P);
+    % higher pitches get higher weights
+    %     PressnitzerWeights=repmat(min(lags)./lags,nTimePoints,1);
+    % weaker weighting
+    PressnitzerWeights=repmat((min(lags)./lags).^0.5, nTimePoints,1);
+    P=P.*PressnitzerWeights';
+    sacf=sacf.*PressnitzerWeights';
+end
+
+% wrap up
+method.acfLags=lags;
+method.filteredSACFdt=dt;
+
+boundaryValue{1}=acf(:,end-nLags+1:end);
+boundaryValue{2}=P(:,end);
+% save signal buffer for next segment
+boundaryValue{3} = inputSignalMatrix(:, end-max(lagPointers)+1 : end);
+
+method.displaydt=method.filteredSACFdt;
+
+% if ~isfield(params, 'plotUnflteredSACF'), params.plotUnflteredSACF=0; end
+% if method.plotGraphs
+%     method.plotUnflteredSACF=params.plotUnflteredSACF;
+%     if ~method.plotUnflteredSACF
+%         method=filteredSACFPlot(P,method);
+%     else
+%         method=filteredSACFPlot(SACF,method);
+%     end
+% end
+
+
+% ------------------------------------------------  plotting ACFs
+function cascadePlot(toPlot, lags, BFs)
+% % useful code
+[nChannels nLags]=size(toPlot);
+
+% cunning code to represent channels as parallel lines
+[nRows nCols]=size(toPlot);
+if nChannels>1
+    % max(toPlot) defines the spacing between lines
+    a=max(max(toPlot))*(0:nRows-1)';
+    % a is the height to be added to each channel
+    peakGain=10;
+    % peakGain emphasises the peak height
+    x=peakGain*toPlot+repmat(a,1,nCols);
+    x=nRows*x/max(max(x));
+else
+    x=toPlot;                            % used when only the stimulus is returned
+end
+plot(lags, x','k')
+ylim([0 nRows])
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MAP/intpow.c	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,77 @@
+/* intpow - Nick Clark - 3/5/2011
+ *
+ * Function that raises a double precision vector to an integer power 
+ * vector. The following call to this mex function... 
+ *
+ * >>      z = intpow(x,y)
+ * 
+ * ... does the equivalent of the following in Matlab...
+ *
+ * >>      z = x .^ ceil(y)
+ * 
+ * NOTE: Under most circumstances, this function is slower than MATLAB's 
+ * built in ^ operator, but for the (generally) small integer powers used 
+ * in MAP we observe massive performance boosts using this C function.
+ */
+
+/*************************************************************************/
+/* Header(s)                                                             */
+/*************************************************************************/
+#include "mex.h"
+
+/*************************************************************************/
+/* Input vars                                                            */
+/*************************************************************************/
+#define IN_x 	prhs[0]
+#define IN_y 	prhs[1]
+
+/*************************************************************************/
+/* Output vars                                                           */
+/*************************************************************************/
+#define OUT_z 	plhs[0]
+
+/*************************************************************************/
+/* Gateway function and error checking                                   */
+/*************************************************************************/
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+    /* variable declarations */
+    int numElements, xM, xN, yM, yN; 
+    int nn, kk; 
+    double *x, *y, *z;
+     
+    /*  check the number of input and output parameters  */  
+    if(nrhs!=2)
+        mexErrMsgTxt("intpow : Two input args expected");
+    if(nlhs > 1)
+        mexErrMsgTxt("intpow : Too many outputs");
+    
+    /* check that x and y have equal size */ 
+    x = mxGetPr(IN_x);
+    xM = mxGetM(IN_x);
+    xN = mxGetN(IN_x);
+    
+    y = mxGetPr(IN_y);
+    yM = mxGetM(IN_y);
+    yN = mxGetN(IN_y);
+    
+    if  (xM != yM || xN != yN)
+        mexErrMsgTxt("intpow : x and y must have equal size");
+    
+    /* find upper loop boundary */
+    numElements = xM * xN; 
+    
+    /*  allocate memory and pointer for the output array */ 
+    OUT_z = mxCreateDoubleMatrix(xM,xN,mxREAL);
+    z = mxGetPr(OUT_z);
+    
+    /*  do stuff */ 
+    for( nn = 0;  nn<numElements; ++nn )
+    {
+        z[nn] = 1.0;
+        for (kk = 0; kk<y[nn]; ++kk)
+        {
+            z[nn] = z[nn]*x[nn];
+        }
+    }            
+}
Binary file MAP/intpow.mexa64 has changed
Binary file MAP/intpow.mexglx has changed
Binary file MAP/intpow.mexw32 has changed
Binary file MAP/intpow.mexw64 has changed
Binary file MAP1_14 quick reference.doc has changed
Binary file multithreshold 1.46/CHIMES.WAV has changed
Binary file multithreshold 1.46/CedrusUSB/FTCOMMS.VXD has changed
Binary file multithreshold 1.46/CedrusUSB/FTDIBUS.CAT has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/CedrusUSB/FTDIBUS.INF	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,143 @@
+; FTDIBUS.INF
+; Copyright (c) 2000-2003 FTDI Ltd.
+
+[Version]
+signature="$CHICAGO$"
+Class=USB
+ClassGUID={36fc9e60-c465-11cf-8056-444553540000}
+Provider=%FTDI%
+CatalogFile=ftdibus.cat
+DriverVer=06/16/2003,1.00.2134
+
+[SourceDisksNames]
+1=%DriversDisk%,,,
+
+[SourceDisksFiles]
+ftcomms.vxd = 1
+ftserial.sys = 1
+ftsenum.vxd = 1
+ftsenum.sys = 1
+ftsermou.vxd = 1
+ftserui.dll = 1
+ftdibus.sys = 1
+ftdiunin.exe = 1
+ftdiunin.ini = 1
+ftdiun2k.ini = 1
+
+[DestinationDirs]
+FtdiBus.Copy1 = 11
+FtdiBus.Copy2 = 17
+FtdiBus.NT.Copy = 10,system32\drivers
+FtdiBus.NT.Copy2 = 11
+
+[Manufacturer]
+%Ftdi%=FtdiHw
+
+[FtdiHw]
+%USB\VID_0403&PID_F228.DeviceDesc%=FtdiBus,USB\VID_0403&PID_F228
+
+[ControlFlags]
+ExcludeFromSelect=USB\VID_0403&PID_F228
+
+[FtdiBus]
+CopyFiles=FtdiBus.Copy1,FtdiBus.Copy2
+AddReg=FtdiBus.AddReg, FtdiBusUnInst.Reg
+RemoveDevice=FtdiBus.RemDev
+
+[FtdiBus.HW]
+AddReg=FtdiBus.AddReg.HW
+
+[FtdiBus.AddReg]
+HKR,,DevLoader,,*ntkern
+HKR,,NTMPDriver,,ftserial.sys
+
+[FtdiBus.AddReg.HW]
+HKR,,"UpperFilters",0x00010000,"ftsenum.sys"
+
+[FtdiBus.Copy1]
+ftcomms.vxd
+ftsenum.vxd
+ftsermou.vxd
+ftserial.sys
+ftsenum.sys
+ftserui.dll
+ftdiunin.exe
+ftdiunin.ini
+
+[FtdiBus.Copy2]
+ftdibus.inf
+ftdiport.inf
+ftsermou.inf
+
+[FtdiBus.RemDev]
+DelFiles=FtdiBus.Delfiles
+DELKEY=HKLM,%WINUN%\FTDICOMM
+
+[FtdiBusUnInst.Reg]
+HKLM,%WINUN%,"FTDICOMM"
+HKLM,%WINUN%\FTDICOMM , "UninstallString",,"%11%\ftdiunin.exe %11%\ftdiunin.ini"
+HKLM,%WINUN%\FTDICOMM , "DisplayName",,"Cedrus USB Drivers"
+
+[FtdiBus.DelFiles]
+FTCOMMS.VXD
+ftsenum.vxd
+ftsermou.vxd
+FTSERIAL.SYS
+FTPORTS.INF
+FTDICOM.INF
+ftdibus.inf
+ftdiport.inf
+ftsenum.sys
+ftserui.dll
+ftdiunin.exe
+ftdiunin.ini
+
+;---------------------------------------------------------------;
+; For Win2000 ...
+;
+
+[FtdiBus.NT]
+CopyFiles=FtdiBus.NT.Copy,FtdiBus.NT.Copy2
+AddReg=FtdiBus.NT.AddReg,FtdiBusUnInst.NT.Reg
+
+[FtdiBus.NT.Services]
+AddService = FTDIBUS, 0x00000002, FtdiBus_AddService
+
+[FtdiBus_AddService]
+DisplayName    = %FtdiBus.SvcDesc%
+ServiceType    = 1                  ; SERVICE_KERNEL_DRIVER
+StartType      = 3                  ; SERVICE_DEMAND_START
+ErrorControl   = 1                  ; SERVICE_ERROR_NORMAL
+ServiceBinary  = %10%\system32\drivers\ftdibus.sys
+LoadOrderGroup = Base
+AddReg         = FtdiBus_AddService.AddReg
+
+[FtdiBus.NT.AddReg]
+HKR,,DevLoader,,*ntkern
+HKR,,NTMPDriver,,ftdibus.sys
+
+[FtdiBus_AddService.AddReg]
+HKR,Parameters,"MaximumTransferSize",0x10001,4096
+HKR,Parameters,"DebugLevel",0x10001,2
+
+[FtdiBus.NT.Copy]
+ftdibus.sys
+
+[FtdiBus.NT.Copy2]
+ftdiunin.exe
+ftdiun2k.ini
+
+[FtdiBusUnInst.NT.Reg]
+HKLM,%WINUN%,"FTDICOMM"
+HKLM,%WINUN%\FTDICOMM , "UninstallString",,"%11%\ftdiunin.exe %11%\ftdiun2k.ini"
+HKLM,%WINUN%\FTDICOMM , "DisplayName",,"Cedrus USB Drivers"
+
+;---------------------------------------------------------------;
+
+[Strings]
+Ftdi="FTDI"
+DriversDisk="Cedrus USB Drivers Disk"
+USB\VID_0403&PID_F228.DeviceDesc="Cedrus RB-x30 Response Pad"
+WINUN="Software\Microsoft\Windows\CurrentVersion\Uninstall"
+FtdiBus.SvcDesc="USB Serial Converter Driver"
+
Binary file multithreshold 1.46/CedrusUSB/FTDIPORT.CAT has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/CedrusUSB/FTDIPORT.INF	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,159 @@
+; FTDIPORT.INF
+; Copyright (c) 2000-2003 FTDI Ltd.
+;
+
+[Version]
+Signature="$CHICAGO$"
+Class=Ports
+ClassGUID={4d36e978-e325-11ce-bfc1-08002be10318}
+Provider=%FTDI%
+CatalogFile=ftdiport.cat
+DriverVer=06/16/2003,1.00.2134
+
+[SourceDisksNames]
+1=%DriversDisk%,,,
+
+[SourceDisksFiles]
+ftser2k.sys=1
+ftdiport.inf=1
+ftserui2.dll=1
+
+[DestinationDirs]
+DefaultDestDir=11
+FtdiPort.NT.Copy=10,system32\drivers
+FtdiPort.NT.CopyUI=10,system32
+
+; Install class "Ports"
+;----------------------------------------------------------
+[ClassInstall]
+AddReg=PortsClass.AddReg
+
+[PortsClass.AddReg]
+HKR,,,,%PortsClassName%
+
+[ClassInstall32.NT]
+AddReg=PortsClass.NT.AddReg
+
+[PortsClass.NT.AddReg]
+HKR,,,,%PortsClassName%
+HKR,,Icon,,"-23"
+HKR,,Installer32,,"MsPorts.Dll,PortsClassInstaller"
+
+[ControlFlags]
+ExcludeFromSelect=*
+
+[Manufacturer]
+%FTDI%=FtdiHw
+
+[FtdiHw]
+%VID_0403&PID_F228.DeviceDesc%=FtdiPort232,FTDIBUS\COMPORT&VID_0403&PID_F228
+
+;---------------------------------------------------------------;
+; For Win98 ...
+;
+
+[FtdiPort]
+AddReg=FtdiPort.AddReg,FtdiPort.W98.AddReg
+
+[FtdiPort.AddReg]
+HKR,,PortSubClass,1,01
+
+[FtdiPort.W98.AddReg]
+HKR,,DevLoader,,*vcomm
+HKR,,Enumerator,,ftsenum.vxd
+HKR,,PortDriver,,ftcomms.vxd
+HKR,,Contention,,*vcd
+HKR,,ConfigDialog,,ftserui.dll
+HKR,,DCB,3,1C,00,00,00, 80,25,00,00, 11,33,00,00, 00,00, 0a,00, 0a,00, 08, 00, 00, 11, 13, 00, 00, 00
+HKR,,PortSubClass,1,01
+HKR,,EnumPropPages,,"ftserui.dll,EnumPropPages"
+
+[FtdiPort232]
+AddReg=FtdiPort.AddReg,FtdiPort.W98.AddReg
+
+[FtdiPort232.HW]
+AddReg=FtdiPort232.HW.AddReg
+
+[FtdiPort232.HW.AddReg]
+HKR,,ConfigData,1,01,00,3F,3F,10,27,88,13,C4,09,E2,04,71,02,38,41,9c,80,4E,C0,34,00,1A,00,0D,00,06,40,03,80,00,00,d0,80
+
+;---------------------------------------------------------------;
+; For Win2000 ...
+;
+
+[FtdiPort.NT]
+CopyFiles=FtdiPort.NT.Copy,FtdiPort.NT.CopyUI
+AddReg=FtdiPort.AddReg,FtdiPort.NT.AddReg
+
+[FtdiPort.NT.HW]
+AddReg=FtdiPort.NT.HW.AddReg
+
+[FtdiPort.NT.Services]
+AddService = FTSER2K, 0x00000002, FtdiPort_AddService
+AddService = Serenum,,SerEnum_AddService
+DelService = FTSERIAL
+
+[FtdiPort_AddService]
+DisplayName    = %FtdiPort.SvcDesc%
+ServiceType    = 1                  ; SERVICE_KERNEL_DRIVER
+StartType      = 3                  ; SERVICE_DEMAND_START
+ErrorControl   = 1                  ; SERVICE_ERROR_NORMAL
+ServiceBinary  = %10%\system32\drivers\ftser2k.sys
+LoadOrderGroup = Base
+AddReg         = FtdiPort_AddService.AddReg
+
+; -------------- Serenum Driver install section
+[SerEnum_AddService]
+DisplayName    = %SerEnum.SvcDesc%
+ServiceType    = 1               ; SERVICE_KERNEL_DRIVER
+StartType      = 3               ; SERVICE_DEMAND_START
+ErrorControl   = 1               ; SERVICE_ERROR_NORMAL
+ServiceBinary  = %12%\serenum.sys
+LoadOrderGroup = PNP Filter
+
+[FtdiPort.NT.AddReg]
+HKR,,EnumPropPages32,,"ftserui2.dll,SerialPortPropPageProvider"
+
+[FtdiPort_AddService.AddReg]
+HKR,Parameters,"MaximumTransferSize",0x10001,4096
+HKR,Parameters,"DebugLevel",0x10001,2
+
+[FtdiPort.NT.HW.AddReg]
+HKR,,"UpperFilters",0x00010000,"serenum"
+
+[FtdiPort.NT.Copy]
+ftser2k.sys
+
+[FtdiPort.NT.CopyUI]
+ftserui2.dll
+
+[FtdiPort232.NT]
+CopyFiles=FtdiPort.NT.Copy,FtdiPort.NT.CopyUI
+AddReg=FtdiPort.NT.AddReg
+
+[FtdiPort232.NT.HW]
+AddReg=FtdiPort232.NT.HW.AddReg
+
+[FtdiPort232.NT.Services]
+AddService = FTSER2K, 0x00000002, FtdiPort_AddService
+AddService = Serenum,,SerEnum_AddService
+DelService = FTSERIAL
+
+[FtdiPort232.NT.HW.AddReg]
+HKR,,"UpperFilters",0x00010000,"serenum"
+HKR,,"ConfigData",1,01,00,3F,3F,10,27,88,13,C4,09,E2,04,71,02,38,41,9c,80,4E,C0,34,00,1A,00,0D,00,06,40,03,80,00,00,d0,80
+HKR,,"MinReadTimeout",0x00010001,0
+HKR,,"MinWriteTimeout",0x00010001,0
+HKR,,"LatencyTimer",0x00010001,16
+
+;---------------------------------------------------------------;
+
+[Strings]
+FTDI="FTDI"
+DriversDisk="Cedrus USB Drivers Disk"
+PortsClassName = "Ports (COM & LPT)"
+VID_0403&PID_F228.DeviceDesc="Cedrus RB-x30 Response Pad"
+FtdiPort.SvcDesc="USB Serial Port Driver"
+SerEnum.SvcDesc="Serenum Filter Driver"
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/CedrusUSB/FTDIUN2K.INI	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,7 @@
+[Uninstall]
+Device=VID_0403&PID_F228
+Converter=FTDIBUS
+Serial=FTSER2K
+Key=FTDICOMM
+
+
Binary file multithreshold 1.46/CedrusUSB/FTDIUNIN.EXE has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/CedrusUSB/FTDIUNIN.INI	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,5 @@
+[Uninstall]
+Device=VID_0403&PID_F228
+InfFiles=FTDIBUS,FTDIPORT,FTSERMOU
+Key=FTDICOMM
+
Binary file multithreshold 1.46/CedrusUSB/FTSENUM.SYS has changed
Binary file multithreshold 1.46/CedrusUSB/FTSENUM.VXD has changed
Binary file multithreshold 1.46/CedrusUSB/FTSERIAL.SYS has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/CedrusUSB/FTSERMOU.INF	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,77 @@
+[Version]
+Signature="$CHICAGO$"
+Class=Mouse
+Provider=%MS%
+
+[DestinationDirs]
+DefaultDestDir = 11        ; LDID_SYS
+Sermou.Coyp    = 11
+
+[SourceDisksNames]
+91=%SerMouDisk%,,1
+
+[SourceDisksFiles]
+ftsermou.vxd=91
+
+[Manufacturer]
+%MS%=MS
+
+; Manufacturer Sections
+; ----------------------------------------
+[MS]
+%Sermou.Desc%=Sermou, SERENUM\FTSERMOU
+%Sermou_0F01.Desc%=Sermou, SERENUM\FTSM0F01
+%Sermou_0F04.Desc%=Sermou, SERENUM\FTSM0F04
+%Sermou_0F05.Desc%=Sermou, SERENUM\FTSM0F05
+%Sermou_0F06.Desc%=Sermou, SERENUM\FTSM0F06
+%Sermou_0F07.Desc%=Sermou, SERENUM\FTSM0F07
+%Sermou_0F08.Desc%=Sermou, SERENUM\FTSM0F08
+%Sermou_0F09.Desc%=Sermou, SERENUM\FTSM0F09
+%Sermou_0F0A.Desc%=Sermou, SERENUM\FTSM0F0A
+%Sermou_0F0C.Desc%=Sermou, SERENUM\FTSM0F0C
+%Sermou_0F0F.Desc%=Sermou, SERENUM\FTSM0F0F
+
+
+; Install sections
+; ----------------------------------------
+[Sermou]
+DelReg=Prev.DelReg
+AddReg=VMOUSE.AddReg
+CopyFiles=Sermou.Copy
+UpdateInis=ftsermou.Ini
+
+[Prev.DelReg]
+HKR,,DevLoader
+HKR,,MouseDriver
+
+[VMOUSE.AddReg]
+HKR,,DevLoader,,*vmouse
+HKR,,MouseDriver,,ftsermou.vxd
+
+[Sermou.Copy]
+ftsermou.vxd
+
+[Sermou.Ini]
+system.ini,boot.description,,"mouse.drv=%Sermou.Desc%"
+system.ini,boot,,"mouse.drv=mouse.drv"
+system.ini,386Enh,,"mouse=*vmouse"
+
+
+; ----------------------------------------
+; User-visible Strings
+
+[Strings]
+SerMouDisk="Sample Win95 Mouse Driver Disk"
+MS="Microsoft"
+Sermou.Desc="Win95 Sample Serial Mouse Minidriver"
+Sermou_0F01.Desc="Microsoft serial mouse"
+Sermou_0F04.Desc="Mouse Systems mouse"
+Sermou_0F05.Desc="Mouse Systems 3-button mouse"
+Sermou_0F06.Desc="Genius mouse"
+Sermou_0F07.Desc="Genius mouse"
+Sermou_0F08.Desc="Logitech serial mouse"
+Sermou_0F09.Desc="Microsoft BallPoint serial mouse"
+Sermou_0F0A.Desc="Microsoft Plug and Play mouse"
+Sermou_0F0C.Desc="Microsoft-compatible serial mouse"
+Sermou_0F0F.Desc="Microsoft Serial BallPoint-compatible mouse"
+
Binary file multithreshold 1.46/CedrusUSB/FTSERMOU.VXD has changed
Binary file multithreshold 1.46/CedrusUSB/FTSERUI.DLL has changed
Binary file multithreshold 1.46/CedrusUSB/Installing the Cedrus USB Button box.doc has changed
Binary file multithreshold 1.46/CedrusUSB/ftdibus.sys has changed
Binary file multithreshold 1.46/CedrusUSB/ftser2k.sys has changed
Binary file multithreshold 1.46/CedrusUSB/ftserui2.dll has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/Levitt2.m	Fri May 27 13:19:21 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='';
Binary file multithreshold 1.46/MAP1_14variables.mat has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/MAPmodel.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,136 @@
+function [modelResponse, MacGregorResponse]=MAPmodel( MAPplot, method)
+
+global experiment stimulusParameters audio withinRuns
+global outerMiddleEarParams DRNLParams AN_IHCsynapseParams
+
+savePath=path;
+addpath('..\MAP')
+modelResponse=[];
+MacGregorResponse=[];
+
+% mono only (column vector)
+audio=audio(:,1)';
+
+% if stop button pressed earlier
+if experiment.stop, return, end
+
+% -------------------------------------------------------------- run Model
+MAPparamsName=experiment.name;
+showPlotsAndDetails=experiment.MAPplot;
+AN_spikesOrProbability='spikes';
+
+% [response, method]=MAPsequenceSeg(audio, method, 1:8);
+global ICoutput ANdt
+    MAP1_14(audio, 1/method.dt, method.nonlinCF,...
+        MAPparamsName, AN_spikesOrProbability);
+    
+if showPlotsAndDetails
+    options.showModelParameters=0;
+    options.showModelOutput=1;
+    options.printFiringRates=1;
+    options.showACF=0;
+    options.showEfferent=1;
+    showMAP(options)
+end
+
+% No response,  probably caused by hitting 'stop' button
+if isempty(ICoutput), return, end
+
+% MacGregor response is the sum total of all final stage spiking
+MacGregorResponse= sum(ICoutput,1);                 % use IC
+
+% ---------------------------------------------------------- end model run
+
+dt=ANdt;
+time=dt:dt:dt*length(MacGregorResponse);
+
+% group delay on unit response
+MacGonsetDelay= 0.004;
+MacGoffsetDelay= 0.022;
+
+% now find the response of the MacGregor model during the target presentation + group delay
+switch experiment.threshEstMethod
+    case {'2I2AFC++', '2I2AFC+++'}
+        idx= time>stimulusParameters.testTargetBegins+MacGonsetDelay ...
+            & time<stimulusParameters.testTargetEnds+MacGoffsetDelay;
+        nSpikesTrueWindow=sum(MacGregorResponse(:,idx));
+        idx=find(time>stimulusParameters.testNonTargetBegins+MacGonsetDelay ...
+            & time<stimulusParameters.testNonTargetEnds+MacGoffsetDelay);
+        nSpikesFalseWindow=sum(MacGregorResponse(:,idx));
+        % nSpikesDuringTarget is +ve when more spikes are found
+        %   in the target window
+        difference= nSpikesTrueWindow-nSpikesFalseWindow;
+
+        if difference>0
+            % hit
+            nSpikesDuringTarget=experiment.MacGThreshold+1;
+        elseif    difference<0
+            % miss (wrong choice)
+            nSpikesDuringTarget=experiment.MacGThreshold-1;
+        else
+            if rand>0.5
+                % hit (random choice)
+                nSpikesDuringTarget=experiment.MacGThreshold+1;
+            else
+                % miss (random choice)
+                nSpikesDuringTarget=experiment.MacGThreshold-1;
+            end
+        end
+        disp(['level target dummy decision: ' ...
+            num2str([withinRuns.variableValue nSpikesTrueWindow ...
+            nSpikesFalseWindow  nSpikesDuringTarget], '%4.0f') ] )
+
+    otherwise
+        % idx=find(time>stimulusParameters.testTargetBegins+MacGonsetDelay ...
+        %         & time<stimulusParameters.testTargetEnds+MacGoffsetDelay);
+        % no delay at onset
+        idx=find(time>stimulusParameters.testTargetBegins +MacGonsetDelay...
+            & time<stimulusParameters.testTargetEnds+MacGoffsetDelay);
+        nSpikesDuringTarget=sum(MacGregorResponse(:,idx));
+        
+        % find(MacGregorResponse)*dt-stimulusParameters.stimulusDelay
+        timeX=time(idx);
+end
+
+% now find the response of the MacGregor model at the end of the masker
+idx2=find(time>stimulusParameters.testTargetBegins-0.02 ...
+    & time<stimulusParameters.testTargetBegins);
+if ~isempty(idx2)
+    maskerRate=mean(mean(MacGregorResponse(idx2)));
+else
+    %e.g. no masker
+    maskerRate=0;
+end
+
+if experiment.MAPplot
+    % add vertical lines to indicate target region
+    figure(99), subplot(6,1,6)
+    hold on
+    yL=get(gca,'YLim');
+    plot([stimulusParameters.testTargetBegins + MacGonsetDelay ...
+        stimulusParameters.testTargetBegins   + MacGonsetDelay],yL,'r')
+    plot([stimulusParameters.testTargetEnds   + MacGoffsetDelay ...
+        stimulusParameters.testTargetEnds     + MacGoffsetDelay],yL,'r')
+end
+
+% specify unambiguous response
+switch experiment.paradigm
+    case 'gapDetection'
+        gapResponse=(maskerRate-nSpikesDuringTarget)/maskerRate;
+        if gapResponse>0.2
+            modelResponse=2;    % gap detected
+        else
+            modelResponse=1;    % gap not detected
+        end
+        [nSpikesDuringTarget maskerRate gapResponse modelResponse]
+        figure(22), plot(timeX,earObject(idx))
+    otherwise
+        if nSpikesDuringTarget>experiment.MacGThreshold
+            modelResponse=2;    % stimulus detected
+        else
+            modelResponse=1;    % nothing heard (default)
+        end
+end
+
+
+path(savePath)
\ No newline at end of file
Binary file multithreshold 1.46/TADA.WAV has changed
Binary file multithreshold 1.46/Twister.wav has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/addToMsg.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,35 @@
+% ---------------------------------------------------------- addToMsg
+function addToMsg(message,append, warning)
+% 'message' is posted to the message board
+% if append==1, message is appended to the current message
+global experiment expGUIhandles
+
+if nargin<3
+    % this is not a warning screen
+    warning=0;
+end
+
+if append
+msg=get(expGUIhandles.textMSG,'string');
+[r c]=size(msg);
+    if length(message)<=c
+        y=[message blanks(c-length(message))];
+        msg(r+1,:)=y;
+    else
+        msg=message;
+    end
+else
+    msg=message;
+end
+
+try
+    set(expGUIhandles.textMSG,'string', msg,'fontSize', experiment.msgFontSize)
+    if warning
+        % flash red to signal a warning
+        set(expGUIhandles.textMSG,'backgroundcolor','r', 'ForegroundColor', 'w'	)
+    else
+        set(expGUIhandles.textMSG,'backgroundcolor','w', 'ForegroundColor', 'b')
+    end
+catch
+    error(message)
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/bestFitPsychometicFunctions.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,314 @@
+% ------------------------------------------------------- bestFitPsychometicFunctions
+function [psy, levelsPhaseTwoBinVector, logistic, rareEvent]= bestFitPsychometicFunctions (levelsPhaseTwo, responsesPhaseTwo)
+% bestFitPsychometicFunctions computes a psychometric function from a matrix of levels and responses
+%output
+%  psy is the empirical probabbility of a detection associated with levels in levelsPhaseTwoBinVector
+%  logistic is a structure with results for fitting the logistic function
+%    the logistic fit depends on whether maximum likelihood is used or least squares
+%  rareEvent is a structure with results for fitting the rareEvent function
+%   this is always calculated and lest squares is always used
+
+global experiment stimulusParameters binFrequencies
+
+% Generate a psychometic function by binning the levelsPhaseTwo
+% x is a vector of [levelsPhaseTwo; responsesPhaseTwo]
+% experiment.psyBinWidth defines the width of the bin
+[psy, levelsPhaseTwoBinVector, binFrequencies,yesResponses, noResponses]= ...
+    psychometricFunction(levelsPhaseTwo, responsesPhaseTwo, experiment.psyBinWidth);
+% [levelsPhaseTwoBinVector; binFrequencies; psy];
+
+% undefined slope - return
+if isempty(psy)
+    % slope is undefined
+    psy=[]; levelsPhaseTwoBinVector=[];
+    logistic.bestThreshold=NaN; logistic.bestK=NaN;  logistic.predictionsLOG=[]; logistic.predictionLevels=[];
+    rareEvent.bestGain=NaN; rareEvent.bestVMin=NaN; rareEvent.predictionsRE=[]; rareEvent.predictionLevels=[];
+    rareEvent.thresholddB= NaN; rareEvent.bestPaMindB=NaN;
+    return
+end
+
+% find best fit rare event function
+switch experiment.paradigm
+    case 'gapDuration'
+        % i.e. don't attempt this but visit the function to set null results
+        rareEvent=fitRareEvent([], responsesPhaseTwo, stimulusParameters.targetDuration);
+    otherwise
+        rareEvent=fitRareEvent(levelsPhaseTwo, responsesPhaseTwo, stimulusParameters.targetDuration);
+end
+
+% find best logistic fit
+logisticFunc=' 1./(1+exp(-a2.*(x-a1)));';
+switch experiment.functionEstMethod
+    % least squares estimate
+    case {'logisticLS', 'rareEvent','peaksAndTroughs'}
+        [a1, a2, Euclid]=fitFunctionUsingLeastSquares(levelsPhaseTwo, responsesPhaseTwo, ...
+            logisticFunc, experiment.possLogSlopes, experiment.meanSearchStep);
+%         [a1, a2, Euclid]=fitLogisticUsingLS(psy, levelsPhaseTwoBinVector); %! does not give same result
+        logistic.bestThreshold=a1;
+        logistic.bestK=a2;
+        logistic.predictionsLOG= ...
+            1./(1+exp(-logistic.bestK.*(experiment.predictionLevels-logistic.bestThreshold)));
+        logistic.predictionLevels=experiment.predictionLevels;
+        logistic.Euclid = Euclid;
+        %         predResponses=1./(1+exp(-logistic.bestK.*(levelsPhaseTwo-logistic.bestThreshold)));
+        %         [levelsPhaseTwo' responsesPhaseTwo' predResponses' responsesPhaseTwo'-predResponses' ]
+
+        % maximum likelihood fitting
+    case 'logisticML'
+        [a1, a2, Euclid]=fitFunctionUsingMaxLikelihood (levelsPhaseTwoBinVector,...
+            psy, yesResponses, noResponses, logisticFunc, experiment.possLogSlopes,experiment.meanSearchStep);
+        logistic.bestThreshold=a1;
+        logistic.bestK=a2;
+        logistic.predictionsLOG= ...
+            1./(1+exp(-logistic.bestK.*(experiment.predictionLevels-logistic.bestThreshold)));
+        logistic.predictionLevels=experiment.predictionLevels;
+        logistic.Euclid = Euclid;
+end
+
+% disp(num2str([logistic.bestThreshold logistic.bestK logistic.Euclid]))
+% disp(num2str([ rareEvent.thresholddB rareEvent.bestGain rareEvent.bestVMin rareEvent.Euclid]))
+
+% --------------------------------------------- fitLogisticUsingLS
+function [mean, slope, Euclid]=fitLogisticUsingLS(p,L)
+
+%!! each bin needs to be weighted by its size 
+
+idx1=find(p>0);
+p=p(idx1);
+L=L(idx1);
+idx1=find(p<1);
+p=p(idx1);
+L=L(idx1);
+
+if length(L)<2
+    mean=NaN;
+    slope=NaN;
+    Euclid=NaN;
+    return
+end
+
+y=L;
+x=log(1./p -1);
+a =polyfit(x, y, 1);
+mean=a(2);
+slope=-1/a(1);
+
+% euclid
+predy=polyval(a,x);
+Euclid=sum((predy-y).^2);
+[mean slope Euclid];
+
+% --------------------------------------------- fitFunctionUsingLeastSquares
+function [a1, a2, Euclid]=fitFunctionUsingLeastSquares(levelsPhaseTwo, responsesPhaseTwo, func, possSlopes, meanSearchStep)
+
+% nResponses= yesResponses+noResponses;
+% idx=find(not(nResponses==0));
+% levelsPhaseTwo=levelsPhaseTwo(idx);
+% yesResponses=yesResponses(idx);
+% noResponses=noResponses(idx);
+% nResponses=nResponses(idx);
+
+% psy=yesResponses./nResponses;
+
+possThresholds=min(levelsPhaseTwo):meanSearchStep:max(levelsPhaseTwo);
+
+
+% create vectors representing all combinations of a1 and a2
+nPossThresh=length(possThresholds);
+nPossSlopes=length(possSlopes);
+a1=repmat(possThresholds',nPossSlopes,1);
+a2=repmat(possSlopes,nPossThresh,1);
+a2=reshape(a2,nPossThresh*nPossSlopes,1);
+
+% each response is predicted by every possible threshold and slope
+LS=ones(size(a1));
+for i=1:length(levelsPhaseTwo)
+    x=levelsPhaseTwo(i);
+    eval(['y=' func]);
+    actual=responsesPhaseTwo(i);
+    error= (actual - y).^2;
+    LS=LS+error;
+end
+
+[Euclid, idx]=min(LS);
+
+a1=a1(idx);
+a2=a2(idx);
+
+% x=levelsPhaseTwo;
+% eval(['y=' func]);
+% Euclid= sum((psy-y).^2);
+
+% plot(levelsPhaseTwo,y,'r')
+% hold on
+% plot(levelsPhaseTwo,psy,'o')
+
+% --------------------------------------------- fitFunctionUsingMaxLikelihood
+function [a1, a2, Euclid]=fitFunctionUsingMaxLikelihood...
+    (levelsPhaseTwo,psy, yesResponses, noResponses, func, possible_a2, meanSearchStep)
+
+% fitFunctionUsingMaxLikelihood fits the function in 'func' to binned yes-no data.
+% levelsPhaseTwo specifies the bin centers
+% yesResponses and noResponses are the niumber of yes and no responsesPhaseTwo in each bin
+% 'func' is a function of a1, b1, x; e.g. func='1./(1+exp(-a2.*(x-a1)));';
+%  and a2, a1 are parameters to be discovered.
+% If bins are empty (i.e. neither yes or no), these are eliminated
+%
+
+nResponses=yesResponses+noResponses;
+possible_a1=min(levelsPhaseTwo):meanSearchStep:max(levelsPhaseTwo);
+
+% if nargin<6
+%     possible_a2=-2:.05:4;
+% end
+
+% create vectors representing all combinations of a1 and a2
+nPossThresh=length(possible_a1);
+nPossSlopes=length(possible_a2);
+a1=repmat(possible_a1',nPossSlopes,1);
+a2=repmat(possible_a2,nPossThresh,1);
+a2=reshape(a2,nPossThresh*nPossSlopes,1);
+
+cumulativeProbability=ones(1, length(a2));
+cumulativeProbability=cumulativeProbability';
+
+for i=1:length(levelsPhaseTwo)
+    x=levelsPhaseTwo(i);
+    eval(['y=' func]);
+    funcVal=(1-y).^yesResponses(i);
+    cumulativeProbability= cumulativeProbability.*funcVal;
+    funcVal=y.^noResponses(i);
+    cumulativeProbability= cumulativeProbability.*funcVal;
+end
+
+[maxProb idx]=max(cumulativeProbability);
+a1=a1(idx);
+a2=a2(idx);
+
+% x=levelsPhaseTwo;
+eval(['y=' func]);
+Euclid= sum(nResponses.*(psy-y).^2);
+
+% figure(1), clf
+% plot(levelsPhaseTwo,y)
+% hold on
+% plot(levelsPhaseTwo,psy,'o')
+
+
+
+% --------------------------------------------------- fitRareEvent
+function rareEvent=fitRareEvent(stimulusLevels, responsesPhaseTwo, duration, gains, Vmins)
+% least squares estimate of *rare event* function
+% model is: r = g P – A   ... g=events/s/Pa, A= events/s, P= pressure (Pa)
+% psy=1- exp(d(gP –A  ))   ... d=duration
+% p(event)=gain*levelmPa -Vmin
+% 'responsesPhaseTwo' is a binary vector of subject's decision.
+% 'stimulusLevels' are the corresponding signal levesl (values)
+% duration is required to compute the expectation of an event occurring
+% gains is an optional list of gains to be tried
+% Vmins is an optional list of Vmins to be tried
+
+global experiment
+if nargin<5
+    minVmin=.1; maxVmin=10; nVmins=100;
+    Vmins=[0 logspace(log10(minVmin),log10(maxVmin),nVmins)];
+    % disp(Vmins)
+    gainMin=0.0001; gainMax=1; nGains=100; 
+    gains=[1e-5 logspace(log10(gainMin),log10(gainMax),nGains)];
+end
+
+rareEvent.bestGain=NaN;
+rareEvent.bestVMin=NaN;
+rareEvent.thresholddB=0;
+rareEvent.bestPaMindB=NaN;
+rareEvent.predictionLevels=[];
+rareEvent.predictionsRE=[];
+rareEvent.Euclid=NaN;
+
+if isempty(stimulusLevels), return, end
+
+% expected slope is negative, rareEvent can not be used
+if experiment.psyFunSlope<0
+    return
+end
+
+% NB calculations in microPascals!
+stimulusLevelsAsPressure=28 * 10.^(stimulusLevels/20);
+
+% allGains=reshape(repmat(gains,nVmins,1), 1, nVmins*nGains);
+% allVmins=repmat(Vmins, 1, nGains);
+
+    predictions=NaN*zeros(1,length(stimulusLevels));
+    gainCount=0;
+    Euclid=inf; bestVmin=0; bestGain=0;
+    for gain= gains
+        gainCount=gainCount+1;
+        VminCount=0;
+        
+        % 1 – exp(-d (g P – A))
+        for Vmin=Vmins
+            VminCount=VminCount+1;
+            % all levelsPhaseTwo are simultaneously assessed
+            
+            % original linear function
+%             gP_Vmin=gain*stimulusLevelsAsPressure-Vmin;
+%             idx=(gP_Vmin>0);
+            %   predictions(idx)= 1-exp(-duration*(gP_Vmin(idx)));
+            %   new log function log(r) =gP-A
+            
+            % log function
+            gP_Vmin=gain*stimulusLevelsAsPressure-Vmin;
+            idx=(gP_Vmin>0);
+            predictions(idx)= 1-exp(-duration*exp(gP_Vmin(idx)));
+            predictions(~idx)=0;
+            
+%             % square function
+%             P_Vmin=stimulusLevelsAsPressure-Vmin;
+%             idx=(P_Vmin)>0;
+%             predictions(idx)= 1-exp(-duration*gain*(P_Vmin(idx)).^2);
+%             predictions(~idx)=0;
+            
+            
+            % NB the error is equally weighted for each stimulus/response pair
+            % this is not the same as equal weighting for each distinct level
+            error=(predictions - responsesPhaseTwo).^2;
+            error=mean(error(~isnan(error)));
+            if error<Euclid
+                Euclid=error;
+                bestVmin=Vmin;
+                bestVminCount=VminCount;
+                %                 bestGainCount=gainCount;
+                bestGain=gain;
+            end
+        end
+    end
+    % disp(Vmins)
+
+% if bestGainCount==1 | bestGainCount==nGains
+%     disp(['gain estimate ' num2str(gains(bestGainCount)) ' may be out of range'])
+% end
+
+[rareEvent.Euclid idx]=min(Euclid);
+rareEvent.bestGain=bestGain;
+rareEvent.bestVMin=bestVmin;
+rareEvent.thresholdPa=(-log(0.5)/duration + rareEvent.bestVMin)/rareEvent.bestGain;
+rareEvent.thresholddB=20*log10(rareEvent.thresholdPa/28);
+rareEvent.bestPaMindB=20*log10((rareEvent.bestVMin/rareEvent.bestGain)/28);
+
+predictionLevels= -50:1:120;
+rareEvent.predictionLevels=predictionLevels;
+stimulusLevelsAsPressure=28*10.^(predictionLevels/20);
+
+% gP_Vmin=rareEvent.bestGain*stimulusLevelsAsPressure-rareEvent.bestVMin;
+% rareEvent.predictionsRE= 1-exp(-duration*(gP_Vmin));
+
+gP_Vmin=rareEvent.bestGain*stimulusLevelsAsPressure-rareEvent.bestVMin;
+rareEvent.predictionsRE=  1-exp(-duration*exp(gP_Vmin));
+
+%             P_Vmin=stimulusLevelsAsPressure-Vmin;
+%             predictions= 1-exp(-duration*gain*P_Vmin.^2);
+% predictions(predictions<0)=0;
+%             rareEvent.predictionsRE=predictions;
+
+% rareEvent
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/compare.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,36 @@
+f=[100	200	500	1000	2000	5000	10000];
+levels=-10:10:90;
+
+without=[
+1.44E-10	8.24E-10	1.15E-09	1.43E-09	1.08E-09	4.75E-10	1.43E-09
+4.56E-10	2.61E-09	3.63E-09	4.52E-09	3.37E-09	1.50E-09	4.52E-09
+1.44E-09	8.24E-09	1.15E-08	1.44E-08	1.06E-08	4.75E-09	1.44E-08
+4.56E-09	2.61E-08	4.45E-08	5.16E-08	3.73E-08	1.15E-08	5.16E-08
+1.44E-08	7.05E-08	9.57E-08	9.34E-08	7.44E-08	1.98E-08	9.34E-08
+4.56E-08	1.28E-07	1.46E-07	1.34E-07	1.04E-07	4.35E-08	1.34E-07
+1.06E-07	1.76E-07	2.29E-07	1.99E-07	1.47E-07	5.80E-08	1.99E-07
+1.72E-07	2.48E-07	3.65E-07	3.94E-07	3.39E-07	1.31E-07	3.94E-07
+2.54E-07	3.59E-07	7.88E-07	9.97E-07	9.07E-07	3.51E-07	9.97E-07
+3.82E-07	6.00E-07	2.13E-06	2.85E-06	2.66E-06	1.03E-06	2.85E-06
+5.81E-07	1.37E-06	6.30E-06	8.65E-06	8.17E-06	3.30E-06	8.65E-06
+];
+with=[
+2.60E-11	1.48E-10	2.09E-10	2.61E-10	1.93E-10	8.54E-11	2.61E-10
+8.21E-11	4.69E-10	6.61E-10	8.25E-10	6.10E-10	2.70E-10	8.25E-10
+2.60E-10	1.48E-09	2.09E-09	2.61E-09	1.93E-09	8.54E-10	2.61E-09
+8.21E-10	4.69E-09	6.61E-09	8.25E-09	6.10E-09	2.70E-09	8.25E-09
+2.60E-09	1.48E-08	2.35E-08	3.10E-08	1.96E-08	8.54E-09	3.10E-08
+8.21E-09	4.56E-08	7.17E-08	7.64E-08	5.59E-08	1.33E-08	7.64E-08
+2.60E-08	1.02E-07	1.20E-07	1.16E-07	9.13E-08	3.13E-08	1.16E-07
+7.49E-08	1.51E-07	1.79E-07	1.70E-07	1.25E-07	4.88E-08	1.70E-07
+1.38E-07	2.10E-07	2.90E-07	2.70E-07	2.24E-07	8.63E-08	2.70E-07
+2.10E-07	3.02E-07	5.08E-07	6.24E-07	5.58E-07	2.15E-07	6.24E-07
+3.13E-07	4.33E-07	1.29E-06	1.70E-06	1.57E-06	6.05E-07	1.70E-06
+];
+figure(7), clf
+criterion = 1e-7;
+c1=contour(f, levels, with,[criterion criterion])
+hold on
+c2=contour(f, levels, without,[criterion criterion])
+title(['criterion= ' num2str(criterion)])
+set(gca,'Xscale','log')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/compareMicrophonic.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,43 @@
+% these data are generated by the testBM program
+
+
+f=[250   500  1000  2000  4000  8000];
+levels=-10:10:90;
+
+with=[
+3.00036e-010	2.9476e-010	3.67369e-010	2.69424e-010	2.61262e-010	7.18365e-011
+9.48796e-010	9.32111e-010	1.16172e-009	8.51994e-010	8.26184e-010	2.27167e-010
+3.00036e-009	2.9476e-009	3.67369e-009	2.69424e-009	2.61262e-009	7.18365e-010
+9.48796e-009	9.32126e-009	1.16172e-008	8.51994e-009	8.26184e-009	2.27167e-009
+2.98964e-008	3.30801e-008	4.3799e-008	2.85983e-008	2.12715e-008	7.18365e-009
+8.08142e-008	1.0005e-007	1.0854e-007	8.23884e-008	6.41103e-008	1.57936e-008
+1.4489e-007	1.70294e-007	1.67989e-007	1.37031e-007	9.77912e-008	3.74565e-008
+1.9871e-007	2.56245e-007	2.50429e-007	1.82704e-007	1.2266e-007	5.73054e-008
+2.80266e-007	4.15464e-007	4.42073e-007	3.65116e-007	3.24109e-007	6.7619e-008
+4.49308e-007	8.26643e-007	1.0501e-006	9.22625e-007	9.46576e-007	2.13766e-007
+8.73737e-007	2.1498e-006	2.9006e-006	2.61691e-006	2.90337e-006	6.36048e-007
+];
+
+without=[
+1.85179e-009	1.84842e-009	2.29365e-009	1.68885e-009	1.64802e-009	4.53194e-010
+5.85587e-009	5.84521e-009	7.25317e-009	5.34061e-009	5.2115e-009	1.43313e-009
+1.85179e-008	1.84842e-008	2.39525e-008	1.67348e-008	1.41015e-008	4.53194e-009
+5.70059e-008	6.97074e-008	8.049e-008	5.93827e-008	4.75289e-008	1.43313e-008
+1.21363e-007	1.42557e-007	1.42791e-007	1.14796e-007	8.59727e-008	2.31062e-008
+1.7631e-007	2.1607e-007	2.05558e-007	1.61584e-007	1.09552e-007	5.05732e-008
+2.41242e-007	3.44485e-007	3.25688e-007	2.57527e-007	2.17035e-007	6.31655e-008
+3.64591e-007	5.90911e-007	7.23077e-007	6.17822e-007	6.09472e-007	1.38217e-007
+6.52753e-007	1.44434e-006	1.89854e-006	1.69908e-006	1.84634e-006	4.09033e-007
+1.43691e-006	4.03513e-006	5.54045e-006	5.04855e-006	5.73398e-006	1.24307e-006
+3.75649e-006	1.20961e-005	1.69372e-005	1.55783e-005	1.7989e-005	3.87293e-006
+];
+
+
+figure(7), clf
+criterion = 1e-7;
+c1=contour(f, levels, with,[criterion criterion])
+
+hold on
+c2=contour(f, levels, without,[criterion criterion])
+title(['criterion= ' num2str(criterion)])
+set(gca,'Xscale','log')
Binary file multithreshold 1.46/ding.wav has changed
Binary file multithreshold 1.46/expGUI_MT.fig has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/expGUI_MT.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,1647 @@
+% expGUI_MT = 'experimenter GUI for multiThreshold
+% allows the experimenter to design experiments.
+% The *running* of experiments is left to subjGUI.m
+% 
+% There are three kinds of experiments known as 'earOptions':
+% 1. Measurements using real listeners 
+%  'left', 'right',  'diotic', 'dichoticLeft', 'dichoticRight'
+% 2. Measurements using the MAP model as the subject
+%   'MAPmodelListen',  'MAPmodelMultiCh', 'MAPmodelSingleCh'
+% 3. Monte Carlo simulations
+%   'statsModelLogistic','statsModelRareEvent'
+%
+% There are many stimulus configurations relating to different measurement
+% requirements. These configurations are defined in paradigm files located
+% in the 'paradigms' folder with names of the form paradigm_<name>.m. These
+% files specify values in the stimulusParameter and experiment structures.
+% Some minor parameters are specified in the intialiseGUI function below.
+% Each configuration is only a start up arrangement and the user can modify
+% the parameters on the GUI itself.
+%
+% the 'RUN' button initiates the measurements and hands control over to the
+% subjGUI program. When the measurements are complete control is handed
+% back and the stack unwinds without any further action
+
+function varargout = expGUI_MT(varargin)
+%EXPGUI_MT M-file for expGUI_MT.fig
+%      EXPGUI_MT, by itself, creates a new EXPGUI_MT or raises the existing
+%      singleton*.
+%
+%      H = EXPGUI_MT returns the handle to a new EXPGUI_MT or the handle to
+%      the existing singleton*.
+%
+%      EXPGUI_MT('Property','Value',...) creates a new EXPGUI_MT using the
+%      given property value pairs. Unrecognized properties are passed via
+%      varargin to expGUI_MT_OpeningFcn.  This calling syntax produces a
+%      warning when there is an existing singleton*.
+%
+%      EXPGUI_MT('CALLBACK') and EXPGUI_MT('CALLBACK',hObject,...) call the
+%      local function named CALLBACK in EXPGUI_MT.M with the given input
+%      arguments.
+%
+%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
+%      instance to run (singleton)".
+%
+% See also: GUIDE, GUIDATA, GUIHANDLES
+
+% Edit the above text to modify the response to help expGUI_MT
+
+% Last Modified by GUIDE v2.5 07-Apr-2011 07:20:00
+
+% Begin initialization code - DO NOT EDIT
+gui_Singleton = 1;
+gui_State = struct('gui_Name',       mfilename, ...
+    'gui_Singleton',  gui_Singleton, ...
+    'gui_OpeningFcn', @expGUI_MT_OpeningFcn, ...
+    'gui_OutputFcn',  @expGUI_MT_OutputFcn, ...
+    'gui_LayoutFcn',  [], ...
+    'gui_Callback',   []);
+if nargin && ischar(varargin{1})
+    gui_State.gui_Callback = str2func(varargin{1});
+end
+
+if nargout
+    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
+else
+    gui_mainfcn(gui_State, varargin{:});
+end
+% End initialization code - DO NOT EDIT
+
+% --------------------------------------------------  expGUI_MT_OpeningFcn
+function expGUI_MT_OpeningFcn(hObject, eventdata, handles, varargin)
+
+% Choose default command line output for expGUI_MT
+handles.output = hObject;
+
+cla(handles.axes1)
+cla(handles.axes2)
+cla(handles.axes4)
+cla(handles.axes5)
+
+% Update handles structure
+guidata(hObject, handles);
+
+function varargout = expGUI_MT_OutputFcn(hObject, eventdata, handles)
+% Get default command line output from handles structure
+initializeGUI(handles)
+varargout{1} = handles.output;
+setLocationOfGUIs(handles)
+
+function setLocationOfGUIs(handles)
+global checkForPreviousGUI  % holds screen positioning across repeated calls 
+scrnsize=get(0,'screensize');
+checkForPreviousGUI=[];
+% if isstruct(checkForPreviousGUI)...
+%         && checkForPreviousGUI.GUIalreadyStarted==1 ...
+%         && isfield(checkForPreviousGUI,'GUIposition')
+%     set(handles.figure1,'position',checkForPreviousGUI.GUIposition)
+% else
+%     % relocate the GUI only if this is the first time of use
+%     set(0, 'units','pixels')
+%     % occupies top to bottom of screen but only 60% width
+%     % [left bottom width height]
+%     firstPos=[0.01*scrnsize(4) 0.03*scrnsize(3) 0.6*scrnsize(3) 0.92*scrnsize(4)];
+%     firstPos=[4 0.045*scrnsize(4) 0.6*scrnsize(3) 0.93*scrnsize(4)];
+%     set(handles.figure1, 'units','pixels')
+%     set(handles.figure1,'position',firstPos)
+%     checkForPreviousGUI.GUIalreadyStarted=1;
+%     checkForPreviousGUI.GUIposition=firstPos;
+% end
+set(handles.figure1,'color',[.871 .961 .996])
+set(handles.figure1,'name', pwd)
+
+% MAP model figure; sits alongside GUI if requested
+figure(99)
+% [left bottom width height]
+MAPpos=[0.615*scrnsize(3) 0.05*scrnsize(4) 0.15*scrnsize(3) 0.85*scrnsize(4)];
+% visible only on request.
+set(gcf,'position',MAPpos , 'visible','off')
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% -----------------------------------------------------initializeGUI
+function initializeGUI(handles)
+% Populate the edit boxes and popup menus on the GUI
+% Then wait for user action
+global stimulusParameters experiment betweenRuns
+global targetTypes maskerTypes backgroundTypes
+global variableNames paradigmNames threshEstNames  cueNames
+
+% dbstop if error         % allow for debugging and user error reporting
+% dbstop if warning
+
+% specify structure fields for pretty automatic printing
+% It also initialises some simple variables
+orderGlobals
+
+addpath ('paradigms')   % preset paradigm informations is stored here
+% filesep is usd to be compatible with other operating systems
+% addpath (['..' filesep 'modules'], ['..' filesep 'utilities'], ...
+%     ['..' filesep 'parameterStore'],  ['..' filesep 'wavFileStore'],...
+%     ['..' filesep 'testPrograms'])
+
+% specify all variables that  need to be set on the GUI
+variableNames={'stimulusDelay','maskerDuration','maskerLevel',...
+    'maskerRelativeFrequency', 'targetFrequency', 'gapDuration',...
+    'targetDuration','targetLevel','rampDuration',...
+    'cueTestDifference', 'WRVstartValues', 'WRVsteps', 'WRVlimits'};
+
+% Variable variables
+% (specifies paradigm paramaters that can changed on a 'between runs' basis)
+% make them options in the two between runs variable menus
+% NB 'numOHIOtones' is used only to solve a problem; it should not be
+% selected manually
+betweenRunsVariables={'stimulusDelay','maskerDuration','maskerLevel',...
+    'maskerRelativeFrequency','targetFrequency', 'gapDuration',...
+    'targetDuration','targetLevel','numOHIOtones'};
+set(handles.popupmenuVaryParameter1,'string',betweenRunsVariables)
+set(handles.popupmenuVaryParameter2,'string',betweenRunsVariables)
+
+% NB 'Warning: popupmenu control requires a scalar Value'
+% indicates that an inappropriate 'value' is being set.
+% when testing for this, always clear the GUI before running
+
+% Trial presentation order - randomize at startup
+presentationOrderNames={'randomize within blocks', 'fixed sequence', ...
+    'randomize across blocks'};
+set(handles.popupmenuRandomize,'string', presentationOrderNames)
+
+% targetType- value must be set in paradigm
+targetTypes={'tone','noise', 'pinkNoise','whiteNoise','24TalkerBabble',...
+    'speech', 'Twister','digitStrings'};
+set(handles.popupmenuTargetType, 'string', targetTypes);
+
+% maskerType - value must be set in paradigm
+maskerTypes={'tone','noise', 'pinkNoise','TEN','whiteNoise','24TalkerBabble', ...
+    'speech'};
+set(handles.popupmenuMaskerType, 'string', maskerTypes);
+
+% background Type- value must be set in paradigm (default = 1, 'none')
+backgroundTypes={'none','noise', 'pinkNoise', 'TEN','noiseDich',...
+    'pinkNoiseDich','whiteNoise','24TalkerBabble',...
+    '16TalkerBabble','8TalkerBabble','4TalkerBabble',...
+    '4TalkerReversedBabble','2TalkerBabble','1TalkerBabble'};
+set(handles.popupmenuBackgroundType, 'string', backgroundTypes);
+set(handles.editBackgroundLevel,'string',...
+    num2str(stimulusParameters.backgroundLevel))
+
+% Establish available paradigms by scanning paradigms folder
+paradigmNames= what('paradigms');
+paradigmNames=paradigmNames.m;       % m files only
+for i=1:length(paradigmNames), paradigmNames{i}=paradigmNames{i}(10:end-2); end
+set(handles.popupmenuParadigm,'string', paradigmNames)
+
+% startup paradigm, 'training' (could be anywhere on the list)
+startupParadigm='training';
+idx= find(strcmp(paradigmNames,startupParadigm));
+if ~isempty(idx)
+    set(handles.popupmenuParadigm,'value', idx)
+else
+    % training paradigm is always the startup paradigm
+    error(['expGUI_MT\initializeGUI: No ' startupParadigm...
+        ' paradigm found in paradigms folder'])
+end
+
+earOptions={'left', 'right',  'diotic', 'dichoticLeft', 'dichoticRight',...
+    'MAPmodelListen',  'MAPmodelMultiCh', 'MAPmodelSingleCh'...
+    'statsModelLogistic','statsModelRareEvent'};
+set(handles.popupmenuEar,'string', earOptions)
+defaultOption=1;
+experiment.ear=earOptions{defaultOption};
+set(handles.popupmenuEar,'value', defaultOption)    % 'left' is deafult
+set(handles.pushbuttonSingleShot, 'visible', 'off') % use only for MAP
+
+% masker phase box- value must be set in paradigm
+phaseOptions={'sin','cos','alt','rand'};
+set(handles.popupmenuPhase,'string', phaseOptions)
+
+% Cue
+cueNames={'cued', 'noCue'};
+set(handles.popupmenuCueNoCue, 'string', cueNames);
+
+% threshold assessment method - value must be set in paradigm
+threshEstNames={'oneIntervalUpDown', 'MaxLikelihood', ...
+    '2I2AFC++', '2I2AFC+++'};
+set(handles.popupmenuThreshEst, 'string', threshEstNames);
+experiment.stopCriteria2IFC=[75 3 5];
+experiment.stopCriteriaSI=[20];
+
+% ** editBoxes that are only set by hand
+% music (relative) level, 'tada!' (manual setting only)
+% increase for the hard of hearing
+set(handles.editMusicLevel,'string','0')
+
+% Catch Trial Rate
+set(handles.editCatchTrialRate,'string','0.2   0.1  2 ');
+
+% calibration
+stimulusParameters.restoreCalibration=7;
+set(handles.editcalibrationdB,'string',...
+    stimulusParameters.restoreCalibration)
+
+% a MAPplot
+experiment.MAPplot=0;	%default
+set(handles.editMAPplot,'string',num2str(experiment.MAPplot))
+
+% saveData
+experiment.saveData=1;
+set(handles.editSaveData,'string',num2str(experiment.saveData))
+
+% printTracks
+experiment.printTracks=0;
+set(handles.editPrintTracks,'string',num2str(experiment.printTracks))
+
+% standard delay between button press and initiation of next stimulus
+experiment.clickToStimulusPause=1;
+
+% buttonBoxType: NB no problem if mouse is used instead
+experiment.buttonBoxType='square';
+
+% estimation of the mean
+% {'logisticLS', 'logisticML', 'rareEvent'}
+experiment.functionEstMethod='logisticLS';
+
+% message box
+set(handles.textMSG,'backgroundcolor', 'w', 'ForegroundColor', 'b', 'string', '')
+set(handles.editMsgFont,'string','7')
+set(handles.editSubjectFont,'string','14')
+
+% default psychometric bin size and logistic slopes
+experiment.psyBinWidth=1;  % dB
+maxLogisticK=2; % steepest slope contemplated
+experiment.maxLogisticK=maxLogisticK;
+experiment.numPossLogisticK=100;
+experiment.possLogSlopes= ...
+    0.01: maxLogisticK/experiment.numPossLogisticK: maxLogisticK;
+experiment.meanSearchStep=0.25; % dB
+
+% indicate that this is the first run and the GUI should be located in
+% default location.
+experiment.justInitialized=1;
+
+% set up GUI based on training paradigm
+aParadigmSelection(handles);
+earSetUp(handles)
+aThresholdAssessmentMethod(handles)
+aShowRelevantObjects(handles)
+
+% Done. Now wait for action
+
+% -------------------------------------------- popupmenuMaskerType_Callback
+function popupmenuMaskerType_Callback(hObject, eventdata, handles)
+% show or remove masker frequency box
+aShowRelevantObjects(handles)
+
+% -------------------------------------------- popupmenuTargetType_Callback
+function popupmenuTargetType_Callback(hObject, eventdata, handles)
+% show or remove target frequency box
+aShowRelevantObjects(handles)
+
+% -------------------------------------------- popupmenuParadigm_Callback
+function popupmenuParadigm_Callback(hObject, eventdata, handles)
+% Any change to the paradigm selection causes all boxes to be shown
+% showParameters(handles)
+aParadigmSelection(handles);
+
+% -------------------------------------------- aParadigmSelection
+function aParadigmSelection(handles)
+global experiment stimulusParameters betweenRuns  paradigmNames
+global variableNames
+
+% identify paradigm selected
+chosenOption=get(handles.popupmenuParadigm,'value');
+paradigm=paradigmNames{chosenOption};
+experiment.paradigm=paradigm;
+
+%Paradigm: read in all relevant parameters
+% a file must exist with this name 'paradigm_<paradigm>'
+% 'handles' are only occasionally used
+addpath ('paradigms')
+cmd=['paradigm_' paradigm '(handles);'];
+try
+    eval(cmd)
+catch
+    error(['ExpGUI\aParadigmSelection:'...
+        'paradigm file not found or error in file'])
+end
+rmpath ('paradigms')
+
+% if a variable is subject to change, specify list of values here
+% eg. stimulusParameters.targetFrequency=betweenRuns.variableList1;
+cmd=['stimulusParameters.' ...
+    betweenRuns.variableName1 '=betweenRuns.variableList1;'];
+eval (cmd);
+cmd=['stimulusParameters.' ...
+    betweenRuns.variableName2 '=betweenRuns.variableList2;'];
+eval (cmd);
+
+% establish popup menus on the basis of the paradigm file
+set(handles.popupmenuRandomize,'value', betweenRuns.randomizeSequence)	
+set(handles.popupmenuPhase,'string', stimulusParameters.maskerPhase)
+if stimulusParameters.includeCue
+    set(handles.popupmenuCueNoCue,'value', 1)
+else
+    set(handles.popupmenuCueNoCue,'value', 2)
+end
+
+set(handles.text34, 'string', stimulusParameters.WRVname)
+
+% Put the new data values into the edit boxes on the GUI
+for i=1:length(variableNames)
+    cmd=(['set(handles.edit' variableNames{i} ...
+        ',''string'', num2str(stimulusParameters.' ...
+        variableNames{i} '));']);
+    eval(cmd);
+end
+% backgroundLevel is not a variableName (?!)
+set(handles.editBackgroundLevel,'string', num2str...
+    (stimulusParameters.backgroundLevel))
+
+% on RUN the sample rate will be picked from the text box
+% However, MAP overrules the sample rate and sets its own
+aSetSampleRate(stimulusParameters.subjectSampleRate, handles);
+
+
+% used for plotting functions (NB affected by paradigm settings)
+experiment.predictionLevels=stimulusParameters.WRVlimits(1):...
+    experiment.meanSearchStep:stimulusParameters.WRVlimits(2);
+experiment.possLogSlopes=abs(experiment.possLogSlopes)*...
+    sign(experiment.psyFunSlope);
+
+aResetPopupMenus(handles)
+
+% ------------------------------------------------------ aResetPopupMenus
+function aResetPopupMenus(handles)
+global   stimulusParameters betweenRuns variableNames 
+global targetTypes maskerTypes experiment backgroundTypes
+
+switch experiment.threshEstMethod
+    case {'MaxLikelihood','oneIntervalUpDown'}
+        set(handles.editstopCriteriaBox, 'string', ...
+            num2str(experiment.singleIntervalMaxTrials))
+        
+    case {'2I2AFC++','2I2AFC+++'}
+        set(handles.editstopCriteriaBox, 'string', ...
+            num2str(experiment.stopCriteria2IFC))
+    otherwise
+        error([' aResetPopupMenus:  threshEstMethod not recognised -> ' ...
+            experiment.threshEstMethod])
+end
+
+% forced noCue
+switch experiment.paradigm
+    case 'discomfort'
+        set(handles.popupmenuCueNoCue,'value', 2)
+end
+
+%set variables popupmenus as specified in betweenRuns
+variableParameter1ID=0; variableParameter2ID=0;
+for i=1:length(variableNames)
+    if strcmp(variableNames{i},betweenRuns.variableName1)
+        variableParameter1ID=i;
+    end   
+    if strcmp(variableNames{i},betweenRuns.variableName2)
+        variableParameter2ID=i;
+    end
+end
+if variableParameter1ID==0 || variableParameter2ID==0;
+    Error('a ResetPopMenu: variableParameter not identified')
+end
+
+% display popupmenus
+set(handles.popupmenuVaryParameter1, 'value',round(variableParameter1ID))
+set(handles.popupmenuVaryParameter2, 'value',round(variableParameter2ID))
+
+% targetType
+idx= find(strcmp(stimulusParameters.targetType, targetTypes));
+set(handles.popupmenuTargetType,'value', idx)
+
+% paradigm selection may alter the maskerType
+idx= find(strcmp(stimulusParameters.maskerType, maskerTypes));
+set(handles.popupmenuMaskerType,'value', idx)
+
+aShowRelevantObjects(handles)
+
+% % backgroundType
+idx= find(strcmp(stimulusParameters.backgroundType, backgroundTypes));
+set(handles.popupmenuBackgroundType,'value', idx)
+set(handles.editBackgroundLevel,'string', ...
+    num2str(stimulusParameters.backgroundLevel))
+
+% ---------------------------------------------- aShowRelevantObjects
+function aShowRelevantObjects(handles)
+global experiment stimulusParameters
+% always on
+set(handles.edittargetLevel, 'visible', 'on')
+set(handles.edittargetDuration, 'visible', 'on')
+set(handles.edittargetFrequency, 'visible', 'on')
+
+switch experiment.ear
+    case {'statsModelLogistic', 'statsModelRareEvent'}
+        set(handles.editStatsModel, 'visible', 'on')
+        set(handles.textStatsModel, 'visible', 'on')
+        set(handles.pushbuttonStop, 'visible', 'on')
+        set(handles.pushbuttonOME, 'visible', 'off')
+        set(handles.pushbuttonBM, 'visible', 'off')
+        set(handles.pushbuttonRP, 'visible', 'off')
+        set(handles.pushbuttonAN, 'visible', 'off')
+        set(handles.pushbuttonRF, 'visible', 'off')
+        set(handles.pushbuttonSYN, 'visible', 'off')
+        set(handles.pushbuttonFM, 'visible', 'off')
+        set(handles.pushbuttonParams, 'visible', 'off')
+        set(handles.pushbuttonSingleShot, 'visible', 'off')
+        set(handles.editCatchTrialRate, 'visible', 'off')
+        set(handles.textCatchTrials, 'visible', 'off')
+        set(handles.editcalibrationdB, 'visible', 'off')
+        set(handles.textcalibration, 'visible', 'off')
+        set(handles.popupmenuCueNoCue, 'visible', 'off')
+        set(handles.textCue, 'visible', 'off')
+        set(handles.editMusicLevel,'visible', 'off')
+        set(handles.textMusicLevel,'visible', 'off')
+        set(handles.editMAPplot,'visible', 'off')
+        set(handles.textMAPplot,'visible', 'off')
+        
+    case {'MAPmodel',  'MAPmodelListen', 'MAPmodelMultiCh', 'MAPmodelSingleCh'}
+        set(handles.popupmenuCueNoCue, 'visible', 'off')
+        set(handles.editStatsModel, 'visible', 'off')
+        set(handles.textStatsModel, 'visible', 'off')
+        set(handles.pushbuttonStop, 'visible', 'on')
+        set(handles.pushbuttonOME, 'visible', 'on')
+        set(handles.pushbuttonBM, 'visible', 'on')
+        set(handles.pushbuttonRP, 'visible', 'on')
+        set(handles.pushbuttonAN, 'visible', 'on')
+        set(handles.pushbuttonRF, 'visible', 'on')
+        set(handles.pushbuttonSYN, 'visible', 'on')
+        set(handles.pushbuttonFM, 'visible', 'on')
+        set(handles.pushbuttonParams, 'visible', 'on')
+        set(handles.pushbuttonSingleShot, 'visible', 'on')
+        set(handles.editcalibrationdB, 'visible', 'off')
+        set(handles.textcalibration, 'visible', 'off')
+        set(handles.textCue, 'visible', 'off')
+        set(handles.editMusicLevel,'visible', 'off')
+        set(handles.textMusicLevel,'visible', 'off')
+        set(handles.editMAPplot,'visible', 'on')
+        set(handles.textMAPplot,'visible', 'on')
+        
+    otherwise
+        set(handles.editStatsModel, 'visible', 'off')
+        set(handles.textStatsModel, 'visible', 'off')
+        set(handles.pushbuttonStop, 'visible', 'off')
+        set(handles.pushbuttonOME, 'visible', 'off')
+        set(handles.pushbuttonBM, 'visible', 'off')
+        set(handles.pushbuttonRP, 'visible', 'off')
+        set(handles.pushbuttonAN, 'visible', 'off')
+        set(handles.pushbuttonRF, 'visible', 'off')
+        set(handles.pushbuttonSYN, 'visible', 'off')
+        set(handles.pushbuttonFM, 'visible', 'off')
+        set(handles.pushbuttonParams, 'visible', 'off')
+        set(handles.pushbuttonSingleShot, 'visible', 'off')
+        set(handles.editCatchTrialRate, 'visible', 'on')
+        set(handles.textCatchTrials, 'visible', 'on')
+        set(handles.editcalibrationdB, 'visible', 'on')
+        set(handles.textcalibration, 'visible', 'on')
+        set(handles.popupmenuCueNoCue, 'visible', 'on')
+        set(handles.textCue, 'visible', 'on')
+        set(handles.editMusicLevel,'visible', 'on')
+        set(handles.textMusicLevel,'visible', 'on')
+        set(handles.editMAPplot,'visible', 'off')
+        set(handles.textMAPplot,'visible', 'off')
+end
+
+switch experiment.threshEstMethod
+    case {'MaxLikelihood','oneIntervalUpDown'}
+        set(handles.popupmenuCueNoCue,'visible', 'on')
+        set(handles.textCue,'visible', 'on')
+        set(handles.editstopCriteriaBox, 'string', ...
+            num2str(experiment.singleIntervalMaxTrials))
+        
+        if stimulusParameters.includeCue==0
+            set(handles.editcueTestDifference,'visible', 'off')
+            set(handles.textcueTestDifference,'visible', 'off')
+        else
+            set(handles.editcueTestDifference,'visible', 'on')
+            set(handles.textcueTestDifference,'visible', 'on')
+        end
+        
+    case {'2I2AFC++','2I2AFC+++'}
+        set(handles.editCatchTrialRate, 'visible', 'off')
+        set(handles.textCatchTrials, 'visible', 'off')
+        set(handles.popupmenuCueNoCue,'visible', 'off')
+        set(handles.textCue,'visible', 'off')
+        set(handles.editcueTestDifference,'visible', 'off')
+        set(handles.textcueTestDifference,'visible', 'off')
+end
+
+
+% show/ remove masker related boxes
+switch experiment.paradigm
+    % masker free paradigms
+    case {'training', 'discomfort','absThreshold', 'absThreshold_8',...
+            'TENtest', 'threshold_duration','SRT'}
+        set(handles.editmaskerDuration,'visible', 'off')
+        set(handles.editmaskerLevel,'visible', 'off')
+        set(handles.editmaskerRelativeFrequency,'visible', 'off')
+        set(handles.editgapDuration,'visible', 'off')
+        set(handles.textmaskerDuration,'visible', 'off')
+        set(handles.textmaskerLevel,'visible', 'off')
+        set(handles.textmaskerRelativeFrequency,'visible', 'off')
+        set(handles.textgapDuration,'visible', 'off')
+        set(handles.popupmenuMaskerType,'visible', 'off')
+        set(handles.textMaskerType,'visible', 'off')
+        
+        % paradigms with maskers
+    case {'forwardMasking','forwardMaskingD','trainingIFMC', 'TMC','TMC_16ms', ...
+           'TMCmodel','IFMC','IFMC_8ms','GOM','overShoot','overShootB',...
+           'gapDetection', 'psychometric', 'FMreProbe'}
+        set(handles.editmaskerDuration,'visible', 'on')
+        set(handles.editmaskerLevel,'visible', 'on')
+        set(handles.editmaskerRelativeFrequency,'visible', 'on')
+        set(handles.editgapDuration,'visible', 'on')
+        set(handles.popupmenuMaskerType,'visible', 'on')
+        set(handles.textmaskerDuration,'visible', 'on')
+        set(handles.textmaskerLevel,'visible', 'on')
+        set(handles.textmaskerRelativeFrequency,'visible', 'on')
+        set(handles.textgapDuration,'visible', 'on')
+        set(handles.popupmenuMaskerType,'visible', 'on')
+        set(handles.textMaskerType,'visible', 'on')
+        % masker relative frequency /type
+        chosenOption=get(handles.popupmenuMaskerType,'value');
+        maskerTypes=get(handles.popupmenuMaskerType,'string');
+        maskerType=maskerTypes{chosenOption};
+        switch maskerType
+            case 'tone'
+                set(handles.editmaskerRelativeFrequency,'visible', 'on')
+            otherwise
+                set(handles.editmaskerRelativeFrequency,'visible', 'off')
+        end
+end
+
+eval(['set(handles.edit' stimulusParameters.WRVname ...
+    ',''visible'',''off'' )'])
+
+% target type
+chosenOption=get(handles.popupmenuTargetType,'value');
+targetTypes=get(handles.popupmenuTargetType,'string');
+targetType=targetTypes{chosenOption};
+switch targetType
+    case 'tone'
+        set(handles.edittargetFrequency,'visible', 'on')
+    otherwise
+        set(handles.edittargetFrequency,'visible', 'off')
+end
+
+if strcmp(stimulusParameters.backgroundType,'none')
+    set(handles.popupmenuBackgroundType, 'visible', 'on');
+    set(handles.editBackgroundLevel,'visible','off')
+    set(handles.textBGlevel,'visible','off')
+else
+    set(handles.popupmenuBackgroundType, 'visible', 'on');
+    set(handles.editBackgroundLevel,'visible','on')
+    set(handles.textBGlevel,'visible','on')
+end
+
+
+
+% ------------------------------------------------ pushbuttonRun_Callback
+function pushbuttonRun_Callback(hObject, eventdata, handles)
+global checkForPreviousGUI % holds screen positioning across repeated calls 
+global experiment
+checkForPreviousGUI.GUIposition=get(handles.figure1,'position');
+experiment.singleShot=0;
+run (handles)
+experiment.stop=0;
+
+function run (handles)
+global experiment expGUIhandles stimulusParameters
+tic
+expGUIhandles=handles;
+set(handles.pushbuttonStop, 'backgroundColor', [.941 .941 .941])
+
+% message box white (removes any previous error message)
+set(handles.textMSG,...
+    'backgroundcolor', 'w', 'ForegroundColor', 'b', 'string', '')
+
+errorMsg=aReadAndCheckParameterBoxes(handles);
+if ~isempty(errorMsg)
+    append=0;
+    warning=1;
+    addToMsg(['error message:' errorMsg], append, warning)
+    return
+end
+
+if isnan(stimulusParameters.targetLevel)
+    addToMsg('Error: targetlevel not set', 1)
+    error('Error: targetlevel not set')
+end
+
+set(handles.textMSG,'backgroundcolor', 'w')
+set(handles.textMSG,'string', ' ')
+
+% leave the program and start up multiThreshold
+subjGUI_MT % leave the program and start up multiThreshold
+experiment.justInitialized=0;% prevents moving subjectGUI
+toc
+
+% --- Executes on button press in pushbuttonSingleShot.
+function pushbuttonSingleShot_Callback(hObject, eventdata, handles)
+global experiment 
+experiment.singleShot=1;
+
+% special test for spontaneous activity
+x=get(handles.editWRVstartValues, 'string');
+y=get(handles.edittargetDuration, 'string');
+set(handles.editWRVstartValues, 'string', '-20')
+set(handles.edittargetDuration, 'string', '1')
+
+MAPplot=get(handles.editMAPplot, 'string');
+set(handles.editMAPplot, 'string', '1')
+drawnow
+
+run (handles)
+
+set(handles.editMAPplot, 'string', MAPplot)
+set(handles.editWRVstartValues, 'string', x)
+set(handles.edittargetDuration, 'string', y)
+
+% ------------------------------------------aReadAndCheckParameterBoxes
+function errorMsg=aReadAndCheckParameterBoxes(handles)
+global experiment  stimulusParameters betweenRuns  statsModel
+global variableNames  LevittControl
+% When the program sets the parameters all should be well
+% But when the user changes them...
+
+errorMsg='';
+
+% name
+experiment.name=get(handles.editName,'string');
+
+% ear/models
+option=get(handles.popupmenuEar,'value');
+strings=get(handles.popupmenuEar,'string');
+experiment.ear=strings{option};
+
+switch experiment.ear
+    case { 'MAPmodel', 'MAPmodelMultiCh', ...
+            'MAPmodelSingleCh', 'MAPmodelListen'}         
+        % MAPmodel writes forced parameter settings to the screen 
+        %  so that they can be read from there
+        set(handles.popupmenuRandomize,'value',2)       % fixed sequence
+        set(handles.editstimulusDelay,'string','0.01')  % no stimulus delay
+        stimulusParameters.includeCue=0;                % no cue for MAP
+end
+
+% find tone type
+option=get(handles.popupmenuTargetType,'value');
+strings=get(handles.popupmenuTargetType,'string');
+stimulusParameters.targetType=strings{option};
+
+% find masker type
+option=get(handles.popupmenuMaskerType,'value');
+strings=get(handles.popupmenuMaskerType,'string');
+stimulusParameters.maskerType=strings{option};
+
+% find background type and level
+option=get(handles.popupmenuBackgroundType,'value');
+strings=get(handles.popupmenuBackgroundType,'string');
+stimulusParameters.backgroundTypeValue=option;
+stimulusParameters.backgroundLevel=...
+    str2num(get(handles.editBackgroundLevel,'string'));
+stimulusParameters.backgroundType=strings{option};
+
+% Read all stimulus parameter boxes
+for i=1:length(variableNames)
+    cmd=['stimulusParameters.' variableNames{i} ...
+        '= str2num(get(handles.edit' variableNames{i} ',''string'' ));'];
+    eval(cmd);
+end
+% for multiple levels
+stimulusParameters.targetLevels=stimulusParameters.targetLevel;
+
+% check that all required values are in the edit boxes
+for i=1:length(variableNames)-3 % do not include 'level limits'
+    eval([ 'variableValues=stimulusParameters.' variableNames{i} ';'])
+    if isempty(variableValues), errorMsg=[ variableNames{i} ...
+            ' is an empty box']; return, end
+end
+
+chosenOption=get(handles.popupmenuVaryParameter1,'value');
+betweenRuns.variableName1=variableNames{chosenOption};
+eval(['betweenRuns.variableList1 = stimulusParameters.' ...
+    betweenRuns.variableName1 ';']);
+
+chosenOption=get(handles.popupmenuVaryParameter2,'value');
+betweenRuns.variableName2=variableNames{chosenOption};
+eval(['betweenRuns.variableList2 = stimulusParameters.' ...
+    betweenRuns.variableName2 ';']);
+
+% Check that variable parameters 1 & 2 have different names
+if strcmp(betweenRuns.variableName1,betweenRuns.variableName2) ...
+        && ~strcmp(betweenRuns.variableName1,'none')
+    errorMsg='variable parameters have the same name';
+    return
+end
+
+% calibration
+%  this is used to *reduce* the output signal from what it otherwise 
+%  would be
+% signal values are between 1 - 2^23
+%  these are interpreted as microPascals between -29 dB and 128 dB SPL
+% calibrationdB adjusts these values to compensate for equipment 
+%  characteristics
+%  this will change the range. e.g. a 7 dB calibration will yield 
+%   a range of -36 to 121 dB SPL
+% Calibration is not used when modelling. Values are treated as dB SPL
+stimulusParameters.calibrationdB=...
+    str2num(get(handles.editcalibrationdB,'string'));
+
+% check on cue
+cueSetUp(handles)
+
+stimulusParameters.WRVinitialStep=stimulusParameters.WRVsteps(1);
+stimulusParameters.WRVsmallStep=stimulusParameters.WRVsteps(2);
+
+% jitter start value set after reading in new parameters
+switch experiment.paradigm
+    case 'discomfort'
+        stimulusParameters.jitterStartdB=0;
+    otherwise
+        stimulusParameters.jitterStartdB=abs(stimulusParameters.WRVsteps(1));
+end
+
+
+% stats model mean and slope
+statsModelParameters= str2num(get(handles.editStatsModel,'string'));
+switch experiment.ear
+    case {'statsModelLogistic'}
+        statsModel.logisticMean=statsModelParameters(1) ;
+        statsModel.logisticSlope=statsModelParameters(2);
+        statsModel.rareEvenGain=NaN ;
+        statsModel.rareEventVmin=NaN;
+    case 'statsModelRareEvent'
+        statsModel.logisticMean=NaN ;
+        statsModel.logisticSlope=NaN;
+        statsModel.rareEvenGain=statsModelParameters(2) ;
+        statsModel.rareEventVmin=statsModelParameters(1);
+end
+
+% MAP plotting
+experiment.MAPplot=str2num(get(handles.editMAPplot,'string'));
+% if ~isequal(experiment.MAPplot, 0),
+%     % any other character will do it
+%     experiment.MAPplot=1;
+% end
+
+% save data
+experiment.saveData=str2num(get(handles.editSaveData,'string'));
+if ~isequal(experiment.saveData, 0),
+    % any other character will do it
+    experiment.saveData=1;
+end
+
+% print tracks
+experiment.printTracks=str2num(get(handles.editPrintTracks,'string'));
+if ~isequal(experiment.printTracks, 0),
+    % any other character will do it
+    experiment.printTracks=1;
+end
+
+% catch trial rate
+% (1)= start rate,   (2)= base rate,   (3)= time constant (trials)
+stimulusParameters.catchTrialRates=...
+    str2num(get(handles.editCatchTrialRate,'string'));
+if stimulusParameters.catchTrialRates(1) ...
+        < stimulusParameters.catchTrialRates(2)
+    errorMsg=...
+        'catch trial base rates must be less than catch trial start rate';
+    return,
+end
+
+% sample rate
+% The sample rate is set in the paradigm file.
+% Normally this is set in the startUp paradigm file and then left
+% When the model is used, the multiThreshold sample rate
+% overrules anything in the model
+stimulusParameters.sampleRate=...
+    str2num(get(handles.textsampleRate,'string'));
+
+% music level
+stimulusParameters.musicLeveldB=...
+    str2num(get(handles.editMusicLevel,'string'));
+
+%  set message box font size
+experiment.msgFontSize=str2num(get(handles.editMsgFont,'string'));
+experiment.subjGUIfontSize=str2num(get(handles.editSubjectFont,'string'));
+
+% stop criteria
+experiment.singleIntervalMaxTrials=...
+    str2num(get(handles.editstopCriteriaBox,'string'));
+experiment.maxTrials=experiment.singleIntervalMaxTrials(1);
+
+% set up 2IFC is required (? better in atrhesholdAssessmentMethod)
+switch experiment.threshEstMethod
+    case {'2I2AFC++', '2A2AIFC+++'}
+        experiment.peaksUsed=experiment.singleIntervalMaxTrials(2);
+        experiment.PeakTroughCriterionSD=...
+            experiment.singleIntervalMaxTrials(3);
+        experiment.trialsToBeUsed= 5;
+        LevittControl.maxTrials=experiment.singleIntervalMaxTrials(1);
+        % start value for step until reduced
+        LevittControl.startLevelStep= stimulusParameters.WRVsteps(1);
+        % reduced step size
+        LevittControl.steadyLevittStep= stimulusParameters.WRVsteps(2); 
+        LevittControl.TurnsToSmallSteps= 2;
+        LevittControl.useLastNturns= 2*experiment.peaksUsed;
+        LevittControl.minReversals= ...
+            LevittControl.TurnsToSmallSteps+2*experiment.peaksUsed;
+        LevittControl.targetsdPT = experiment.PeakTroughCriterionSD;
+        LevittControl.maxLevittValue= stimulusParameters.WRVlimits(2);
+        Levitt2;
+end
+
+% What kind of randomisation is required?
+idx=get(handles.popupmenuRandomize,'value');
+s=get(handles.popupmenuRandomize,'string');
+betweenRuns.randomizeSequence=s{idx};
+
+% Make small adjustments to variable values
+%  to keep values unique against later sorting
+x=betweenRuns.variableList1;
+[y idx]= sort(x);
+for i=1:length(y)-1, if y(i+1)==y(i); y(i+1)=y(i)*1.001; end, end
+x(idx)=y;
+betweenRuns.variableList1=x;
+
+x=betweenRuns.variableList2;
+[y idx]= sort(x);
+for i=1:length(y)-1, if y(i+1)==y(i); y(i+1)=y(i)*1.001; end, end
+x(idx)=y;
+betweenRuns.variableList2=x;
+
+% Checks: after reading and setting parameters  ------------------------------------------
+% check for finger trouble (more checks possible
+if stimulusParameters.maskerDuration>10
+    errorMsg='maskerDuration is too long'; return, end
+if stimulusParameters.gapDuration>10
+    errorMsg='gapDuration is too long'; return, end
+if stimulusParameters.targetDuration>10
+    errorMsg='targetDuration is too long'; return, end
+
+% rare event slope check
+if experiment.psyFunSlope<0 ...
+        && strcmp(experiment.functionEstMethod,'rareEvent')
+    errorMsg='cannot use rareEvent option for negative psychometr slopes';
+    return
+end
+
+% check ramps
+if stimulusParameters.rampDuration*2> stimulusParameters.targetDuration
+    errorMsg=' ramp duration is too long for the target';
+    return
+end
+
+if max(stimulusParameters.maskerDuration)>0 ...
+        && max(stimulusParameters.rampDuration...
+        *2> stimulusParameters.maskerDuration)
+    errorMsg=' ramp duration is too long for the masker';
+    return
+end
+
+% Check WRVstartValues for length and compatibility with randomization
+% only one start value supplied so all start values are the same
+if length(stimulusParameters.WRVstartValues)==1     
+    stimulusParameters.WRVstartValues= ...
+        repmat(stimulusParameters.WRVstartValues, 1, ...
+        length(betweenRuns.variableList1)...
+        *length(betweenRuns.variableList2));
+elseif ~isequal(length(stimulusParameters.WRVstartValues), ...
+        length(betweenRuns.variableList1)...
+        *length(betweenRuns.variableList2))
+    % otherwise we need one value for each combination of var1/ var2
+    errorMsg='WRVstartValues not the same length as number of runs';
+    return
+elseif strcmp(betweenRuns.randomizeSequence, 'randomize within blocks')...
+        && length(stimulusParameters.WRVstartValues)>1
+    errorMsg='multiple WRVstartValues inappropriate';
+    return
+end
+
+switch experiment.paradigm
+    %     case { 'TMC',  'TMCmodel','IFMC'}
+    case {'trainingIFMC', 'TMC','TMC_16ms', 'TMC - ELP', 'IFMC'}
+        
+        % For TMC and IFMC multiple target levels can be set
+        if length(stimulusParameters.targetLevel)==1
+            betweenRuns.targetLevels=...
+                repmat(stimulusParameters.targetLevel, 1, ...
+                length(betweenRuns.variableList1)...
+                *length(betweenRuns.variableList2));
+        elseif length(stimulusParameters.targetLevel)==...
+                length(betweenRuns.variableList2)
+            x=stimulusParameters.targetLevel;
+            x=repmat(x,length(betweenRuns.variableList1),1);
+            x=reshape(x,1,length(betweenRuns.variableList1)*length(betweenRuns.variableList2));
+            betweenRuns.targetLevels=x;
+        else
+            errorMsg='targetLevels not the same length as number of targetFrequencies';
+        end
+end
+
+switch experiment.paradigm
+    case  {'gapDetection', 'frequencyDiscrimination'}
+        if ~isequal(stimulusParameters.targetDuration, ...
+                stimulusParameters.maskerDuration)
+            addToMsg(...
+                'Warning: masker and target duration not the same.',1,1)
+        end        
+        if ~isequal(stimulusParameters.maskerLevel, ...
+                stimulusParameters.targetLevel)
+            addToMsg(['Warning: masker and target level different.'...
+                'They will be changed to be equal',1,1]);
+        end
+end
+
+% -------------------------------------------- aSetSampleRate
+function aSetSampleRate(sampleRate, handles)
+global  stimulusParameters
+stimulusParameters.sampleRate=sampleRate;
+set(handles.textsampleRate,'string',num2str(stimulusParameters.sampleRate))
+
+% -------------------------------------------- popupmenuEar_Callback
+function popupmenuEar_Callback(hObject, eventdata, handles)
+global experiment
+option=get(handles.popupmenuEar,'value');
+options=get(handles.popupmenuEar,'string');			% left/right/model
+experiment.ear=options{option};
+switch experiment.ear
+    case 'statsModelLogistic'
+        set(handles.editStatsModel,'string', '15, 0.5')
+    case 'statsModelRareEvent'
+        set(handles.editStatsModel,'string', '20 1')
+end
+earSetUp(handles)
+
+% -------------------------------------------- earSetUp
+function	earSetUp(handles)
+global experiment stimulusParameters
+% option=get(handles.popupmenuEar,'value');
+% options=get(handles.popupmenuEar,'string');			% left/right/model
+% experiment.ear=options{option};
+
+switch experiment.ear
+    case {'statsModelLogistic'}
+        statsModel.logisticSlope=0.5;
+        statsModel.logisticMean=15;
+        set(handles.editStatsModel,'string', ...
+            num2str([statsModel.logisticMean statsModel.logisticSlope]))
+        set(handles.textStatsModel,...
+            'string', {'statsModel',' logistic threshold\ slope'})
+    case 'statsModelRareEvent'
+        set(handles.textStatsModel,'string', ...
+            {'statsModel',' rareEvent Vmin\ gain'})
+end
+
+switch experiment.ear
+    case {'statsModelLogistic', 'statsModelRareEvent'}
+        set(handles.editStatsModel, 'visible', 'off')
+        set(handles.textStatsModel, 'visible', 'off')
+        
+        % default psychometric bin size and logistic slopes
+        set(handles.popupmenuRandomize,'value',2)   % fixed sequence
+        set(handles.editName,'string', 'statsModel')
+        %         experiment.headphonesUsed=0;
+        
+    case {'MAPmodelListen', 'MAPmodelMultiCh', 'MAPmodelSingleCh'}
+        stimulusParameters.includeCue=0;						 % no cue
+        set(handles.popupmenuCueNoCue,'value', 2)
+        
+        set(handles.editCatchTrialRate,'string','0 0  2 ');%no catch trials
+        set(handles.editName,'string', 'Normal')			% force name
+        experiment.name=get(handles.editName,'string');	% read name back
+        set(handles.editcalibrationdB,'string','0')	
+        
+        set(handles.popupmenuRandomize,'value',2)       % fixed sequence
+        set(handles.editstimulusDelay,'string','0')
+        
+        set(handles.editSaveData,'string', '0')
+        set(handles.editSubjectFont,'string', '10');
+        experiment.MacGThreshold=0; % num MacG spikes to exceed threshold
+end
+aResetPopupMenus(handles)
+
+% --------------------------------------------- popupmenuCueNoCue_Callback
+function popupmenuCueNoCue_Callback(hObject, eventdata, handles)
+cueSetUp(handles)
+
+% ------------------------------------------------------------- cueSetUp
+function cueSetUp(handles)
+global stimulusParameters
+
+chosenOption=get(handles.popupmenuCueNoCue,'value');
+if chosenOption==1
+    stimulusParameters.includeCue=1;
+    set(handles.editcueTestDifference,'visible', 'on')
+    set(handles.textcueTestDifference,'visible', 'on')
+    stimulusParameters.subjectText=stimulusParameters.instructions{2};
+else
+    stimulusParameters.includeCue=0;
+    set(handles.editcueTestDifference,'visible', 'off')
+    set(handles.textcueTestDifference,'visible', 'off')
+    stimulusParameters.subjectText= stimulusParameters.instructions{1};
+end
+
+% -------------------------------------------- popupmenuThreshEst_Callback
+function popupmenuThreshEst_Callback(hObject, eventdata, handles)
+aThresholdAssessmentMethod(handles);
+
+%  --------------------------------------------- aThresholdAssessmentMethod
+function aThresholdAssessmentMethod(handles)
+% identify the threshold assessment method
+%  and set various parameters on the GUI appropriately
+global stimulusParameters experiment  threshEstNames LevittControl
+
+chosenOption=get(handles.popupmenuThreshEst,'value');
+experiment.threshEstMethod=threshEstNames{chosenOption};
+set(handles.editCatchTrialRate, 'visible', 'on')
+set(handles.textCatchTrials, 'visible', 'on')
+
+% establish appropriate stop criterion and post on GUI
+switch experiment.threshEstMethod
+    case 'MaxLikelihood'
+        experiment.functionEstMethod='logisticML';
+        stimulusParameters.WRVsteps=10*experiment.psyFunSlope;  % ???
+        set(handles.textstopCriteria,'string', 'stop criteria \ maxTrials')
+        experiment.singleIntervalMaxTrials=experiment.stopCriteriaSI;
+        experiment.allowCatchTrials= 1;
+        switch experiment.paradigm
+            case 'training'
+                experiment.possLogSlopes=0.5;
+        end
+        
+    case 'oneIntervalUpDown'
+        experiment.functionEstMethod='logisticLS';
+        set(handles.textstopCriteria,'string', 'stop criteria \ maxTrials')
+        experiment.singleIntervalMaxTrials=experiment.stopCriteriaSI;
+        switch experiment.paradigm
+            case 'discomfort'
+                experiment.allowCatchTrials= 0;
+            otherwise
+                experiment.allowCatchTrials= 1;
+        end
+        
+    case {'2I2AFC++',  '2I2AFC+++'}
+        LevittControl.rule='++'; %  e.g. '++' or '+++'
+        experiment.singleIntervalMaxTrials=experiment.stopCriteria2IFC;
+        experiment.functionEstMethod='peaksAndTroughs';
+        LevittControl.maxTrials=experiment.singleIntervalMaxTrials(1);
+        set(handles.editWRVsteps,'string', ...
+            num2str(stimulusParameters.WRVsteps))
+        set(handles.textstopCriteria,'string', {'trials peaks sdCrit'})
+        experiment.allowCatchTrials= 0;
+end
+
+set(handles.textstopCriteria,'fontSize',8)
+set(handles.editstopCriteriaBox,'string',...
+    num2str(experiment.singleIntervalMaxTrials))
+
+% establish the appropriate instructions to the subject
+% NB responsibility for this is now transferred to the paradigm file
+switch experiment.threshEstMethod
+    % only one value required for level change
+    case {'2I2AFC++', '2A2AIFC+++'}		
+        stimulusParameters.subjectText=...
+            'did the tone occur in window 1 or 2?';
+    case {'MaxLikelihood',  'oneIntervalUpDown'};
+        switch stimulusParameters.includeCue
+            case 0
+                stimulusParameters.subjectText=...
+                    stimulusParameters.instructions{1};
+            case 1
+                stimulusParameters.subjectText= ...
+                    stimulusParameters.instructions{2};
+        end
+end
+stimulusParameters.messageString={'training'};
+
+aResetPopupMenus(handles)
+% -------------------------------------------------- function orderGlobals
+function orderGlobals
+global  stimulusParameters experiment betweenRuns withinRuns
+
+stimulusParameters=[];
+stimulusParameters.sampleRate=		[];
+stimulusParameters.targetType=	'';
+stimulusParameters.targetFrequency=	[];
+stimulusParameters.targetDuration=	[];
+stimulusParameters.targetLevel=	[];
+stimulusParameters.gapDuration=	[];
+stimulusParameters.maskerType=	'';
+stimulusParameters.maskerRelativeFrequency=	[];
+stimulusParameters.maskerDuration=	[];
+stimulusParameters.maskerLevel=	[];
+stimulusParameters.backgroundType=	'';
+stimulusParameters.backgroundTypeValue=	[];
+stimulusParameters.backgroundLevel=	[];
+stimulusParameters.includeCue=	[];
+experiment.clickToStimulusPause=[];
+stimulusParameters.stimulusDelay=	[];
+stimulusParameters.rampDuration=	[];
+stimulusParameters.absThresholds=	[];
+stimulusParameters.numOHIOtones=	[];
+
+stimulusParameters.WRVname=	'';
+stimulusParameters.WRVstartValues=		[];
+stimulusParameters.WRVsteps=	[];
+stimulusParameters.WRVlimits=	[];
+stimulusParameters.WRVinitialStep=		[];
+stimulusParameters.WRVsmallStep=	[];
+experiment.singleIntervalMaxTrials=	[];
+stimulusParameters.calibrationdB=	[];
+
+stimulusParameters.catchTrialRates=	[];
+stimulusParameters.catchTrialBaseRate=	[];
+stimulusParameters.catchTrialRate=	[];
+stimulusParameters.catchTrialTimeConstant=	[];
+
+stimulusParameters.dt=		[];
+
+stimulusParameters.jitterStartdB=	[];
+stimulusParameters.restoreCalibration=	[];
+stimulusParameters.messageString=		[];
+stimulusParameters.cueTestDifference=	[];
+stimulusParameters.subjectText=	 '';
+stimulusParameters.testTargetBegins=	[];
+stimulusParameters.testTargetEnds=	[];
+stimulusParameters.musicLeveldB=	[];
+
+stimulusParameters.subjectSampleRate=[];
+stimulusParameters.MAPSampleRate=[];
+
+experiment=[];
+experiment.name=	'';
+experiment.date=	'';
+experiment.paradigm=	'';
+experiment.ear=	'';
+experiment.headphonesUsed=[];
+experiment.singleShot=	[];
+experiment.randomize=	'';
+experiment.maxTrials=	[];
+experiment.MacGThreshold=	[];
+experiment.resetCriterion=	[];
+experiment.runResetCriterion=	[];
+
+experiment.comparisonData=	[];
+experiment.absThresholds=	[];
+experiment.threshEstMethod=	'';
+experiment.functionEstMethod=	'';
+experiment.psyBinWidth=	[];
+experiment.maxLogisticK=2;
+experiment.numPossLogisticK=100;
+experiment.possLogSlopes=	[];
+experiment.meanSearchStep=	[];
+experiment.psyFunSlope=	[];
+experiment.predictionLevels=[];
+
+experiment.buttonBoxType=	'';
+experiment.buttonBoxStatus=	'';
+experiment.status=	'';
+experiment.stop=	0;
+experiment.pleaseRepeat=	[];
+experiment.justInitialized=[];
+
+experiment.MAPplot=	    [];
+experiment.saveData=	[];
+experiment.printTracks=	[];
+experiment.msgFontSize=	[];
+experiment.subjGUIfontSize=	[];
+
+experiment.timeAtStart=	'';
+experiment.minElapsed=	[];
+
+betweenRuns=[];
+betweenRuns.variableName1=	'';
+betweenRuns.variableList1=	[];
+betweenRuns.variableName2=	'';
+betweenRuns.variableList2=	[];
+betweenRuns.var1Sequence=	[];
+betweenRuns.var2Sequence=	[];
+betweenRuns.randomizeSequence=[];
+betweenRuns.timeNow=	[];
+betweenRuns.runNumber=	[];
+% betweenRuns.variableCount1=	[];
+% betweenRuns.variableCount2=	[];
+betweenRuns.thresholds=	[];
+betweenRuns.forceThresholds=	[];
+betweenRuns.observationCount=	[];
+betweenRuns.timesOfFirstReversals=	[];
+betweenRuns.bestThresholdTracks='';
+betweenRuns.bestThresholdMeanTracks='';
+betweenRuns.bestThresholdMedianTracks='';
+betweenRuns.levelTracks='';
+betweenRuns.responseTracks='';
+betweenRuns.slopeKTracks=	[];
+betweenRuns.gainTracks=	[];
+betweenRuns.VminTracks=	[];
+betweenRuns.bestGain=	[];
+betweenRuns.bestVMin=	[];
+betweenRuns.bestPaMin=	[];
+betweenRuns.bestLogisticM=	[];
+betweenRuns.bestLogisticK=	[];
+betweenRuns.psychometicFunction='';
+betweenRuns.catchTrials=	[];
+betweenRuns.caughtOut=	[];
+
+withinRuns=[];
+withinRuns.trialNumber=[];
+withinRuns.nowInPhase2=0;
+withinRuns.beginningOfPhase2=0;
+withinRuns.variableValue=[];
+withinRuns.direction='';
+withinRuns.peaks=[];
+withinRuns.troughs=	[];
+withinRuns.levelList=	[];
+withinRuns.responseList=	 [];
+withinRuns.meanEstTrack=	[];
+withinRuns.meanLogisticEstTrack=[];
+withinRuns.bestSlopeK=	[];
+withinRuns.bestGain=	[];
+withinRuns.bestVMin=	[];
+withinRuns.forceThreshold=[];
+withinRuns.catchTrial=	[];
+withinRuns.caughtOut=[];
+withinRuns.catchTrialCount=[];
+withinRuns.wrongButton=	[];
+withinRuns.babblePlaying=0;
+
+% --- Executes on selection change in popupmenuBackgroundType.
+function popupmenuBackgroundType_Callback(hObject, eventdata, handles)
+global backgroundTypes
+option=get(handles.popupmenuBackgroundType,'value');
+selectedBackground=backgroundTypes{option};
+stimulusParameters.backgroundType=selectedBackground;
+
+switch selectedBackground
+    case 'none'
+        set(handles.editBackgroundLevel,'visible','off')
+        set(handles.textBGlevel,'visible','off')
+    otherwise
+        set(handles.editBackgroundLevel,'visible','on')
+        set(handles.textBGlevel,'visible','on')
+end
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function pushbuttonStop_Callback(hObject, eventdata, handles)
+global experiment
+experiment.stop=1;
+disp('stop!')
+set(handles.pushbuttonStop, 'backgroundColor','r')
+pause(.1)
+drawnow
+
+function pushbuttonOME_Callback(hObject, eventdata, handles)
+aReadAndCheckParameterBoxes(handles);
+testOME
+
+function pushbuttonBM_Callback(hObject, eventdata, handles)
+global  stimulusParameters experiment
+aReadAndCheckParameterBoxes(handles);
+testBM(stimulusParameters.targetFrequency, experiment.name);
+
+function pushbuttonAN_Callback(hObject, eventdata, handles)
+aReadAndCheckParameterBoxes(handles);
+% now carry out tests
+showPSTHs=0;
+testAN
+
+function pushbuttonRF_Callback(hObject, eventdata, handles)
+aReadAndCheckParameterBoxes(handles);
+showPSTHs=1;
+testRF
+
+function pushbuttonSYN_Callback(hObject, eventdata, handles)
+aReadAndCheckParameterBoxes(handles);
+testSynapse
+
+function pushbuttonFM_Callback(hObject, eventdata, handles)
+aReadAndCheckParameterBoxes(handles);
+testFM
+
+function popupmenuPhase_Callback(hObject, eventdata, handles)
+global stimulusParameters
+
+optionNo=get(handles.popupmenuPhase,'value');
+options=get(handles.popupmenuPhase,'string');
+phase=options{optionNo};
+stimulusParameters.maskerPhase=phase;
+stimulusParameters.targetPhase=phase;
+
+function pushbuttonParams_Callback(hObject, eventdata, handles)
+global experiment stimulusParameters
+aReadAndCheckParameterBoxes(handles);
+% print model parameters using the 'name' box (e.g. CTa -> MAPparamsCTa)
+showParams=1; BFlist=-1;
+paramFunctionName=['method=MAPparams' experiment.name ...
+    '(BFlist, stimulusParameters.sampleRate, showParams);'];
+eval(paramFunctionName) % go and fetch the parameters requesting parameter printout
+
+
+% --- Executes on button press in pushbuttonRP.
+function pushbuttonRP_Callback(hObject, eventdata, handles)
+global experiment stimulusParameters
+aReadAndCheckParameterBoxes(handles);
+% now carry out test
+testRP(stimulusParameters.targetFrequency,experiment.name)
+
+% function handles % ??
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+function editmaskerDuration_Callback(hObject, eventdata, handles)
+
+function editmaskerDuration_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+function editmaskerLevel_Callback(hObject, eventdata, handles)
+
+function editmaskerLevel_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+function editmaskerRelativeFrequency_Callback(hObject, eventdata, handles)
+
+function editmaskerRelativeFrequency_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+function editWRVstartValues_Callback(hObject, eventdata, handles)
+
+function editWRVstartValues_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+function editgapDuration_Callback(hObject, eventdata, handles)
+
+function editgapDuration_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+function edittargetDuration_Callback(hObject, eventdata, handles)
+
+function edittargetDuration_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+function edittargetLevel_Callback(hObject, eventdata, handles)
+
+function edittargetLevel_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+function editrampDuration_Callback(hObject, eventdata, handles)
+
+function editrampDuration_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+function editcueTestDifference_Callback(hObject, eventdata, handles)
+
+function editcueTestDifference_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+
+function editWRVsteps_Callback(hObject, eventdata, handles)
+
+function editWRVsteps_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+function editWRVlimits_Callback(hObject, eventdata, handles)
+
+function editWRVlimits_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+function edittargetFrequency_Callback(hObject, eventdata, handles)
+
+function edittargetFrequency_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+function editName_Callback(hObject, eventdata, handles)
+
+function editName_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+function editcalibrationdB_Callback(hObject, eventdata, handles)
+
+function editcalibrationdB_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+function editMAPplot_Callback(hObject, eventdata, handles)
+
+function editMAPplot_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+function editMsgFont_Callback(hObject, eventdata, handles)
+
+function editMsgFont_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+function editCatchTrialRate_Callback(hObject, eventdata, handles)
+
+function editCatchTrialRate_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+
+function editSaveData_Callback(hObject, eventdata, handles)
+
+function editSaveData_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+function editStatsModel_Callback(hObject, eventdata, handles)
+
+function editStatsModel_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+function editBackgroundLevel_Callback(hObject, eventdata, handles)
+
+function editBackgroundLevel_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+function editPrintTracks_Callback(hObject, eventdata, handles)
+
+function editPrintTracks_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+function editstopCriteriaBox_Callback(hObject, eventdata, handles)
+
+function editstopCriteriaBox_CreateFcn(hObject, eventdata, handles)
+
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+function editstimulusDelay_Callback(hObject, eventdata, handles)
+
+function editstimulusDelay_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+
+function popupmenuCueNoCue_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+function popupmenuEar_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','red');
+end
+
+function popupmenuVaryParameter1_Callback(hObject, eventdata, handles)
+
+function popupmenuVaryParameter1_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+function popupmenuVaryParameter2_Callback(hObject, eventdata, handles)
+
+function popupmenuVaryParameter2_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+function popupmenuRandomize_Callback(hObject, eventdata, handles)
+
+function popupmenuRandomize_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+function popupmenuParadigm_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+
+function popupmenuMaskerType_CreateFcn(hObject, eventdata, handles)
+
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+
+function popupmenuThreshEst_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+function popupmenuBackgroundType_CreateFcn(hObject, eventdata, handles)
+
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+
+function popupmenuTargetType_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+function editSubjectFont_Callback(hObject, eventdata, handles)
+
+function editSubjectFont_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+function editMusicLevel_Callback(hObject, eventdata, handles)
+
+function editMusicLevel_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+function figure1_ButtonDownFcn(hObject, eventdata, handles)
+
+
+function edit33_Callback(hObject, eventdata, handles)
+
+function edit33_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+
+function popupmenuPhase_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+function editsegSize_Callback(hObject, eventdata, handles)
+
+function editsegSize_CreateFcn(hObject, eventdata, handles)
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+
+function editnumOHIOtones_Callback(hObject, eventdata, handles)
+% hObject    handle to editnumOHIOtones (see GCBO)
+% eventdata  reserved - to be defined in a future version of MATLAB
+% handles    structure with handles and user data (see GUIDATA)
+
+% Hints: get(hObject,'String') returns contents of editnumOHIOtones as text
+%        str2double(get(hObject,'String')) returns contents of editnumOHIOtones as a double
+
+
+% --- Executes during object creation, after setting all properties.
+function editnumOHIOtones_CreateFcn(hObject, eventdata, handles)
+% hObject    handle to editnumOHIOtones (see GCBO)
+% eventdata  reserved - to be defined in a future version of MATLAB
+% handles    empty - handles not created until after all CreateFcns called
+
+% Hint: edit controls usually have a white background on Windows.
+%       See ISPC and COMPUTER.
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+
+    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/hs_err_pid6084.log	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,258 @@
+#
+# An unexpected error has been detected by Java Runtime Environment:
+#
+#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x0000000002e47250, pid=6084, tid=5820
+#
+# Java VM: Java HotSpot(TM) 64-Bit Server VM (1.6.0-b105 mixed mode)
+# Problematic frame:
+# C  [libmwgui.dll+0x77250]
+#
+# If you would like to submit a bug report, please visit:
+#   http://java.sun.com/webapps/bugreport/crash.jsp
+#
+
+---------------  T H R E A D  ---------------
+
+Current thread (0x0000000003d2fc00):  JavaThread "main" [_thread_in_native, id=5820]
+
+siginfo: ExceptionCode=0xc0000005, reading address 0x0000000000000000
+
+Registers:
+EAX=0x0000000000000000, EBX=0x0000000000000000, ECX=0x0000000000000000, EDX=0x0000000000000000
+ESP=0x00000000010296f8, EBP=0x0000000000000001, ESI=0x0000000000000000, EDI=0x0000000000000000
+EIP=0x0000000002e47250, EFLAGS=0x0000000000010206
+
+Top of Stack: (sp=0x00000000010296f8)
+0x00000000010296f8:   0000000002fb728f 4010002000000000
+0x0000000001029708:   0000000000000000 0000000035937370
+0x0000000001029718:   0000000002e596dd 0000000008a3cf00
+0x0000000001029728:   0000000002f7fb49 4010000000000000
+0x0000000001029738:   4008000000000000 0000000000000000
+0x0000000001029748:   0000000000000000 0000000008a3cf60
+0x0000000001029758:   0000000002fb72be 0000000008a3cf00
+0x0000000001029768:   0000000000000001 4010000000000000
+0x0000000001029778:   0000000000000000 0000000000000000
+0x0000000001029788:   0000000002f8d1de 0000000000000000
+0x0000000001029798:   0000000008a3cf60 0000000000000001
+0x00000000010297a8:   000000001176d320 0000000009e522a0
+0x00000000010297b8:   000000000319bd9e 0000000008a3cf60
+0x00000000010297c8:   0000000000000020 0000000000000002
+0x00000000010297d8:   00000000013b7338 0000000008a3cf50
+0x00000000010297e8:   00000000359f17a0 000000003c19ca80 
+
+Instructions: (pc=0x0000000002e47250)
+0x0000000002e47240:   89 11 c3 cc cc cc cc cc cc cc cc cc cc cc cc cc
+0x0000000002e47250:   8b 01 c3 cc cc cc cc cc cc cc cc cc cc cc cc cc 
+
+
+Stack: [0x0000000000030000,0x0000000001030000),  sp=0x00000000010296f8,  free space=16357k
+Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
+C  [libmwgui.dll+0x77250]
+
+Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
+j  com.mathworks.jmi.NativeMatlab.SendMatlabMessage(Ljava/lang/Object;)Ljava/lang/Object;+0
+j  com.mathworks.jmi.NativeMatlab.sendMatlabMessage(Ljava/lang/Object;)Ljava/lang/Object;+22
+j  com.mathworks.jmi.MatlabLooper.sendMatlabMessage(Lcom/mathworks/services/message/MWMessage;)Ljava/lang/Object;+20
+j  com.mathworks.jmi.Matlab.mtFevalConsoleOutput(Ljava/lang/String;[Ljava/lang/Object;I)Ljava/lang/Object;+58
+j  com.mathworks.mde.desk.MLDesktop$5.run()V+14
+j  com.mathworks.jmi.NativeMatlab.dispatchMTRequests(Z)V+50
+v  ~StubRoutines::call_stub
+
+---------------  P R O C E S S  ---------------
+
+Java Threads: ( => current thread )
+  0x0000000011b68400 JavaThread "Thread-168" [_thread_blocked, id=3544]
+  0x0000000011b68c00 JavaThread "Prefs Updater" [_thread_blocked, id=6864]
+  0x0000000011b67000 JavaThread "Thread-8" [_thread_blocked, id=6900]
+  0x0000000011b66800 JavaThread "Thread-7" [_thread_blocked, id=6792]
+  0x0000000011b66000 JavaThread "Thread-6" [_thread_blocked, id=868]
+  0x0000000011b65800 JavaThread "Thread-5" [_thread_blocked, id=6628]
+  0x0000000030e0a000 JavaThread "Active Reference Queue Daemon" daemon [_thread_blocked, id=1428]
+  0x0000000011b97800 JavaThread "Timer-2" daemon [_thread_blocked, id=3276]
+  0x0000000030ded400 JavaThread "Timer-1" daemon [_thread_blocked, id=6912]
+  0x0000000011a81000 JavaThread "TimerQueue" daemon [_thread_blocked, id=5220]
+  0x00000000117fd400 JavaThread "AWT-EventQueue-0" [_thread_blocked, id=120]
+  0x00000000114dec00 JavaThread "AWT-Windows" daemon [_thread_in_native, id=3212]
+  0x00000000114de400 JavaThread "AWT-Shutdown" [_thread_blocked, id=6512]
+  0x00000000114ddc00 JavaThread "Java2D Disposer" daemon [_thread_blocked, id=4896]
+  0x0000000011244c00 JavaThread "Timer-0" [_thread_blocked, id=3172]
+  0x000000000fb42400 JavaThread "Low Memory Detector" daemon [_thread_blocked, id=2312]
+  0x000000000fb40000 JavaThread "CompilerThread1" daemon [_thread_blocked, id=3556]
+  0x000000000fb3b800 JavaThread "CompilerThread0" daemon [_thread_blocked, id=2260]
+  0x000000000fb37400 JavaThread "Attach Listener" daemon [_thread_blocked, id=6760]
+  0x000000000fb1f400 JavaThread "Finalizer" daemon [_thread_blocked, id=5488]
+  0x000000000fb19800 JavaThread "Reference Handler" daemon [_thread_blocked, id=6300]
+=>0x0000000003d2fc00 JavaThread "main" [_thread_in_native, id=5820]
+
+Other Threads:
+  0x000000000fb16000 VMThread [id=7068]
+  0x000000000fb47800 WatcherThread [id=4288]
+
+VM state:not at safepoint (normal execution)
+
+VM Mutex/Monitor currently owned by a thread: None
+
+Heap
+ PSYoungGen      total 7104K, used 6681K [0x00000000265a0000, 0x0000000026d80000, 0x00000000296a0000)
+  eden space 6400K, 97% used [0x00000000265a0000,0x0000000026bb6710,0x0000000026be0000)
+  from space 704K, 63% used [0x0000000026cd0000,0x0000000026d40000,0x0000000026d80000)
+  to   space 832K, 0% used [0x0000000026be0000,0x0000000026be0000,0x0000000026cb0000)
+ PSOldGen        total 47616K, used 41927K [0x000000001d2a0000, 0x0000000020120000, 0x00000000265a0000)
+  object space 47616K, 88% used [0x000000001d2a0000,0x000000001fb91f18,0x0000000020120000)
+ PSPermGen       total 80384K, used 43275K [0x00000000152a0000, 0x000000001a120000, 0x000000001d2a0000)
+  object space 80384K, 53% used [0x00000000152a0000,0x0000000017ce2c78,0x000000001a120000)
+
+Dynamic libraries:
+0x0000000140000000 - 0x0000000140138000 	C:\Program Files\MATLAB\R2008a\bin\win64\MATLAB.exe
+0x0000000077420000 - 0x00000000775c9000 	C:\Windows\SYSTEM32\ntdll.dll
+0x0000000077300000 - 0x000000007741f000 	C:\Windows\system32\kernel32.dll
+0x000007fefd440000 - 0x000007fefd4ab000 	C:\Windows\system32\KERNELBASE.dll
+0x0000000180000000 - 0x0000000180401000 	C:\Program Files\MATLAB\R2008a\bin\win64\libut.dll
+0x000007fefee00000 - 0x000007fefee17000 	C:\Windows\system32\imagehlp.dll
+0x000007fefd7c0000 - 0x000007fefd85f000 	C:\Windows\system32\msvcrt.dll
+0x00000000775f0000 - 0x00000000775f7000 	C:\Windows\system32\PSAPI.DLL
+0x00000000011e0000 - 0x0000000001208000 	C:\Program Files\MATLAB\R2008a\bin\win64\LIBEXPAT.dll
+0x0000000073a30000 - 0x0000000073af9000 	C:\Windows\WinSxS\amd64_microsoft.vc80.crt_1fc8b3b9a1e18e3b_8.0.50727.5592_none_88e45feb2faab9ce\MSVCR80.dll
+0x000000004a800000 - 0x000000004a917000 	C:\Program Files\MATLAB\R2008a\bin\win64\icuuc36.dll
+0x000007fefea70000 - 0x000007fefeb4b000 	C:\Windows\system32\ADVAPI32.dll
+0x000007feff180000 - 0x000007feff19f000 	C:\Windows\SYSTEM32\sechost.dll
+0x000007feff2d0000 - 0x000007feff3fd000 	C:\Windows\system32\RPCRT4.dll
+0x0000000001220000 - 0x0000000001223000 	C:\Program Files\MATLAB\R2008a\bin\win64\icudt36.dll
+0x000000004ab00000 - 0x000000004ab0f000 	C:\Program Files\MATLAB\R2008a\bin\win64\icuio36.dll
+0x0000000001250000 - 0x0000000001356000 	C:\Program Files\MATLAB\R2008a\bin\win64\icuin36.dll
+0x0000000072330000 - 0x0000000072439000 	C:\Windows\WinSxS\amd64_microsoft.vc80.crt_1fc8b3b9a1e18e3b_8.0.50727.5592_none_88e45feb2faab9ce\MSVCP80.dll
+0x0000000077200000 - 0x00000000772fa000 	C:\Windows\system32\USER32.dll
+0x000007fefd750000 - 0x000007fefd7b7000 	C:\Windows\system32\GDI32.dll
+0x000007fefea60000 - 0x000007fefea6e000 	C:\Windows\system32\LPK.dll
+0x000007feff030000 - 0x000007feff0f9000 	C:\Windows\system32\USP10.dll
+0x0000000001370000 - 0x00000000014e4000 	C:\Program Files\MATLAB\R2008a\bin\win64\libmwservices.dll
+0x0000000001500000 - 0x0000000001570000 	C:\Program Files\MATLAB\R2008a\bin\win64\libmx.dll
+0x0000000001580000 - 0x0000000001597000 	C:\Program Files\MATLAB\R2008a\bin\win64\zlib1.dll
+0x00000000015a0000 - 0x0000000001648000 	C:\Program Files\MATLAB\R2008a\bin\win64\libmwmathutil.dll
+0x0000000001660000 - 0x00000000016b5000 	C:\Program Files\MATLAB\R2008a\bin\win64\mpath.dll
+0x00000000016d0000 - 0x00000000016f1000 	C:\Program Files\MATLAB\R2008a\bin\win64\mlutil.dll
+0x000007fef9870000 - 0x000007fef9910000 	C:\Windows\WinSxS\amd64_microsoft.windows.common-controls_6595b64144ccf1df_5.82.7601.17514_none_a4d6a923711520a9\COMCTL32.dll
+0x000007fefec90000 - 0x000007fefed27000 	C:\Windows\system32\comdlg32.dll
+0x000007fefed80000 - 0x000007fefedf1000 	C:\Windows\system32\SHLWAPI.dll
+0x000007fefd970000 - 0x000007fefe6f8000 	C:\Windows\system32\SHELL32.dll
+0x000007fefc840000 - 0x000007fefc856000 	C:\Windows\system32\NETAPI32.dll
+0x000007fefc830000 - 0x000007fefc83c000 	C:\Windows\system32\netutils.dll
+0x000007fefcee0000 - 0x000007fefcf03000 	C:\Windows\system32\srvcli.dll
+0x000007fefc810000 - 0x000007fefc825000 	C:\Windows\system32\wkscli.dll
+0x000007fefed30000 - 0x000007fefed7d000 	C:\Windows\system32\WS2_32.dll
+0x000007fefd740000 - 0x000007fefd748000 	C:\Windows\system32\NSI.dll
+0x0000000001710000 - 0x0000000001765000 	C:\Program Files\MATLAB\R2008a\bin\win64\mcr.dll
+0x0000000001780000 - 0x00000000017a5000 	C:\Program Files\MATLAB\R2008a\bin\win64\iqm.dll
+0x00000000017c0000 - 0x00000000017e1000 	C:\Program Files\MATLAB\R2008a\bin\win64\bridge.dll
+0x0000000001800000 - 0x0000000001811000 	C:\Program Files\MATLAB\R2008a\bin\win64\libmex.dll
+0x0000000001830000 - 0x00000000018bc000 	C:\Program Files\MATLAB\R2008a\bin\win64\m_dispatcher.dll
+0x00000000018d0000 - 0x00000000018f5000 	C:\Program Files\MATLAB\R2008a\bin\win64\datasvcs.dll
+0x0000000012000000 - 0x0000000012295000 	C:\Program Files\MATLAB\R2008a\bin\win64\xerces-c_2_7.dll
+0x0000000001920000 - 0x00000000021b1000 	C:\Program Files\MATLAB\R2008a\bin\win64\m_interpreter.dll
+0x00000000021d0000 - 0x0000000002201000 	C:\Program Files\MATLAB\R2008a\bin\win64\libmat.dll
+0x0000000002220000 - 0x0000000002325000 	C:\Program Files\MATLAB\R2008a\bin\win64\libhdf5.dll
+0x0000000002330000 - 0x000000000239f000 	C:\Program Files\MATLAB\R2008a\bin\win64\profiler.dll
+0x00000000023b0000 - 0x00000000023ba000 	C:\Program Files\MATLAB\R2008a\bin\win64\libmwmathrng.dll
+0x00000000023d0000 - 0x00000000023ea000 	C:\Program Files\MATLAB\R2008a\bin\win64\m_pcodeio.dll
+0x0000000002400000 - 0x000000000244a000 	C:\Program Files\MATLAB\R2008a\bin\win64\m_ir.dll
+0x0000000002460000 - 0x0000000002a1b000 	C:\Program Files\MATLAB\R2008a\bin\win64\m_parser.dll
+0x0000000002a30000 - 0x0000000002a42000 	C:\Program Files\MATLAB\R2008a\bin\win64\ir_xfmr.dll
+0x0000000002a60000 - 0x0000000002c7b000 	C:\Program Files\MATLAB\R2008a\bin\win64\mcos.dll
+0x0000000002c90000 - 0x0000000002c9c000 	C:\Program Files\MATLAB\R2008a\bin\win64\mtok.dll
+0x0000000002cb0000 - 0x0000000002cd0000 	C:\Program Files\MATLAB\R2008a\bin\win64\m_pcodegen.dll
+0x000007fef4b20000 - 0x000007fef4c45000 	C:\Windows\system32\dbghelp.dll
+0x0000000002ce0000 - 0x0000000002cf0000 	C:\Program Files\MATLAB\R2008a\bin\win64\boost_thread-vc80-mt-1_34_1.dll
+0x0000000002d00000 - 0x0000000002dc0000 	C:\Program Files\MATLAB\R2008a\bin\win64\udd.dll
+0x0000000002dd0000 - 0x0000000002f12000 	C:\Program Files\MATLAB\R2008a\bin\win64\libmwgui.dll
+0x0000000002f30000 - 0x000000000316a000 	C:\Program Files\MATLAB\R2008a\bin\win64\hg.dll
+0x0000000003180000 - 0x00000000031d6000 	C:\Program Files\MATLAB\R2008a\bin\win64\jmi.dll
+0x00000000031f0000 - 0x000000000322e000 	C:\Program Files\MATLAB\R2008a\bin\win64\libmwhardcopy.dll
+0x0000000003240000 - 0x000000000329c000 	C:\Program Files\MATLAB\R2008a\bin\win64\libuij.dll
+0x00000000032b0000 - 0x000000000353c000 	C:\Program Files\MATLAB\R2008a\bin\win64\numerics.dll
+0x0000000003550000 - 0x000000000355c000 	C:\Program Files\MATLAB\R2008a\bin\win64\libmwblas.dll
+0x0000000003570000 - 0x000000000357f000 	C:\Program Files\MATLAB\R2008a\bin\win64\libmwbinder.dll
+0x0000000003590000 - 0x00000000035b4000 	C:\Program Files\MATLAB\R2008a\bin\win64\libmwlapack.dll
+0x00000000035d0000 - 0x00000000035db000 	C:\Program Files\MATLAB\R2008a\bin\win64\libmwfftw.dll
+0x00000000035f0000 - 0x0000000003625000 	C:\Program Files\MATLAB\R2008a\bin\win64\libmwrookfastbp.dll
+0x0000000003640000 - 0x000000000366e000 	C:\Program Files\MATLAB\R2008a\bin\win64\libmwma57.dll
+0x0000000010000000 - 0x00000000100d3000 	C:\Program Files\MATLAB\R2008a\bin\win64\libifcoremd.dll
+0x0000000003680000 - 0x000000000389d000 	C:\Program Files\MATLAB\R2008a\bin\win64\libmmd.dll
+0x00000000038a0000 - 0x00000000038a9000 	C:\Program Files\MATLAB\R2008a\bin\win64\libmwcsparse.dll
+0x00000000038c0000 - 0x000000000398a000 	C:\Program Files\MATLAB\R2008a\bin\win64\libmwumfpack.dll
+0x00000000039a0000 - 0x00000000039ad000 	C:\Program Files\MATLAB\R2008a\bin\win64\libmwamd.dll
+0x00000000039c0000 - 0x0000000003a52000 	C:\Program Files\MATLAB\R2008a\bin\win64\libmwcholmod.dll
+0x0000000003a70000 - 0x0000000003a7c000 	C:\Program Files\MATLAB\R2008a\bin\win64\libmwcolamd.dll
+0x0000000003a90000 - 0x0000000003b49000 	C:\Program Files\MATLAB\R2008a\bin\win64\uiw.dll
+0x0000000003b60000 - 0x0000000003b6a000 	C:\Program Files\MATLAB\R2008a\bin\win64\uinone.dll
+0x0000000068a70000 - 0x0000000068c0c000 	C:\Windows\WinSxS\amd64_microsoft.vc80.mfc_1fc8b3b9a1e18e3b_8.0.50727.5592_none_8448f49f328da8c3\MFC80.DLL
+0x000007fefb690000 - 0x000007fefb701000 	C:\Windows\system32\WINSPOOL.DRV
+0x000007fefee20000 - 0x000007feff023000 	C:\Windows\system32\ole32.dll
+0x000007fefebb0000 - 0x000007fefec87000 	C:\Windows\system32\OLEAUT32.dll
+0x0000000003b80000 - 0x0000000003c10000 	C:\Program Files\MATLAB\R2008a\bin\win64\udd_mi.dll
+0x0000000003c20000 - 0x0000000003c38000 	C:\Program Files\MATLAB\R2008a\bin\win64\mwoles05.DLL
+0x0000000003c50000 - 0x0000000003cb9000 	C:\Program Files\MATLAB\R2008a\bin\win64\comcli.dll
+0x0000000072310000 - 0x0000000072330000 	C:\Windows\WinSxS\amd64_microsoft.vc80.atl_1fc8b3b9a1e18e3b_8.0.50727.5592_none_8a1e1b372ed7b012\ATL80.DLL
+0x0000000003cd0000 - 0x0000000003cde000 	C:\Program Files\MATLAB\R2008a\bin\win64\mlautoregister.dll
+0x000007feff4a0000 - 0x000007feff4ce000 	C:\Windows\system32\IMM32.DLL
+0x000007fefd860000 - 0x000007fefd969000 	C:\Windows\system32\MSCTF.dll
+0x000000006fa00000 - 0x000000006fa3f000 	C:\PROGRA~2\Sophos\SOPHOS~1\SOPHOS~2.DLL
+0x00000000076c0000 - 0x000000000808e000 	C:\Program Files\MATLAB\R2008a\bin\win64\mkl.dll
+0x00000000068d0000 - 0x000000000691b000 	C:\Program Files\MATLAB\R2008a\bin\win64\libguide40.dll
+0x0000000003e70000 - 0x0000000003e78000 	C:\Program Files\MATLAB\R2008a\bin\win64\mklcompat.dll
+0x0000000008090000 - 0x0000000008637000 	C:\Program Files\MATLAB\R2008a\bin\win64\mllapack.dll
+0x00000000070b0000 - 0x00000000071a4000 	C:\Program Files\MATLAB\R2008a\bin\win64\libfftw3i.dll
+0x0000000007260000 - 0x000000000734e000 	C:\Program Files\MATLAB\R2008a\bin\win64\libfftw3f.dll
+0x000007fefd370000 - 0x000007fefd37f000 	C:\Windows\system32\profapi.dll
+0x000007fefd240000 - 0x000007fefd24f000 	C:\Windows\system32\CRYPTBASE.dll
+0x000007fefbe90000 - 0x000007fefc084000 	C:\Windows\WinSxS\amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.7601.17514_none_fa396087175ac9ac\comctl32.dll
+0x000007fefe700000 - 0x000007fefe8d7000 	C:\Windows\system32\SETUPAPI.dll
+0x000007fefd4b0000 - 0x000007fefd4e6000 	C:\Windows\system32\CFGMGR32.dll
+0x000007fefd420000 - 0x000007fefd43a000 	C:\Windows\system32\DEVOBJ.dll
+0x000007feff400000 - 0x000007feff499000 	C:\Windows\system32\CLBCatQ.DLL
+0x000007fefb8f0000 - 0x000007fefba1c000 	C:\Windows\system32\propsys.dll
+0x000007fefaea0000 - 0x000007fefaecd000 	C:\Windows\system32\ntmarta.dll
+0x000007fefeb50000 - 0x000007fefeba2000 	C:\Windows\system32\WLDAP32.dll
+0x000007fefa500000 - 0x000007fefa527000 	C:\Windows\system32\iphlpapi.dll
+0x000007fefa4f0000 - 0x000007fefa4fb000 	C:\Windows\system32\WINNSI.DLL
+0x000007fefca60000 - 0x000007fefcabb000 	C:\Windows\system32\DNSAPI.dll
+0x000007fefa0b0000 - 0x000007fefa0c8000 	C:\Windows\system32\dhcpcsvc.DLL
+0x000007fefa0d0000 - 0x000007fefa0e1000 	C:\Windows\system32\dhcpcsvc6.DLL
+0x000007fefd210000 - 0x000007fefd235000 	C:\Windows\system32\SspiCli.dll
+0x0000000074aa0000 - 0x0000000074aa3000 	C:\Windows\system32\icmp.Dll
+0x000000000edf0000 - 0x000000000f341000 	C:\Program Files\MATLAB\R2008a\sys\java\jre\win64\jre1.6.0\bin\server\jvm.dll
+0x000007fefaed0000 - 0x000007fefaf0b000 	C:\Windows\system32\WINMM.dll
+0x0000000007450000 - 0x00000000074b5000 	C:\Program Files\WIDCOMM\Bluetooth Software\btmmhook.dll
+0x0000000007230000 - 0x000000000723a000 	C:\Program Files\MATLAB\R2008a\sys\java\jre\win64\jre1.6.0\bin\hpi.dll
+0x0000000008740000 - 0x000000000874e000 	C:\Program Files\MATLAB\R2008a\sys\java\jre\win64\jre1.6.0\bin\verify.dll
+0x0000000008750000 - 0x0000000008777000 	C:\Program Files\MATLAB\R2008a\sys\java\jre\win64\jre1.6.0\bin\java.dll
+0x0000000008780000 - 0x0000000008792000 	C:\Program Files\MATLAB\R2008a\sys\java\jre\win64\jre1.6.0\bin\zip.dll
+0x00000000087a0000 - 0x00000000087b6000 	C:\Program Files\MATLAB\R2008a\bin\win64\nativejava.dll
+0x00000000088a0000 - 0x00000000088b6000 	C:\Program Files\MATLAB\R2008a\bin\win64\nativejmi.dll
+0x000000000f850000 - 0x000000000f857000 	C:\Program Files\MATLAB\R2008a\bin\win64\nativeservices.dll
+0x0000000011ce0000 - 0x0000000011f30000 	C:\Program Files\MATLAB\R2008a\sys\java\jre\win64\jre1.6.0\bin\awt.dll
+0x00000000306a0000 - 0x0000000030709000 	C:\Program Files\MATLAB\R2008a\sys\java\jre\win64\jre1.6.0\bin\fontmanager.dll
+
+VM Arguments:
+jvm_args: -Xss512k -XX:PermSize=32M -Xms64m -XX:NewRatio=3 -XX:MaxPermSize=128M -Xmx196m -XX:MaxDirectMemorySize=2147400000 -Dsun.java2d.noddraw=true -Dsun.awt.nopixfmt=true -Xshare:off -Xrs -Djava.library.path=C:\Program Files\MATLAB\R2008a\bin\win64 vfprintf abort
+java_command: <unknown>
+Launcher Type: generic
+
+Environment Variables:
+CLASSPATH=.;C:\Program Files (x86)\Java\jre6\lib\ext\QTJava.zip
+PATH=C:\Program Files (x86)\Nokia\PC Connectivity Solution\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files\Intel\WiFi\bin\;C:\Program Files\Common Files\Intel\WirelessCommon\;C:\Program Files\Intel\DMIX;C:\Program Files (x86)\NTRU Cryptosystems\NTRU TCG Software Stack\bin\;C:\Program Files\NTRU Cryptosystems\NTRU TCG Software Stack\bin\;C:\Program Files\Wave Systems Corp\Gemalto\Access Client\v5\;c:\Program Files\WIDCOMM\Bluetooth Software\;c:\Program Files\WIDCOMM\Bluetooth Software\syswow64;C:\Program Files (x86)\Common Files\Roxio Shared\DLLShared\;C:\Program Files (x86)\Common Files\Roxio Shared\10.0\DLLShared\;C:\Program Files (x86)\Common Files\Adobe\AGL;C:\Program Files\MATLAB\R2010b\bin;C:\Program Files\MATLAB\R2010a\bin;C:\Program Files\MATLAB\R2008a\bin;C:\Program Files\MATLAB\R2008a\bin\win64;C:\Program Files (x86)\QuickTime\QTSystem\;C:\Program Files\Microsoft Windows Performance Toolkit\
+USERNAME=rmeddis
+OS=Windows_NT
+PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 37 Stepping 2, GenuineIntel
+
+
+
+---------------  S Y S T E M  ---------------
+
+OS: Windows NT 6.1 Build 7601 Service Pack 1
+
+CPU:total 4 em64t ht
+
+Memory: 4k page, physical 8181592k(6037968k free), swap 16361336k(14041736k free)
+
+vm_info: Java HotSpot(TM) 64-Bit Server VM (1.6.0-b105) for windows-amd64, built on Nov 29 2006 00:38:01 by "java_re" with unknown MS VC++:1400
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/nextStimulus.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,853 @@
+function errormsg=nextStimulus(handles)
+% Handles everything concerned with the stimulus presentation
+%  called from startNewRun in subjGUI
+
+global experiment stimulusParameters withinRuns betweenRuns
+experiment.status='presentingStimulus';
+errormsg='';
+
+% interrupt by 'stop' button
+if experiment.stop
+    disp('******** experiment manually stopped  *****************')
+    experiment.status= 'waitingForStart';
+    addToMsg('manually stopped',1)
+    return
+end
+
+% -----------------------------------------choose catch trials at random
+% catch trials are for subject threshold measurements only
+% this is the only place where withinRuns.catchTrial is set
+if experiment.allowCatchTrials
+    if withinRuns.trialNumber==1;
+        % first trial is never a catch trial
+        withinRuns.catchTrial=0;
+        withinRuns.catchTrialCount=0;   % reset count on first trial
+    elseif withinRuns.trialNumber==2 ...
+            && withinRuns.catchTrialCount==0
+        % second trial is always a catch trial
+        withinRuns.catchTrial=1;
+        withinRuns.catchTrialCount=1;   % this must be the first
+    elseif withinRuns.thisIsRepeatTrial
+        % for requested repeats do not change catch trial status
+        withinRuns.thisIsRepeatTrial=0; % reset toggle
+    else
+        % choose whether or not to have a catch trial
+        R=rand;
+        if R<stimulusParameters.catchTrialRate
+            % catch trial
+            withinRuns.catchTrial=1;
+            addToMsg('Catch Trial',1)
+            withinRuns.catchTrialCount=withinRuns.catchTrialCount+1;
+        else
+            % not a catch trial
+            withinRuns.catchTrial=0;
+        end
+    end
+else
+    % no catch trials for statistical evaluations or 2AIFC or (poss) MAP
+    withinRuns.catchTrial=0;
+end
+
+%------------ during stimulus presentation show appropriate button images
+switch experiment.ear
+    case {'statsModelLogistic', 'statsModelRareEvent',...
+            'MAPmodel', 'MAPmodelMultiCh', 'MAPmodelSingleCh'}
+        % no buttons shown
+    otherwise
+        switch experiment.threshEstMethod
+            case {'2I2AFC++', '2I2AFC+++'}
+                %Except for 2I2AFC
+                % For 2I2AFC the buttons on the screen ab initio
+                set(handles.frame1,'visible','off')
+                set(handles.pushbuttonGO,'visible','off')
+                set(handles.pushbuttoNotSure,'visible','off')
+                set(handles.pushbuttonWrongButton,'visible','off')
+                set(handles.pushbutton3,'visible','off')
+                set(handles.pushbutton0,'visible','off')
+                set(handles.pushbutton1,'visible','on')
+                set(handles.pushbutton2,'visible','on')
+                drawnow
+            otherwise
+                % i.e. single interval/ maxLikelihood
+                set(handles.frame1,'backgroundColor','w')
+                set(handles.frame1,'visible','off')
+                set(handles.pushbuttoNotSure,'visible','off')
+                set(handles.pushbuttonWrongButton,'visible','off')
+                set(handles.pushbutton3,'visible','off')
+                set(handles.pushbutton2,'visible','off')
+                set(handles.pushbutton1,'visible','off')
+                set(handles.pushbutton0,'visible','off')
+                pause(.1)
+        end
+end
+
+set(handles.textMSG,'BackgroundColor','w', 'ForegroundColor', 'b')
+            
+% Now the serious business of crafting and presenting the stimulus
+errormsg= stimulusMakeAndPlay (handles);
+
+if ~isempty(errormsg)
+    % e.g. clipping. subjGUI will service the error
+    return
+end
+
+% after playing the stimulus, reset the subjectGUI
+switch experiment.ear
+    case {'statsModelLogistic', 'statsModelRareEvent',...
+            'MAPmodel', 'MAPmodelMultiCh', 'MAPmodelSingleCh'}
+        % no changes required if model used
+        % NB these changes do occur is 'MAPmodelListen' is selected
+    otherwise
+        switch experiment.threshEstMethod
+            case {'2I2AFC++', '2I2AFC+++'}
+                % buttons already visible
+            otherwise
+                % single interval now make buttons visible
+                set(handles.frame1,'visible','on')
+                set(handles.pushbuttoNotSure,'visible','on')
+                % set(handles.pushbuttonWrongButton,'visible','on')
+                set(handles.pushbutton0,'visible','on')
+                set(handles.pushbutton1,'visible','on')
+                set(handles.pushbutton2,'visible','on')
+                set(handles.pushbutton3,'visible','on')
+        end
+end
+
+switch experiment.paradigm
+    case 'SRT'
+        set(handles.frame1,'backgroundColor','w')
+        set(handles.frame1,'visible','off')
+        set(handles.pushbuttoNotSure,'visible','off')
+        set(handles.pushbuttonWrongButton,'visible','off')
+        set(handles.pushbutton3,'visible','off')
+        set(handles.pushbutton2,'visible','off')
+        set(handles.pushbutton1,'visible','off')
+        set(handles.pushbutton0,'visible','off')
+        set(handles.editdigitInput,'visible','on')
+        set(handles.editdigitInput,'string',[])
+        pause(.2)
+        uicontrol(handles.editdigitInput)
+        
+    otherwise
+        set(handles.editdigitInput,'visible','off')
+end
+
+
+experiment.status='waitingForResponse';
+% home again
+
+% ------------------------------------------------------------------------------------------stimulusMakeAndPlay
+function errormsg=stimulusMakeAndPlay (handles)
+global experiment stimulusParameters betweenRuns withinRuns expGUIhandles  audio
+% creates the stimulus and plays it; there are two stimuli; cue and test
+%  called from nextStimulus
+
+errormsg='';
+
+% first post the subjects instructions on subjGUI
+set(handles.textMSG,'string', stimulusParameters.subjectText)
+
+% select the new levels of the between runs variables
+num=betweenRuns.runNumber;
+cmd=(['stimulusParameters.' betweenRuns.variableName1 '= ' ...
+    num2str(betweenRuns.var1Sequence(num)) ';']);
+% e.g.  stimulusParameters.targetFrequency= 1000;
+eval(cmd);
+
+cmd=(['stimulusParameters.' betweenRuns.variableName2 '= ' ...
+    num2str(betweenRuns.var2Sequence(num)) ';']);
+% e.g.  stimulusParameters.targetDuration= 0.1;
+eval(cmd);
+
+switch experiment.paradigm
+    % target level may vary between runs
+    case {'trainingIFMC', 'TMC','TMC_16ms', 'TMC - ELP', 'IFMC','IFMC_8ms','IFMC_16ms'}
+        idx=floor(num/length(betweenRuns.variableList1)-0.01)+1;
+        cmd=(['stimulusParameters.targetLevel = ' ...
+            num2str(stimulusParameters.targetLevels(idx)) ';']);
+        eval(cmd);
+        if withinRuns.trialNumber==1
+            disp(['targetLevel=' num2str(stimulusParameters.targetLevel)])
+        end
+end
+
+
+% for more readable code use shorter variable names;
+% NB these may change below; these are only the starting values
+
+targetType=        stimulusParameters.targetType;
+targetDuration=    stimulusParameters.targetDuration;
+targetLevel=       stimulusParameters.targetLevel;
+targetFrequency=   stimulusParameters.targetFrequency;
+
+maskerType=        stimulusParameters.maskerType;
+maskerDuration=    stimulusParameters.maskerDuration;
+maskerLevel=       stimulusParameters.maskerLevel;
+maskerRelativeFrequency=  stimulusParameters.maskerRelativeFrequency;
+maskerFrequency=   maskerRelativeFrequency*targetFrequency;
+
+gapDuration=       stimulusParameters.gapDuration;
+
+rampDuration=      stimulusParameters.rampDuration;
+AFCsilenceDuration=stimulusParameters.AFCsilenceDuration; % 2I2AFC gap
+backgroundLevel=   stimulusParameters.backgroundLevel;
+
+% Set level of within runs variable
+% this is the first change to one of the values shown above
+cmd=[stimulusParameters.WRVname '= withinRuns.variableValue;' ];
+% e.g.: maskerLevel= withinRuns.variableValue;
+eval(cmd);
+
+% cue and test stimuli are identical except for a single difference
+% depending on the paradigm
+cueTestDifference= stimulusParameters.cueTestDifference;
+%  cue characteristics before adding cue differences
+cueTargetLevel=targetLevel;
+cueMaskerFrequency=maskerFrequency;
+cueMaskerDuration=maskerDuration;
+cueMaskerLevel=maskerLevel;
+cueTargetFrequency=targetFrequency;
+cueGapDuration=gapDuration;
+
+% ----------------------------paradigm sensitive cue and masker settings
+% switch off unwanted components and base cue on target values
+% for catch trials switch off the target
+switch experiment.paradigm
+    % OHIO is a temporary special arrangement
+    case{'OHIOrand','OHIOspect','OHIOtemp','OHIOspectemp','OHIOabs'}
+        % these values must be set in MAPparamsOHIO
+        targetFrequency=experiment.OHIOfrequencies;
+        numOHIOtones=stimulusParameters.numOHIOtones;
+        maskerType='OHIO';
+        targetType='OHIO';
+        
+        % globalStimParams.beginSilences says when each tone begins
+        % targetFrequency specifies the frequency of each tone
+        % targetLevel is the level of each tone
+        switch experiment.paradigm
+            case 'OHIOabs'
+                % only one tone
+                targetFrequency=targetFrequency(numOHIOtones);
+                globalStimParams.beginSilences=0.01;
+                targetDuration=0.01;
+            case 'OHIOrand'
+                % select random frequencies from the list
+                x=rand(12,1); [x idx]=sort(x);
+                targetFrequency=targetFrequency(idx(1:numOHIOtones));
+                thresholds=experiment.OHIOthresholds;
+                targetLevel=thresholds(idx(1:numOHIOtones))+targetLevel;
+                globalStimParams.beginSilences=0.01:0.02:...
+                    0.01+0.02*(numOHIOtones-1);
+                targetDuration=numOHIOtones*0.02;
+            case 'OHIOspect'
+                % only one tone with multiple frequencies
+                targetFrequency=fliplr(targetFrequency);
+                targetFrequency=targetFrequency(1:numOHIOtones);
+                thresholds=experiment.OHIOthresholds;
+                thresholds=fliplr(thresholds);
+                targetLevel=thresholds(1:numOHIOtones)+targetLevel;
+                globalStimParams.beginSilences=...
+                    repmat(0.01, 1, numOHIOtones);
+                targetDuration=0.02;
+            case 'OHIOspectemp'
+                % only one tone with multiple frequencies
+                targetFrequency=fliplr(targetFrequency);
+                targetFrequency=targetFrequency(1:numOHIOtones);
+                thresholds=experiment.OHIOthresholds;
+                thresholds=fliplr(thresholds);
+                targetLevel=thresholds(1:numOHIOtones)+targetLevel;
+                globalStimParams.beginSilences=0.01:0.02:...
+                    0.01+0.02*(numOHIOtones-1);
+                targetDuration=numOHIOtones*0.02;
+            case 'OHIOtemp'
+                % use only one tone repeatedly
+                tonesToUse=10;
+                targetFrequency=targetFrequency(tonesToUse);
+                targetFrequency=repmat(targetFrequency,1,numOHIOtones);
+                thresholds=experiment.OHIOthresholds;
+                thresholds=thresholds(tonesToUse);
+                targetLevel=repmat(thresholds,1,numOHIOtones)+targetLevel;
+                globalStimParams.beginSilences=0.01:0.02:...
+                    0.01+0.02*(numOHIOtones-1);
+                targetDuration=numOHIOtones*0.02;
+        end
+        % still in OHIO
+        % Dummy values to make things work although no masker or cue used
+        % target values have changed and this affects the cue values
+        cueMaskerLevel=targetLevel;
+        cueTargetLevel=targetLevel;
+        cueTargetFrequency=targetFrequency;
+        cueMaskerFrequency=targetFrequency;
+        maskerFrequency=targetFrequency;
+        maskerLevel=targetLevel;
+        disp(['OHIO frequencies= ' num2str(targetFrequency)])
+end
+
+% --- set cueTarget level according to assessment method
+% cue-test difference applies only with singleInterval
+switch experiment.threshEstMethod
+    case {'2I2AFC++', '2I2AFC+++'}
+        % For 2IFC the cue stimulus (masker + probe) is the 'no' window
+        % and the target stimulus (masker+probe) is the 'yes' window
+        % the order of presentation is decided at the last minute.
+        cueTargetLevel=-100;    % the target is never in the 'no' window
+        cueMaskerLevel=maskerLevel; % masker level is the same in both
+    otherwise
+        % 'single interval' or max likelihood
+        switch experiment.paradigm
+            % cue target is more audible
+            case {'training','absThreshold', 'absThreshold_8',  ...
+                    'TENtest', 'threshold_duration','discomfort',...
+                    'overShoot','overShootB','overShootMB1', ...
+                    'overShootMB2', 'OHIO','OHIOabs','OHIOspect'}
+                cueTargetLevel=targetLevel+cueTestDifference;
+                
+            case {'forwardMasking','forwardMaskingD','trainingIFMC', ...
+                    'TMC','TMC_16ms', 'TMC - ELP', 'IFMC','IFMC_8ms', 'FMreProbe'}
+                % cue masker is weaker to make target more audible
+                cueMaskerLevel=maskerLevel-cueTestDifference;
+        end
+end
+
+% ----------------------------- catch trial
+if withinRuns.catchTrial
+    targetLevel=-100;	% no target
+end
+
+% -------------------------------------- Checks on excessive signal level
+
+% clipping is relevant only for soundcard use (not modelling)
+switch experiment.ear
+    case {'left', 'right', 'diotic',...
+            'dichotic', 'dioticLeft', 'dichoticRight'}
+        experiment.headphonesUsed=1;
+    otherwise
+        experiment.headphonesUsed=0;
+end
+
+% NB calibration *reduces* the level of the soundCard output
+switch experiment.ear
+    case {'left', 'right', 'diotic',...
+            'dichotic', 'dioticLeft', 'dichoticRight'}
+        clippingLevel=91+stimulusParameters.calibrationdB;
+        soundCardMinimum=clippingLevel-20*log10(2^24);
+    otherwise
+        clippingLevel=inf;
+        soundCardMinimum=-inf;
+end
+
+% Check for extreme WRV values and abort if necessary
+% WRVname specifies the value that changes from trial to trial
+withinRuns.forceThreshold=[];
+switch stimulusParameters.WRVname
+    % check for extreme values. Note that one of the tones might be switched off
+    case 'maskerLevel'
+        upperLevel=stimulusParameters.WRVlimits(2);
+        lowerLevel=stimulusParameters.WRVlimits(1);
+        if max(maskerLevel, cueMaskerLevel)> upperLevel
+            errormsg=['Level(' num2str(max(maskerLevel,cueMaskerLevel)) ...
+                ') is too high ***'];
+            withinRuns.forceThreshold=upperLevel;
+            withinRuns.forceThreshold=NaN;
+            return
+        end
+        if max(maskerLevel, cueMaskerLevel)< lowerLevel
+            errormsg=['Level(' num2str(max(maskerLevel,cueMaskerLevel)) ...
+                ') is too low ***'];
+            withinRuns.forceThreshold=lowerLevel;
+            withinRuns.forceThreshold=NaN;
+            return
+        end
+        
+        if max(maskerLevel, cueMaskerLevel)> clippingLevel
+            errormsg=['Level(' num2str(max(maskerLevel,cueMaskerLevel)) ...
+                ') is clipping ***'];
+            withinRuns.forceThreshold=clippingLevel;
+            withinRuns.forceThreshold=NaN;
+            return
+        end
+                
+    case 'targetLevel'
+        upperLevel=stimulusParameters.WRVlimits(2);
+        lowerLevel=stimulusParameters.WRVlimits(1);
+        if ~withinRuns.catchTrial
+            if max(targetLevel, cueTargetLevel)> upperLevel
+                errormsg=['target level (' ...
+                    num2str(max(targetLevel, cueTargetLevel)) ...
+                    ')  is too high ***'];
+                withinRuns.forceThreshold=upperLevel;
+            withinRuns.forceThreshold=NaN;
+                return
+            end
+            if max(targetLevel, cueTargetLevel)< lowerLevel
+                errormsg=['target level (' ...
+                    num2str(max(targetLevel, cueTargetLevel)) ...
+                    ')  is too low ***'];
+                withinRuns.forceThreshold=lowerLevel;
+            withinRuns.forceThreshold=NaN;
+                return
+            end
+            if max(targetLevel, cueTargetLevel)> clippingLevel
+                errormsg=['target level (' ...
+                    num2str(max(targetLevel, cueTargetLevel)) ...
+                    ')  is clipping ***'];
+                withinRuns.forceThreshold=upperLevel;
+            withinRuns.forceThreshold=NaN;
+                return
+            end
+        end    
+    case 'maskerDuration'
+        % this is odd! but harmless
+        if max(maskerDuration, cueMaskerDuration)> ...
+                stimulusParameters.WRVlimits(2)
+            errormsg=['maskerDuration (' ...
+                num2str(max(maskerDuration, cueMaskerDuration))...
+                ') is too long ***'];
+            withinRuns.forceThreshold=stimulusParameters.WRVlimits(2);
+            withinRuns.forceThreshold=NaN;
+            return
+        end
+        
+        if min(maskerDuration, cueMaskerDuration)...
+                < stimulusParameters.WRVlimits(1)
+            errormsg=['maskerDuration (' num2str(maskerLevel) ...
+                ') too short ***'];
+            withinRuns.forceThreshold=stimulusParameters.WRVlimits(1);
+            withinRuns.forceThreshold=NaN;
+            return
+        end
+        
+        % legacy programming
+    case 'gapDuration'
+        if gapDuration<0
+            errormsg=['gapDuration (' num2str(gapDuration) ...
+                ') is less than zero  ***'];
+            return
+        end
+        
+    case 'maskerFrequency'
+        switch experiment.paradigm
+            case 'bandwidth'
+                frequency=maskerFrequency';
+                if stimulusParameters.WRVstep<0
+                    lowerLevel=stimulusParameters.targetFrequency;
+                    upperLevel=stimulusParameters.targetFrequency*2;
+                else
+                    lowerLevel=stimulusParameters.targetFrequency/3;
+                    upperLevel=stimulusParameters.targetFrequency;
+                end
+                
+                if frequency(1)>upperLevel || frequency(1)<lowerLevel
+                    errormsg=['frequency out of range: ' ...
+                        num2str(frequency)];
+                    withinRuns.forceThreshold=frequency;
+                    return
+                end
+            otherwise
+        end
+        
+    case 'maskerRelativeFrequency'
+        if  maskerRelativeFrequency<stimulusParameters.WRVlimits(1)
+            errormsg=['masker frequency (' ...
+                num2str(frequencyDifference) ...
+                ')  is outside WRV limits ***'];
+            withinRuns.forceThreshold=stimulusParameters.WRVlimits(1) ;
+            return
+        end
+        if   maskerRelativeFrequency>stimulusParameters.WRVlimits(2)
+            errormsg=['masker frequency (' ...
+                num2str(frequencyDifference) ...
+                ')  is outside WRV limits ***'];
+            withinRuns.forceThreshold=stimulusParameters.WRVlimits(2) ;
+            return
+        end
+        
+end
+
+% --------------------------------Ear ----------------------------------
+globalStimParams.ears='specified';
+% ear: 1=left, 2=right
+switch experiment.ear
+    case 'left'
+        maskerEar=1;
+        targetEar=1;
+    case 'right'
+        maskerEar=2;
+        targetEar=2;
+    case 'dichoticLeft'
+        maskerEar=2;
+        targetEar=1;
+    case 'dichoticRight'
+        maskerEar=1;
+        targetEar=2;
+    case 'diotic'
+        maskerEar=1;
+        targetEar=1;
+        globalStimParams.ears='diotic';
+    case {'MAPmodel', 'MAPmodelMultiCh', 'MAPmodelSingleCh', 'MAPmodelListen',...
+            'statsModelLogistic', 'statsModelRareEvent'}
+        maskerEar=1;
+        targetEar=1;
+end
+
+backgroundType=stimulusParameters.backgroundType;
+switch stimulusParameters.backgroundType
+    case {'noiseDich', 'pinkNoiseDich'}
+%     case 'Dich'
+        % dich means put the background in the ear opposite to the target
+        backgroundType=backgroundType(1:end-4);
+        switch targetEar
+            case 1
+                backgroundEar=2;
+            case 2
+                backgroundEar=1;
+        end
+    otherwise
+%             case {'none','noise', 'pinkNoise', 'TEN','babble'}
+        backgroundEar=targetEar;
+end
+
+% ------------------------------- Make Stimulus -------------------
+% single interval up/down plays cue then target stimulus
+% 2IFC uses cue stimulus as interval with no target
+globalStimParams.FS=stimulusParameters.sampleRate;
+dt=1/stimulusParameters.sampleRate;
+globalStimParams.dt=dt;
+stimulusParameters.dt=dt; % for use later
+
+% calibration of sound output
+correctiondB=stimulusParameters.calibrationdB;
+globalStimParams.audioOutCorrection=10^(correctiondB/20);
+% the output will be reduced by this amount in stimulusCreate
+% i.e.  audio=audio/globalStimParams.audioOutCorrection
+% A 91 dB level will yield a peak amp of 1 for calibration=0
+% A 91 dB level will yield a peak amp of 0.4467 for calibration=7
+% A 98 dB level will yield a peak amp of 1 for calibration=7
+
+precedingSilence=stimulusParameters.stimulusDelay;
+% all stimuli have 20 ms terminal silence.
+% this is clearance for modelling late-ringing targets
+terminalSilence=.03;
+
+% Now compute overall duration of the stimulus
+% note that all endsilence values are set to -1
+%  so that they will fill with terminal silence as required to make
+%  components equal in length
+% We need to find the longest possible duration
+duration(1)=precedingSilence+maskerDuration+cueGapDuration...
+    +targetDuration+terminalSilence;
+duration(2)=precedingSilence+maskerDuration+gapDuration...
+    +targetDuration+ terminalSilence;
+% If the gap is negative we need to ignore it when estimating total length
+duration(3)=precedingSilence+maskerDuration+ terminalSilence;
+globalStimParams.overallDuration=max(duration);
+globalStimParams.nSignalPoints=...
+    round(globalStimParams.overallDuration/globalStimParams.dt);
+
+%           ----------------------------------------------cue stimulus
+% cue masker
+componentNo=1;
+precedingSilence=stimulusParameters.stimulusDelay;
+stimComponents(maskerEar,componentNo).type=maskerType;
+stimComponents(maskerEar,componentNo).toneDuration=cueMaskerDuration;
+stimComponents(maskerEar,componentNo).frequencies=cueMaskerFrequency;
+stimComponents(maskerEar,componentNo).amplitudesdB=cueMaskerLevel;
+stimComponents(maskerEar,componentNo).beginSilence=precedingSilence;
+stimComponents(maskerEar,componentNo).endSilence=-1;
+stimComponents(maskerEar,componentNo).AMfrequency=0;
+stimComponents(maskerEar,componentNo).AMdepth=0;
+if rampDuration<maskerDuration
+    % ramps must be shorter than the signal
+    stimComponents(maskerEar,componentNo).rampOnDur=rampDuration;
+    stimComponents(maskerEar,componentNo).rampOffDur=rampDuration;
+else
+    % or squeeze the ramp in
+    stimComponents(maskerEar,componentNo).rampOnDur=maskerDuration/2;
+    stimComponents(maskerEar,componentNo).rampOffDur=maskerDuration/2;
+end
+stimComponents(maskerEar,componentNo).phases=...
+    stimulusParameters.maskerPhase;
+stimComponents(maskerEar,componentNo).niterations=0;    % for IRN only
+% stimComponents(targetEar,componentNo)
+
+% cue target
+componentNo=2;
+precedingSilence=precedingSilence + maskerDuration+cueGapDuration;
+stimComponents(targetEar,componentNo).type=targetType;
+stimComponents(targetEar,componentNo).toneDuration=targetDuration;
+stimComponents(targetEar,componentNo).frequencies=cueTargetFrequency;
+stimComponents(targetEar,componentNo).amplitudesdB=cueTargetLevel;
+stimComponents(targetEar,componentNo).beginSilence=precedingSilence;
+stimComponents(targetEar,componentNo).endSilence=-1;
+stimComponents(targetEar,componentNo).AMfrequency=0;
+stimComponents(targetEar,componentNo).AMdepth=0;
+if rampDuration<targetDuration
+    % ramps must be shorter than the signal
+    stimComponents(targetEar,componentNo).rampOnDur=rampDuration;
+    stimComponents(targetEar,componentNo).rampOffDur=rampDuration;
+else
+    stimComponents(targetEar,componentNo).rampOnDur=0;
+    stimComponents(targetEar,componentNo).rampOffDur=0;
+end
+stimComponents(targetEar,componentNo).phases=...
+    stimulusParameters.targetPhase;
+% stimComponents(targetEar,componentNo)
+
+% background same ear as target
+componentNo=3;
+stimComponents(backgroundEar,componentNo).type=backgroundType;
+switch backgroundType
+    case 'TEN'
+        fileName=['..' filesep '..' filesep ...
+            'multithresholdResources' filesep ...
+            'backgrounds and maskers'...
+            filesep 'ten.wav'];
+        [tenNoise, FS]=wavread(fileName);
+        tenNoise=resample(tenNoise, globalStimParams.FS, FS);
+        stimComponents(backgroundEar,componentNo).type='file';
+        stimComponents(backgroundEar,componentNo).stimulus=tenNoise';
+end
+stimComponents(backgroundEar,componentNo).toneDuration=...
+    globalStimParams.overallDuration;
+stimComponents(backgroundEar,componentNo).amplitudesdB=backgroundLevel;
+stimComponents(backgroundEar,componentNo).beginSilence=0;
+stimComponents(backgroundEar,componentNo).endSilence=-1;
+stimComponents(backgroundEar,componentNo).AMfrequency=0;
+stimComponents(backgroundEar,componentNo).AMdepth=0;
+stimComponents(backgroundEar,componentNo).rampOnDur=rampDuration;
+stimComponents(backgroundEar,componentNo).rampOffDur=rampDuration;
+
+[cueStimulus, errormsg]=...
+    stimulusCreate(globalStimParams, stimComponents, 0);
+if ~isempty(errormsg)     % e.g. limits exceeded
+    errormsg
+    return
+end
+
+%               ------------------------------------------ test stimulus
+% masker
+componentNo=1;
+precedingSilence=stimulusParameters.stimulusDelay;
+stimComponents(maskerEar,componentNo).type=maskerType;
+stimComponents(maskerEar,componentNo).toneDuration=maskerDuration;
+stimComponents(maskerEar,componentNo).frequencies=maskerFrequency;
+stimComponents(maskerEar,componentNo).amplitudesdB=maskerLevel;
+stimComponents(maskerEar,componentNo).beginSilence=precedingSilence;
+stimComponents(maskerEar,componentNo).endSilence=-1;
+stimComponents(maskerEar,componentNo).AMfrequency=0;
+stimComponents(maskerEar,componentNo).AMdepth=0;
+if rampDuration<maskerDuration
+    % ramps must be shorter than the signal
+    stimComponents(maskerEar,componentNo).rampOnDur=rampDuration;
+    stimComponents(maskerEar,componentNo).rampOffDur=rampDuration;
+else
+    stimComponents(maskerEar,componentNo).rampOnDur=maskerDuration/2;
+    stimComponents(maskerEar,componentNo).rampOffDur=maskerDuration/2;
+end
+stimComponents(maskerEar,componentNo).phases=...
+    stimulusParameters.maskerPhase;
+stimComponents(maskerEar,componentNo).niterations=0;    % for IRN only
+
+% target
+componentNo=2;
+targetDelay=precedingSilence+ maskerDuration+ gapDuration;
+stimComponents(targetEar,componentNo).type=targetType;
+stimComponents(targetEar,componentNo).toneDuration=targetDuration;
+stimComponents(targetEar,componentNo).frequencies=targetFrequency;
+stimComponents(targetEar,componentNo).amplitudesdB=targetLevel;
+stimComponents(targetEar,componentNo).beginSilence=targetDelay;
+stimComponents(targetEar,componentNo).endSilence=-1;
+stimComponents(targetEar,componentNo).AMfrequency=0;
+stimComponents(targetEar,componentNo).AMdepth=0;
+if rampDuration<targetDuration
+    % ramps must be shorter than the signal
+    stimComponents(targetEar,componentNo).rampOnDur=rampDuration;
+    stimComponents(targetEar,componentNo).rampOffDur=rampDuration;
+else
+    stimComponents(targetEar,componentNo).rampOnDur=0;
+    stimComponents(targetEar,componentNo).rampOffDur=0;
+end
+stimComponents(targetEar,componentNo).phases=stimulusParameters.targetPhase;
+% stimComponents(targetEar,componentNo)
+
+% background same ear as target
+componentNo=3;
+stimComponents(backgroundEar,componentNo).type=backgroundType;
+switch backgroundType
+    case 'TEN'
+        fileName=['..' filesep '..' filesep ...
+            'multithresholdResources' filesep ...
+            'backgrounds and maskers'...
+            filesep 'ten.wav'];
+        [tenNoise, FS]=wavread(fileName);
+
+        tenNoise=resample(tenNoise, globalStimParams.FS, FS);
+        stimComponents(backgroundEar,componentNo).type='file';
+        stimComponents(backgroundEar,componentNo).stimulus=tenNoise';
+end
+stimComponents(backgroundEar,componentNo).toneDuration=...
+    globalStimParams.overallDuration;
+stimComponents(backgroundEar,componentNo).amplitudesdB=backgroundLevel;
+stimComponents(backgroundEar,componentNo).beginSilence=0;
+stimComponents(backgroundEar,componentNo).endSilence=-1;
+stimComponents(backgroundEar,componentNo).rampOnDur=rampDuration;
+stimComponents(backgroundEar,componentNo).rampOffDur=rampDuration;
+stimComponents(backgroundEar,componentNo).AMfrequency=0;
+stimComponents(backgroundEar,componentNo).AMdepth=0;
+
+% timings used when evaluating MAP peripheral model
+% this is the Slope during which spikes are counted
+switch experiment.paradigm
+    case 'gapDetection'
+        % gap is the 'target' in this case
+        stimulusParameters.testTargetBegins=...
+            stimulusParameters.stimulusDelay...
+            +stimulusParameters.maskerDuration;
+        stimulusParameters.testTargetEnds=...
+            stimulusParameters.testTargetBegins+withinRuns.variableValue;
+%     case 'SRT'
+%         set(handles.editdigitInput,'visible','off')
+    otherwise
+        stimulusParameters.testTargetBegins=targetDelay;
+        stimulusParameters.testTargetEnds=targetDelay+targetDuration;
+end
+
+% ------------------------------------------------------------- play!
+% Create and play stimulus (as required by different paradigms)
+switch experiment.ear
+    case {'statsModelLogistic', 'statsModelRareEvent'}
+        audio=[0;0];            % no need to compute stimulus
+        
+    otherwise                   % create the stimulus
+        [targetStimulus, errormsg]= ...
+            stimulusCreate(globalStimParams, stimComponents, 0);
+        
+        if ~isempty(errormsg)   % e.g. limits exceeded
+            errormsg
+            return
+        end
+        
+        switch experiment.ear
+            case {'MAPmodel' , 'MAPmodelMultiCh', 'MAPmodelSingleCh', 'MAPmodelListen'}
+                % model requires no calibration correction;
+                %  signal is already in Pascals
+                globalStimParams.audioOutCorrection=1;
+                % use only the targetStimulus for the MAP model
+                audio=targetStimulus;
+                
+            otherwise           % left, right diotic dichotic
+                if stimulusParameters.includeCue
+                    audio= [cueStimulus;  targetStimulus];
+                else            % no cue
+                    audio=targetStimulus;
+                end
+        end
+        
+        % playtime
+        % order of the cue and test stimuli varies for 2AFC
+        switch experiment.threshEstMethod
+            case {'2I2AFC++', '2I2AFC+++'}
+                % intervening silence (currently none; masking delay serves this purpose)
+                IAFCinterveningSilence=zeros(round(AFCsilenceDuration/dt),2);
+                if rand>0.5				% put test stimulus first
+                    stimulusParameters.testTargetBegins=targetDelay ;
+                    stimulusParameters.testTargetEnds= ...
+                        targetDelay+targetDuration;
+                    stimulusParameters.testNonTargetBegins=...
+                        length(cueStimulus)*dt ...
+                        + AFCsilenceDuration +targetDelay ;
+                    stimulusParameters.testNonTargetEnds=...
+                        length(cueStimulus)*dt ...
+                        + AFCsilenceDuration+targetDelay+targetDuration;
+                    
+                    set(handles.pushbutton1,'backgroundcolor','r'), drawnow
+                    y=audioplayer(targetStimulus, globalStimParams.FS, 24);
+                    playblocking(y)
+                    set(handles.pushbutton1,'backgroundcolor',...
+                        get(0,'defaultUicontrolBackgroundColor')), drawnow
+                    y=audioplayer(IAFCinterveningSilence, ...
+                        globalStimParams.FS, 24);
+                    playblocking(y)
+                    set(handles.pushbutton2,'backgroundcolor','r'), drawnow
+                    y=audioplayer(cueStimulus, globalStimParams.FS, 24);
+                    playblocking(y)
+                    set(handles.pushbutton2,'backgroundcolor',...
+                        get(0,'defaultUicontrolBackgroundColor')), drawnow
+                    withinRuns.stimulusOrder='targetFirst';
+                    audio= [targetStimulus; IAFCinterveningSilence; ...
+                        cueStimulus];   % for plotting purposes later
+                    
+                else					% put test stimulus second
+                    stimulusParameters.testTargetBegins=...
+                        length(cueStimulus)*dt ...
+                        + AFCsilenceDuration +targetDelay ;
+                    stimulusParameters.testTargetEnds=...
+                        length(cueStimulus)*dt ...
+                        + AFCsilenceDuration+targetDelay+targetDuration;
+                    stimulusParameters.testNonTargetBegins=targetDelay ;
+                    stimulusParameters.testNonTargetEnds=...
+                        targetDelay+targetDuration;
+                    
+                    set(handles.pushbutton1,'backgroundcolor','r'),drawnow
+                    y=audioplayer(cueStimulus, globalStimParams.FS, 24);
+                    playblocking(y)
+                    set(handles.pushbutton1,'backgroundcolor',...
+                        get(0,'defaultUicontrolBackgroundColor')), drawnow
+                    y=audioplayer(IAFCinterveningSilence, ...
+                        globalStimParams.FS, 24);
+                    playblocking(y)
+                    set(handles.pushbutton2,'backgroundcolor','r'), drawnow
+                    y=audioplayer(targetStimulus, globalStimParams.FS, 24);
+                    playblocking(y)
+                    set(handles.pushbutton2,'backgroundcolor',...
+                        get(0,'defaultUicontrolBackgroundColor')), drawnow
+                    withinRuns.stimulusOrder='targetSecond';
+                    audio= [cueStimulus; IAFCinterveningSilence; ...
+                        targetStimulus];    % for plotting purposes later
+                end
+            otherwise                       % singleInterval
+                if strcmp(experiment.ear,'MAPmodel') ...
+                        || strcmp(experiment.ear,'MAPmodelMultiCh') ...
+                        || strcmp(experiment.ear,'MAPmodelSingleCh') ...
+                        ||strcmp(experiment.ear,'MAPmodelListen')
+                    % don't play for MAPmodel
+                    switch experiment.ear
+                        % except on special request
+                        case {'MAPmodelListen'}
+                            y=audioplayer(audio, globalStimParams.FS, 24);
+                            playblocking(y) % suspends operations until completed
+                    end
+                else
+                    y=audioplayer(audio, globalStimParams.FS, 24);
+                    playblocking(y)
+                end	  %   if experiment.ear
+        end	% switch experiment.threshEstMethod
+end % switch experiment.ear
+
+
+% switch experiment.ear
+%     case	{'MAPmodel', 'MAPmodelListen',  'MAPmodelMultiCh','MAPmodelSingleCh'}
+%         % save audio for later reference or for input to MAP model
+%         wavwrite(audio/max(audio), globalStimParams.FS,32,'stimulus')
+% end
+
+% Panel 1
+% graphical presentation of the stimulus
+% NB shown *after* the stimulus has been presented
+axes(expGUIhandles.axes1), cla
+% plot is HW rectified and plotted as dB re 28e-6
+% calibration is ignored
+t=dt:dt:dt*length(audio);
+plot(t,stimulusParameters.calibrationdB+20*log10((abs(audio)+1e-10)/28e-6))
+% set(gca,'xtick',[])
+ylim([-20 100])
+ylabel('stimulus (dB SPL)')
+xlim([0 t(end)])
+grid on
+header=[betweenRuns.variableName1  ': ' ...
+    num2str(betweenRuns.var1Sequence(betweenRuns.runNumber))];
+header=[header '      ' num2str(...
+    betweenRuns.var2Sequence(betweenRuns.runNumber)) ':' ...
+    betweenRuns.variableName2 ];
+title(header)
+
Binary file multithreshold 1.46/paradigms/paradigmList.mat has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/paradigms/paradigm_GOM.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,45 @@
+function paradigm_GOM(handles)
+global stimulusParameters experiment betweenRuns
+
+paradigm_training(handles) % default
+
+stimulusParameters.WRVname='maskerLevel';
+stimulusParameters.WRVstartValues=20;
+stimulusParameters.WRVsteps= [-10 -2];
+stimulusParameters.WRVlimits=[-30 110];
+
+% target variable: slope=1, start going down.
+withinRuns.direction='up';
+experiment.psyFunSlope=-1;
+
+betweenRuns.variableName1='targetLevel';
+betweenRuns.variableList1=25: 5: 70;
+betweenRuns.variableName2='maskerRelativeFrequency';
+betweenRuns.variableList2=[1 0.5];
+betweenRuns.randomizeSequence=1; % 'random sequence'
+
+stimulusParameters.maskerType='tone';
+stimulusParameters.maskerPhase='sin';
+stimulusParameters.maskerDuration=0.104;
+stimulusParameters.maskerLevel=stimulusParameters.WRVstartValues(1);
+stimulusParameters.maskerRelativeFrequency=betweenRuns.variableList2;
+
+stimulusParameters.gapDuration=0.0002;
+
+stimulusParameters.targetType='tone';
+stimulusParameters.targetPhase='sin';
+% 		retain current target frequency
+x=str2num(get(handles.edittargetFrequency,'string'));
+stimulusParameters.targetFrequency=x(1);
+
+stimulusParameters.targetDuration=0.004;
+stimulusParameters.targetLevel=stimulusParameters.WRVstartValues(1);
+
+stimulusParameters.rampDuration=0.002;
+
+% instructions to user
+%   single interval up/down no cue
+stimulusParameters.instructions{1}= [{'YES if you hear the tone clearly'}, { }, { 'NO if not (or you are uncertain'}];
+%   single interval up/down with cue
+stimulusParameters.instructions{2}= [{'count the tones you hear clearly'}, { }, { 'ignore indistinct tones'}];
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/paradigms/paradigm_IFMC.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,41 @@
+function paradigm_IFMC(handles)
+global stimulusParameters experiment betweenRuns
+
+paradigm_training(handles) % default
+
+stimulusParameters.WRVname='maskerLevel';
+stimulusParameters.WRVstartValues=-10;
+stimulusParameters.WRVsteps= [-10 -2];
+stimulusParameters.WRVlimits=[-30 110];
+
+experiment.psyFunSlope = -1;
+withinRuns.direction='up';
+
+betweenRuns.variableName1='maskerRelativeFrequency';
+betweenRuns.variableList1=[1       0.5       1.6   .9 .7   1.1 1.3      ];
+betweenRuns.variableName2='targetFrequency';
+% keep old list of target frequencies
+betweenRuns.variableList2=str2num(get(handles.edittargetFrequency,'string'));
+betweenRuns.randomizeSequence=1; % 'random sequence'
+
+stimulusParameters.maskerDuration=0.108;
+stimulusParameters.maskerLevel=stimulusParameters.WRVstartValues(1);
+stimulusParameters.maskerRelativeFrequency=betweenRuns.variableList1;
+
+stimulusParameters.gapDuration=0.01;
+
+stimulusParameters.targetType='tone';
+stimulusParameters.targetPhase='sin';
+stimulusParameters.targetFrequency=betweenRuns.variableList2(1);
+stimulusParameters.targetDuration=0.016;
+stimulusParameters.targetLevel=NaN;
+
+stimulusParameters.rampDuration=0.004;
+
+% instructions to user
+% single interval up/down no cue
+stimulusParameters.instructions{1}=[{'YES if you hear the added click'}, { }, { 'NO if not (or you are uncertain'}];
+% single interval up/down with cue
+stimulusParameters.instructions{2}=[{'count how many distinct clicks you hear'},{'ignore the tones'},{' '},...
+    {'The clicks must be **clearly distinct** to count'}];
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/paradigms/paradigm_IFMC_16ms.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,41 @@
+function paradigm_IFMC_8ms(handles)
+global stimulusParameters experiment betweenRuns
+
+paradigm_training(handles) % default
+
+stimulusParameters.WRVname='maskerLevel';
+stimulusParameters.WRVstartValues=50;
+stimulusParameters.WRVsteps= [-10 -2];
+stimulusParameters.WRVlimits=[-30 110];
+
+experiment.psyFunSlope = -1;
+withinRuns.direction='up';
+
+betweenRuns.variableName1='maskerRelativeFrequency';
+betweenRuns.variableList1=[1       0.5       1.6   .9 .7   1.1 1.3      ];
+betweenRuns.variableName2='targetFrequency';
+% keep old list of target frequencies
+betweenRuns.variableList2=str2num(get(handles.edittargetFrequency,'string'));
+betweenRuns.randomizeSequence=1; % 'random sequence'
+
+stimulusParameters.maskerDuration=0.108;
+stimulusParameters.maskerLevel=stimulusParameters.WRVstartValues(1);
+stimulusParameters.maskerRelativeFrequency=betweenRuns.variableList1;
+
+stimulusParameters.gapDuration=0.01;
+
+stimulusParameters.targetType='tone';
+stimulusParameters.targetPhase='sin';
+stimulusParameters.targetFrequency=betweenRuns.variableList2(1);
+stimulusParameters.targetDuration=0.016;
+stimulusParameters.targetLevel=NaN;
+
+stimulusParameters.rampDuration=0.004;
+
+% instructions to user
+% single interval up/down no cue
+stimulusParameters.instructions{1}=[{'YES if you hear the added click'}, { }, { 'NO if not (or you are uncertain'}];
+% single interval up/down with cue
+stimulusParameters.instructions{2}=[{'count how many distinct clicks you hear'},{'ignore the tones'},{' '},...
+    {'The clicks must be **clearly distinct** to count'}];
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/paradigms/paradigm_SRT.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,72 @@
+function paradigm_SRT(handles)
+global stimulusParameters experiment betweenRuns
+
+stimulusParameters.subjectSampleRate=44100;
+
+%  assessment method
+% {'oneIntervalUpDown', 'MaxLikelihood', '2I2AFC++', '2I2AFC+++'}
+experiment.threshEstMethod='oneIntervalUpDown';
+% {'cued', 'noCue'};
+stimulusParameters.includeCue=0;
+stimulusParameters.cueTestDifference=10;
+
+experiment.singleIntervalMaxTrials=10;
+experiment.maxTrials=10;
+experiment.allowCatchTrials= 0;
+
+% {'tone','noise', 'pinkNoise','whiteNoise','OHIO'}
+stimulusParameters.WRVname='targetLevel';
+stimulusParameters.WRVstartValues=60 ;
+stimulusParameters.WRVsteps=[5 2];
+stimulusParameters.WRVlimits=[-30 110];
+
+% target variable: slope=1, start going down.
+experiment.psyFunSlope=1;
+withinRuns.direction='down';
+
+betweenRuns.variableName1='targetFrequency';
+betweenRuns.variableList1=1000;
+betweenRuns.variableName2='maskerDuration';
+betweenRuns.variableList2=0.1 ;
+% 1='fixed sequence', 2='randomize within blocks', 3='randomize across
+% blocks'
+betweenRuns.randomizeSequence=1; % 'random sequence'
+
+% delay > masker > gap > target
+
+stimulusParameters.stimulusDelay=0.3;
+
+% maskerTypes={'tone','noise', 'pinkNoise','TEN','whiteNoise'};
+stimulusParameters.maskerType='tone';
+stimulusParameters.maskerPhase='sin';
+stimulusParameters.maskerDuration=0.0;
+stimulusParameters.maskerLevel= -50;
+stimulusParameters.maskerRelativeFrequency= 1 ;  % not used
+
+stimulusParameters.gapDuration=0.0;
+
+% targetTypes={'tone','noise', 'pinkNoise','whiteNoise','OHIO'};
+stimulusParameters.targetType='digitStrings';
+stimulusParameters.targetPhase='sin';
+stimulusParameters.targetFrequency=1000;
+stimulusParameters.targetDuration=2;
+stimulusParameters.targetLevel=stimulusParameters.WRVstartValues(1);
+
+stimulusParameters.rampDuration=0.004;
+stimulusParameters.stimulusDelay=1;
+
+% forced choice window interval
+stimulusParameters.AFCsilenceDuration=0.5;
+
+% {'none','noise', 'pinkNoise', 'TEN','noiseDich', 'pinkNoiseDich','whiteNoise'}
+stimulusParameters.backgroundType='24TalkerBabble'; 
+stimulusParameters.backgroundLevel= 60;
+
+% instructions to user
+%   single interval up/down no cue
+stimulusParameters.instructions{1}= ...
+    [{'Type three digits in the box (top left)'}, { }, ...
+    {'then hit return'}];
+
+stimulusParameters.numOHIOtones=1;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/paradigms/paradigm_TENtest.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,33 @@
+function paradigm_TENtest(handles)
+global stimulusParameters experiment betweenRuns
+
+paradigm_training(handles) % default
+
+stimulusParameters.WRVname='targetLevel';
+stimulusParameters.WRVstartValues=40;
+stimulusParameters.WRVsteps=[10 2];
+stimulusParameters.WRVlimits=[-30 110];
+
+betweenRuns.variableName1='targetFrequency';
+betweenRuns.variableList1=[250 500 1000 2000 4000 8000 ];
+betweenRuns.variableName2='targetDuration';
+betweenRuns.variableList2= 0.25;
+betweenRuns.randomizeSequence=1; % 'random sequence'
+
+stimulusParameters.targetType='tone';
+stimulusParameters.targetPhase='sin';
+stimulusParameters.targetFrequency=betweenRuns.variableList1;
+stimulusParameters.targetDuration=0.5;
+stimulusParameters.targetLevel=stimulusParameters.WRVstartValues(1);
+
+% {'none','noise', 'pinkNoise', 'TEN','noiseDich', 'pinkNoiseDich','whiteNoise'}
+stimulusParameters.backgroundType='TEN'; 
+stimulusParameters.backgroundLevel=20;
+
+% instructions to user
+%   single interval up/down no cue
+stimulusParameters.instructions{1}=[{'YES if you hear the added click'}, { }, { 'NO if not (or you are uncertain'}];
+%   single interval up/down with cue
+stimulusParameters.instructions{2}=[{'count how many distinct clicks you hear'},{'ignore the tones'},{' '},...
+    {'The clicks must be **clearly distinct** to count'}];
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/paradigms/paradigm_TMC.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,44 @@
+function paradigm_TMC(handles)
+global stimulusParameters experiment betweenRuns
+
+paradigm_training(handles) % default
+
+stimulusParameters.WRVname='maskerLevel';
+stimulusParameters.WRVstartValues=-10;
+stimulusParameters.WRVsteps= [-10 -4];
+stimulusParameters.WRVlimits=[-30 110];
+
+stimulusParameters.cueTestDifference = 10;
+experiment.psyFunSlope = -1;
+withinRuns.direction='up';
+
+betweenRuns.variableName1='gapDuration';
+betweenRuns.variableList1=[.05 .08 .02 .06 .04 ];
+betweenRuns.variableName2='targetFrequency';
+% retain existing targetFrequencies
+betweenRuns.variableList2=str2num(get(handles.edittargetFrequency,'string'));
+betweenRuns.randomizeSequence=1; % 'random sequence'
+
+stimulusParameters.maskerType='tone';
+stimulusParameters.maskerPhase='sin';
+stimulusParameters.maskerDuration=0.108;
+stimulusParameters.maskerLevel=stimulusParameters.WRVstartValues(1);
+stimulusParameters.maskerRelativeFrequency=1;
+
+stimulusParameters.gapDuration=betweenRuns.variableList1;
+
+stimulusParameters.targetType='tone';
+stimulusParameters.targetPhase='sin';
+stimulusParameters.targetFrequency=betweenRuns.variableList2(1);
+stimulusParameters.targetDuration=0.016;
+stimulusParameters.targetLevel=NaN;
+
+stimulusParameters.rampDuration=0.004;
+
+% instructions to user
+%   single interval up/down no cue
+stimulusParameters.instructions{1}=[{'YES if you hear the added click'}, { }, { 'NO if not (or you are uncertain'}];
+%   single interval up/down with cue
+stimulusParameters.instructions{2}=[{'count how many distinct clicks you hear'},{'ignore the tones'},{' '},...
+    {'The clicks must be **clearly distinct** to count'}];
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/paradigms/paradigm_TMC_16ms.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,46 @@
+function paradigm_TMC_16ms(handles)
+global stimulusParameters experiment betweenRuns
+
+paradigm_training(handles) % default
+
+experiment.singleIntervalMaxTrials=20;
+
+stimulusParameters.WRVname='maskerLevel';
+stimulusParameters.WRVstartValues=50;
+stimulusParameters.WRVsteps= [-10 -4];
+stimulusParameters.WRVlimits=[-30 110];
+
+stimulusParameters.cueTestDifference = 10;
+experiment.psyFunSlope = -1;
+withinRuns.direction='up';
+
+betweenRuns.variableName1='gapDuration';
+betweenRuns.variableList1=[.01 .09 .03 .05 .07];
+betweenRuns.variableName2='targetFrequency';
+% retain existing targetFrequencies
+betweenRuns.variableList2=str2num(get(handles.edittargetFrequency,'string'));
+betweenRuns.randomizeSequence=1; % 'random sequence'
+
+stimulusParameters.maskerType='tone';
+stimulusParameters.maskerPhase='sin';
+stimulusParameters.maskerDuration=0.108;
+stimulusParameters.maskerLevel=stimulusParameters.WRVstartValues(1);
+stimulusParameters.maskerRelativeFrequency=1;
+
+stimulusParameters.gapDuration=betweenRuns.variableList1;
+
+stimulusParameters.targetType='tone';
+stimulusParameters.targetPhase='sin';
+stimulusParameters.targetFrequency=betweenRuns.variableList2(1);
+stimulusParameters.targetDuration=0.016;
+stimulusParameters.targetLevel=NaN;
+
+stimulusParameters.rampDuration=0.004;
+
+% instructions to user
+%   single interval up/down no cue
+stimulusParameters.instructions{1}=[{'YES if you hear the added click'}, { }, { 'NO if not (or you are uncertain'}];
+%   single interval up/down with cue
+stimulusParameters.instructions{2}=[{'count how many distinct clicks you hear'},{'ignore the tones'},{' '},...
+    {'The clicks must be **clearly distinct** to count'}];
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/paradigms/paradigm_TMCmodel.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,45 @@
+function paradigm_TMCmodel(handles)
+global stimulusParameters experiment betweenRuns
+
+paradigm_training(handles) % default
+
+stimulusParameters.WRVname='maskerLevel';
+stimulusParameters.WRVstartValues=30;
+stimulusParameters.WRVsteps= [-10 -4];
+stimulusParameters.WRVlimits=[-30 110];
+
+stimulusParameters.cueTestDifference = 10;
+experiment.psyFunSlope = -1;
+withinRuns.direction='up';
+
+betweenRuns.variableName1='gapDuration';
+betweenRuns.variableList1=[ 0.09 0.01:0.02:0.07 0.02:0.02:.08 0.005];
+betweenRuns.variableName2='targetFrequency';
+% retain existing targetFrequencies
+betweenRuns.variableList2=str2num(get(handles.edittargetFrequency,'string'));
+betweenRuns.randomizeSequence=1; % 'random sequence'
+
+stimulusParameters.maskerType='tone';
+stimulusParameters.maskerPhase='sin';
+stimulusParameters.maskerDuration=0.108;
+stimulusParameters.maskerLevel=stimulusParameters.WRVstartValues(1);
+stimulusParameters.maskerRelativeFrequency=1;
+experiment.singleIntervalMaxTrials=10;
+
+stimulusParameters.gapDuration=betweenRuns.variableList1;
+
+stimulusParameters.targetType='tone';
+stimulusParameters.targetPhase='sin';
+stimulusParameters.targetFrequency=betweenRuns.variableList2(1);
+stimulusParameters.targetDuration=0.016;
+stimulusParameters.targetLevel=NaN;
+
+stimulusParameters.rampDuration=0.004;
+
+% instructions to user
+%   single interval up/down no cue
+stimulusParameters.instructions{1}=[{'YES if you hear the added click'}, { }, { 'NO if not (or you are uncertain'}];
+%   single interval up/down with cue
+stimulusParameters.instructions{2}=[{'count how many distinct clicks you hear'},{'ignore the tones'},{' '},...
+    {'The clicks must be **clearly distinct** to count'}];
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/paradigms/paradigm_absThreshold.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,29 @@
+function paradigm_absThreshold(handles)
+global stimulusParameters experiment betweenRuns
+
+paradigm_training(handles) % default
+
+betweenRuns.variableName1='targetFrequency';
+betweenRuns.variableList1=[250 500 1000 2000 4000 8000 ];
+betweenRuns.variableName2='targetDuration';
+betweenRuns.variableList2= 0.25;
+
+stimulusParameters.targetFrequency=betweenRuns.variableList1;
+stimulusParameters.targetDuration=betweenRuns.variableList2;
+stimulusParameters.targetLevel=stimulusParameters.WRVstartValues(1);
+
+stimulusParameters.WRVstartValues=30;
+
+
+% forced choice window interval
+stimulusParameters.AFCsilenceDuration=0.5;
+
+
+% instructions to user
+%   single interval up/down no cue
+stimulusParameters.instructions{1}=[{'YES if you hear the added click'}, { }, { 'NO if not (or you are uncertain'}];
+%   single interval up/down with cue
+stimulusParameters.instructions{2}=[{'count how many distinct clicks you hear'},{'ignore the tones'},{' '},...
+    {'The clicks must be **clearly distinct** to count'}];
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/paradigms/paradigm_absThreshold_16.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,36 @@
+function paradigm_absThreshold16(handles)
+global stimulusParameters experiment betweenRuns
+
+paradigm_training(handles) % default
+
+betweenRuns.variableName1='targetFrequency';
+betweenRuns.variableList1=1000;
+betweenRuns.variableList1=str2num(get(handles.edittargetFrequency,'string'));
+betweenRuns.variableName2='targetDuration';
+betweenRuns.variableList2=0.016;
+betweenRuns.randomizeSequence=1; % 'random sequence'
+
+% delay > masker > gap > target
+
+
+stimulusParameters.targetType='tone';
+stimulusParameters.targetPhase='sin';
+stimulusParameters.targetFrequency=1000;
+stimulusParameters.targetDuration=0.016;
+stimulusParameters.targetLevel=stimulusParameters.WRVstartValues(1);
+
+stimulusParameters.rampDuration=0.004;
+
+experiment.stopCriteria2IFC=[75 3 5];
+experiment.singleIntervalMaxTrials=[20];
+
+
+% forced choice window interval
+stimulusParameters.AFCsilenceDuration=0.5;
+
+% instructions to user
+%   single interval up/down no cue
+stimulusParameters.instructions{1}= [{'YES if you hear the tone clearly'}, { }, { 'NO if not (or you are uncertain'}];
+%   single interval up/down with cue
+stimulusParameters.instructions{2}= [{'count the tones you hear clearly'}, { }, { 'ignore indistinct tones'}];
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/paradigms/paradigm_absThreshold_8.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,32 @@
+function paradigm_absThreshold_8(handles)
+global stimulusParameters experiment betweenRuns
+
+paradigm_training(handles) % default
+
+betweenRuns.variableName1='targetFrequency';
+betweenRuns.variableList1=1000;
+betweenRuns.variableList1=str2num(get(handles.edittargetFrequency,'string'));
+betweenRuns.variableName2='targetDuration';
+betweenRuns.variableList2=0.008 ;
+betweenRuns.randomizeSequence=1; % 'random sequence'
+
+% delay > masker > gap > target
+
+
+stimulusParameters.targetType='tone';
+stimulusParameters.targetPhase='sin';
+stimulusParameters.targetFrequency=1000;
+stimulusParameters.targetDuration=0.008;
+stimulusParameters.targetLevel=stimulusParameters.WRVstartValues(1);
+
+stimulusParameters.rampDuration=0.004;
+
+% forced choice window interval
+stimulusParameters.AFCsilenceDuration=0.5;
+
+% instructions to user
+%   single interval up/down no cue
+stimulusParameters.instructions{1}= [{'YES if you hear the tone clearly'}, { }, { 'NO if not (or you are uncertain'}];
+%   single interval up/down with cue
+stimulusParameters.instructions{2}= [{'count the tones you hear clearly'}, { }, { 'ignore indistinct tones'}];
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/paradigms/paradigm_discomfort.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,28 @@
+function paradigm_discomfort(handles)
+global stimulusParameters experiment betweenRuns
+
+paradigm_training(handles) % default
+
+stimulusParameters.WRVname='targetLevel';
+stimulusParameters.WRVstartValues=75 ;
+stimulusParameters.WRVsteps=[3 3];
+stimulusParameters.WRVlimits=[-30 110];
+
+betweenRuns.variableName1='targetFrequency';
+betweenRuns.variableList1=[1000];
+betweenRuns.variableName2='targetDuration';
+betweenRuns.variableList2=0.5 ;
+betweenRuns.randomizeSequence=2; % 'fixed sequence'
+
+stimulusParameters.stimulusDelay=0;
+
+stimulusParameters.targetType='tone';
+stimulusParameters.targetPhase='sin';
+stimulusParameters.targetFrequency=1000;
+stimulusParameters.targetDuration=0.5;
+stimulusParameters.targetLevel=stimulusParameters.WRVstartValues(1);
+
+stimulusParameters.instructions{1}= ['Is the tone ''comfortable'', ''loud'' or ''uncomfortable''?'];
+%   single interval up/down with cue
+stimulusParameters.instructions{2}= [];
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/paradigms/paradigm_forwardMasking.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,44 @@
+function paradigm_forwardMasking(handles)
+global stimulusParameters experiment betweenRuns
+
+paradigm_training(handles) % default
+
+stimulusParameters.WRVname='targetLevel';
+stimulusParameters.WRVstartValues=50;
+stimulusParameters.WRVsteps= [10 2];
+stimulusParameters.WRVlimits=[-30 110];
+
+betweenRuns.variableName1='gapDuration';
+betweenRuns.variableList1=[.005 0.01 0.02 0.04];
+betweenRuns.variableName2='maskerLevel';
+betweenRuns.variableList2=[20 40 60 80];
+betweenRuns.randomizeSequence=1; % 'random sequence'
+
+stimulusParameters.maskerType='tone';
+stimulusParameters.maskerPhase='sin';
+stimulusParameters.maskerDuration=0.108;
+stimulusParameters.maskerLevel=betweenRuns.variableList2;
+stimulusParameters.maskerRelativeFrequency=1;
+
+stimulusParameters.gapDuration=betweenRuns.variableList1;
+
+stimulusParameters.targetType='tone';
+stimulusParameters.targetPhase='sin';
+stimulusParameters.targetFrequency=1000;
+stimulusParameters.targetDuration=0.02;
+stimulusParameters.targetLevel=-stimulusParameters.WRVstartValues(1);
+
+stimulusParameters.rampDuration=0.01;
+
+% instructions to user
+% single interval up/down no cue
+stimulusParameters.instructions{1}=[{'YES if you hear the added click'}, { }, { 'NO if not (or you are uncertain'}];
+% single interval up/down with cue
+stimulusParameters.instructions{2}=[{'count how many distinct clicks you hear'},{'ignore the tones'},{' '},...
+    {'The clicks must be **clearly distinct** to count'}];
+
+experiment.maxTrials=10;
+% catchTrials
+experiment.allowCatchTrials= 1;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/paradigms/paradigm_overShoot.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,44 @@
+function paradigm_overShoot(handles)
+global stimulusParameters  betweenRuns
+
+paradigm_training(handles) % default
+
+stimulusParameters.WRVname='targetLevel';
+stimulusParameters.WRVstartValues=50;
+stimulusParameters.WRVsteps= [10 2];
+stimulusParameters.WRVlimits=[-30 110];
+
+betweenRuns.variableName1='gapDuration';
+betweenRuns.variableList1=[-.399 -.2];
+% betweenRuns.variableList1=[-.288 -.218 -.2 -.190 -.170 -.130 -.070 -.030 -.010 .005 .020 .080];
+% betweenRuns.variableList1=[-.350 -.238 -.213 -.180 -.160 -.100 -.040 -.020 0 .010 .040 .140];
+betweenRuns.variableName2='maskerLevel';
+betweenRuns.variableList2=50;
+betweenRuns.randomizeSequence=1; % 'random sequence'
+
+% delay > masker > gap > target
+stimulusParameters.stimulusDelay=0.3;
+
+stimulusParameters.maskerType='tone';
+stimulusParameters.maskerPhase='sin';
+stimulusParameters.maskerDuration=0.4;
+stimulusParameters.maskerLevel=betweenRuns.variableList2;
+stimulusParameters.maskerRelativeFrequency=1;
+
+stimulusParameters.gapDuration=betweenRuns.variableList1;
+
+stimulusParameters.targetType='tone';
+stimulusParameters.targetPhase='sin';
+stimulusParameters.targetFrequency=1000;
+stimulusParameters.targetDuration=0.01;
+stimulusParameters.targetLevel=-stimulusParameters.WRVstartValues(1);
+
+stimulusParameters.rampDuration=0.005;
+
+% instructions to user
+% single interval up/down no cue
+stimulusParameters.instructions{1}=[{'YES if you hear the added click'}, { }, { 'NO if not (or you are uncertain'}];
+% single interval up/down with cue
+stimulusParameters.instructions{2}=[{'count how many distinct clicks you hear'},{'ignore the tones'},{' '},...
+    {'The clicks must be **clearly distinct** to count'}];
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/paradigms/paradigm_psychometric.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,32 @@
+function paradigm_psychometric(handles)
+global stimulusParameters experiment betweenRuns
+
+paradigm_training(handles) % default
+
+experiment.printTracks=1;
+experiment.maxTrials=30;
+
+stimulusParameters.WRVname='targetLevel';
+stimulusParameters.WRVstartValues=30 ;
+stimulusParameters.WRVsteps=[10 2];
+stimulusParameters.WRVlimits=[-30 110];
+
+betweenRuns.variableName1='targetFrequency';
+betweenRuns.variableList1=1000.01:0.01:1000.05;
+betweenRuns.variableName2='targetDuration';
+betweenRuns.variableList2=0.1 ;
+betweenRuns.randomizeSequence=1; % 'random sequence'
+
+stimulusParameters.targetType='tone';
+stimulusParameters.targetPhase='sin';
+stimulusParameters.targetFrequency=1000;
+stimulusParameters.targetDuration=0.1;
+stimulusParameters.targetLevel=stimulusParameters.WRVstartValues(1);
+
+% instructions to user
+%   single interval up/down no cue
+stimulusParameters.instructions{1}= [{'YES if you hear the tone clearly'}, { }, { 'NO if not (or you are uncertain'}];
+%   single interval up/down with cue
+stimulusParameters.instructions{2}= [{'count the tones you hear clearly'}, { }, { 'ignore indistinct tones'}];
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/paradigms/paradigm_threshold_duration.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,33 @@
+function paradigm_threshold_duration(handles)
+global stimulusParameters experiment betweenRuns
+
+paradigm_training(handles) % default
+
+stimulusParameters.WRVname='targetLevel';
+stimulusParameters.WRVstartValues=40;
+stimulusParameters.WRVsteps=[10 2];
+stimulusParameters.WRVlimits=[-30 110];
+
+betweenRuns.variableName1='targetDuration';
+betweenRuns.variableList1=[ .016 .032 .064 .128 .256 .512];
+betweenRuns.variableName2='targetFrequency';
+betweenRuns.variableList2=1000;
+betweenRuns.randomizeSequence=1; % 'random sequence'
+
+stimulusParameters.targetType='tone';
+stimulusParameters.targetPhase='sin';
+% 		retain current target frequency
+x=str2num(get(handles.edittargetFrequency,'string'));
+stimulusParameters.targetFrequency=x(1);
+stimulusParameters.targetDuration=betweenRuns.variableList2;
+stimulusParameters.targetLevel=stimulusParameters.WRVstartValues(1);
+
+stimulusParameters.rampDuration=0.004;
+
+% instructions to user
+%   single interval up/down no cue
+stimulusParameters.instructions{1}=[{'YES if you hear the added click'}, { }, { 'NO if not (or you are uncertain'}];
+%   single interval up/down with cue
+stimulusParameters.instructions{2}=[{'count how many distinct clicks you hear'},{'ignore the tones'},{' '},...
+    {'The clicks must be **clearly distinct** to count'}];
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/paradigms/paradigm_training.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,72 @@
+function paradigm_training(handles)
+global stimulusParameters experiment betweenRuns
+
+stimulusParameters.subjectSampleRate=44100; % compatible with file input
+stimulusParameters.subjectSampleRate=50000; % compatible with file input
+
+%  assessment method
+% {'oneIntervalUpDown', 'MaxLikelihood', '2I2AFC++', '2I2AFC+++'}
+experiment.threshEstMethod='oneIntervalUpDown';
+% {'cued', 'noCue'};
+stimulusParameters.includeCue=1;
+stimulusParameters.cueTestDifference=10;
+
+experiment.singleIntervalMaxTrials=10;
+experiment.maxTrials=10;
+experiment.allowCatchTrials= 1;
+
+% {'tone','noise', 'pinkNoise','whiteNoise','OHIO'}
+stimulusParameters.WRVname='targetLevel';
+stimulusParameters.WRVstartValues=20 ;
+stimulusParameters.WRVsteps=[10 2];
+stimulusParameters.WRVlimits=[-30 110];
+
+% target variable: slope=1, start going down.
+experiment.psyFunSlope=1;
+withinRuns.direction='down';
+
+betweenRuns.variableName1='targetFrequency';
+betweenRuns.variableList1=1000;
+betweenRuns.variableName2='targetDuration';
+betweenRuns.variableList2=0.1 ;
+% 1='fixed sequence', 2='randomize within blocks', 3='randomize across
+% blocks'
+betweenRuns.randomizeSequence=1; % 'random sequence'
+
+% delay > masker > gap > target
+
+stimulusParameters.stimulusDelay=0.3;
+
+% maskerTypes={'tone','noise', 'pinkNoise','TEN','whiteNoise'};
+stimulusParameters.maskerType='tone';
+stimulusParameters.maskerPhase='sin';
+stimulusParameters.maskerDuration=0.0;
+stimulusParameters.maskerLevel= -50;
+stimulusParameters.maskerRelativeFrequency= 1 ;  % not used
+
+stimulusParameters.gapDuration=0.0;
+
+% targetTypes={'tone','noise', 'pinkNoise','whiteNoise','OHIO'};
+stimulusParameters.targetType='tone';
+stimulusParameters.targetPhase='sin';
+stimulusParameters.targetFrequency=1000;
+stimulusParameters.targetDuration=0.1;
+stimulusParameters.targetLevel=stimulusParameters.WRVstartValues(1);
+
+stimulusParameters.rampDuration=0.004;
+
+% forced choice window interval
+stimulusParameters.AFCsilenceDuration=0.5;
+
+% {'none','noise', 'pinkNoise', 'TEN','noiseDich', 'pinkNoiseDich','whiteNoise'}
+stimulusParameters.backgroundType='none'; 
+stimulusParameters.backgroundLevel=-100;
+
+% instructions to user
+%   single interval up/down no cue
+stimulusParameters.instructions{1}= [{'YES if you hear the tone clearly'}, { }, { 'NO if not (or you are uncertain'}];
+%   single interval up/down with cue
+stimulusParameters.instructions{2}= [{'count the tones you hear clearly'}, { }, { 'ignore indistinct tones'}];
+
+stimulusParameters.numOHIOtones=1;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/paradigms/paradigm_trainingIFMC.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,43 @@
+function paradigm_trainingIFMC(handles)
+global stimulusParameters experiment betweenRuns
+
+paradigm_training(handles) % default
+
+stimulusParameters.WRVname='maskerLevel';
+stimulusParameters.WRVstartValues=-10;
+stimulusParameters.WRVsteps= [-10 -2];
+stimulusParameters.WRVlimits=[-30 110];
+
+stimulusParameters.cueTestDifference = 10;
+experiment.psyFunSlope = -1;
+withinRuns.direction='up';
+
+betweenRuns.variableName1='maskerRelativeFrequency';
+betweenRuns.variableList1=[ 0.5       .9 .7   1.3 ];
+betweenRuns.variableName2='targetFrequency';
+% keep old list of target frequencies
+betweenRuns.variableList2=str2num(get(handles.edittargetFrequency,'string'));
+betweenRuns.randomizeSequence=1; % 'random sequence'
+
+stimulusParameters.maskerType='tone';
+stimulusParameters.maskerPhase='sin';
+stimulusParameters.maskerDuration=0.108;
+stimulusParameters.maskerLevel=stimulusParameters.WRVstartValues(1);
+stimulusParameters.maskerRelativeFrequency=betweenRuns.variableList1;
+
+stimulusParameters.gapDuration=0.03;
+
+stimulusParameters.targetType='tone';
+stimulusParameters.targetPhase='sin';
+stimulusParameters.targetFrequency=betweenRuns.variableList2(1);
+stimulusParameters.targetDuration=0.016;
+stimulusParameters.targetLevel= 30;
+
+stimulusParameters.rampDuration=0.004;
+
+% instructions to user
+% single interval up/down no cue
+stimulusParameters.instructions{1}=[{'YES if you hear the added click'}, { }, { 'NO if not (or you are uncertain'}];
+% single interval up/down with cue
+stimulusParameters.instructions{2}=[{'count how many distinct clicks you hear'},{'ignore the tones'},{' '},...
+    {'The clicks must be **clearly distinct** to count'}];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/paradigms/reserve team/OHIOthresholds.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,7 @@
+function experiment=OHIOthresholds(experiment)
+
+experiment.OHIOfrequencies=[494, 663, 870, 1125, 1442, 1838, 2338, 2957, 3725, 4680, 5866,  7334]; %Hz.
+% User must specify abs thresholds (dB SPL) of each tone frequency
+experiment.OHIOthresholds= [
+    9.1	8.6	8.1	7.9	9.8	10.5	13.5	15.0	17.4	19.4	22.6	25.2
+];
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/paradigms/reserve team/paradigm_OHIOabs.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,47 @@
+function paradigm_OHIOabs(handles)
+global stimulusParameters experiment betweenRuns
+
+paradigm_training(handles) % default
+
+% find the  threshold for a tonecomplex  consisting of a sequence of 10-ms tones
+%   whose frequencies are chosen at random from a list (OHIOfrequencies)
+% All tones are presented at the same level (SL) computed using absolute
+%   threshols specified in OHIOthresholds;
+% The duration of the complex is increased across runs and the number of tones is
+%   controlled by OHIOdurations, (for each 20 ms a further tone is added.
+% The frequency of the tones is changed on each trial
+
+experiment.OHIOfrequencies=[494, 663, 870, 1125, 1442, 1838, 2338, 2957, 3725, 4680, 5866,  7334]; %Hz.
+% User must specify abs thresholds (dB SPL) of each tone frequency
+% experiment.OHIOthresholds= [18	16	16	19	20	22	24	26	27	30	32	35];
+
+%  assessment method
+% {'oneIntervalUpDown', 'MaxLikelihood', '2I2AFC++', '2I2AFC+++'}
+experiment.threshEstMethod='oneIntervalUpDown';
+% {'cued', 'noCue'};
+
+stimulusParameters.WRVname='targetLevel';
+stimulusParameters.WRVstartValues=20 ;
+stimulusParameters.WRVsteps=[10 2];
+stimulusParameters.WRVlimits=[-30 110];
+
+betweenRuns.variableName1='numOHIOtones';
+betweenRuns.variableList1= 1:12; % i.e. the frequency to be used
+betweenRuns.variableName2='stimulusDelay';
+betweenRuns.variableList2=0.05;
+betweenRuns.randomizeSequence=2; % not random sequence
+
+stimulusParameters.targetType='OHIO';
+stimulusParameters.targetPhase='sin';
+stimulusParameters.targetFrequency=experiment.OHIOfrequencies;
+stimulusParameters.targetDuration=0.01; % overruled by OHIO program
+stimulusParameters.targetLevel=stimulusParameters.WRVstartValues(1);
+
+stimulusParameters.rampDuration=0.005;
+
+% instructions to user
+%   single interval up/down no cue
+stimulusParameters.instructions{1}= [{'YES if you hear the tone clearly'}, { }, { 'NO if not (or you are uncertain'}];
+%   single interval up/down with cue
+stimulusParameters.instructions{2}= [{'count the tones you hear clearly'}, { }, { 'ignore indistinct tones'}];
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/paradigms/reserve team/paradigm_OHIOrand.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,41 @@
+function paradigm_OHIOrand(handles)
+global stimulusParameters experiment betweenRuns
+
+paradigm_training(handles) % default
+
+% find the  threshold for a tonecomplex  consisting of a sequence of 10-ms tones
+%   whose frequencies are chosen at random from a list (OHIOfrequencies)
+% All tones are presented at the same level (SL) computed using absolute
+%   threshols specified in OHIOthresholds;
+% The duration of the complex is increased across runs and the number of tones is
+%   controlled by OHIOdurations, (for each 20 ms a further tone is added.
+% The frequency of the tones is changed on each trial
+
+% fetch thresholds and frequencies
+experiment=OHIOthresholds(experiment);
+
+stimulusParameters.WRVname='targetLevel';
+stimulusParameters.WRVstartValues=0 ;
+stimulusParameters.WRVsteps=[10 2];
+stimulusParameters.WRVlimits=[-30 110];
+
+betweenRuns.variableName1='numOHIOtones';
+betweenRuns.variableList1= [1 2 4 8 12];
+betweenRuns.variableName2='stimulusDelay';
+betweenRuns.variableList2=0.1;
+betweenRuns.randomizeSequence=2; % not random sequence
+
+stimulusParameters.targetType='OHIO';
+stimulusParameters.targetPhase='sin';
+stimulusParameters.targetFrequency=experiment.OHIOfrequencies;
+stimulusParameters.targetDuration=betweenRuns.variableList2;
+stimulusParameters.targetLevel=stimulusParameters.WRVstartValues(1);
+
+stimulusParameters.rampDuration=0.005;
+
+% instructions to user
+%   single interval up/down no cue
+stimulusParameters.instructions{1}= [{'YES if you hear the tone clearly'}, { }, { 'NO if not (or you are uncertain'}];
+%   single interval up/down with cue
+stimulusParameters.instructions{2}= [{'count the tones you hear clearly'}, { }, { 'ignore indistinct tones'}];
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/paradigms/reserve team/paradigm_OHIOspect.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,41 @@
+function paradigm_OHIOspect(handles)
+global stimulusParameters experiment betweenRuns
+
+paradigm_training(handles) % default
+
+% find the  threshold for a tonecomplex  consisting of a sequence of 10-ms tones
+%   whose frequencies are chosen at random from a list (OHIOfrequencies)
+% All tones are presented at the same level (SL) computed using absolute
+%   threshols specified in OHIOthresholds;
+% The duration of the complex is increased across runs and the number of tones is
+%   controlled by OHIOdurations, (for each 20 ms a further tone is added.
+% The frequency of the tones is changed on each trial
+
+% fetch thresholds and frequencies
+experiment=OHIOthresholds(experiment);
+
+stimulusParameters.WRVname='targetLevel';
+stimulusParameters.WRVstartValues=0 ;
+stimulusParameters.WRVsteps=[10 2];
+stimulusParameters.WRVlimits=[-30 110];
+
+betweenRuns.variableName1='numOHIOtones';
+betweenRuns.variableList1= [1 2 4 8 12];
+betweenRuns.variableName2='stimulusDelay';
+betweenRuns.variableList2=0.1;
+betweenRuns.randomizeSequence=2; % not random sequence
+
+stimulusParameters.targetType='OHIO';
+stimulusParameters.targetPhase='sin';
+stimulusParameters.targetFrequency=experiment.OHIOfrequencies;
+stimulusParameters.targetDuration=betweenRuns.variableList2;
+stimulusParameters.targetLevel=stimulusParameters.WRVstartValues(1);
+
+stimulusParameters.rampDuration=0.005;
+
+% instructions to user
+%   single interval up/down no cue
+stimulusParameters.instructions{1}= [{'YES if you hear the tone clearly'}, { }, { 'NO if not (or you are uncertain'}];
+%   single interval up/down with cue
+stimulusParameters.instructions{2}= [{'count the tones you hear clearly'}, { }, { 'ignore indistinct tones'}];
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/paradigms/reserve team/paradigm_OHIOspectemp.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,40 @@
+function paradigm_OHIOspectemp(handles)
+global stimulusParameters experiment betweenRuns
+
+paradigm_training(handles) % default
+
+% find the  threshold for a tonecomplex  consisting of a sequence of 10-ms tones
+%   whose frequencies are chosen at random from a list (OHIOfrequencies)
+% All tones are presented at the same level (SL) computed using absolute
+%   threshols specified in OHIOthresholds;
+% The duration of the complex is increased across runs and the number of tones is
+%   controlled by OHIOdurations, (for each 20 ms a further tone is added.
+% The frequency of the tones is changed on each trial
+
+% fetch thresholds and frequencies
+experiment=OHIOthresholds(experiment);
+
+stimulusParameters.WRVname='targetLevel';
+stimulusParameters.WRVstartValues=0 ;
+stimulusParameters.WRVsteps=[10 2];
+stimulusParameters.WRVlimits=[-30 110];
+
+betweenRuns.variableName1='numOHIOtones';
+betweenRuns.variableList1= [1 2 4 8 12];
+betweenRuns.variableName2='stimulusDelay';
+betweenRuns.variableList2=0.1;
+betweenRuns.randomizeSequence=2; % not random sequence
+
+stimulusParameters.targetType='OHIO';
+stimulusParameters.targetPhase='sin';
+stimulusParameters.targetFrequency=experiment.OHIOfrequencies;
+stimulusParameters.targetDuration=betweenRuns.variableList2;
+stimulusParameters.targetLevel=stimulusParameters.WRVstartValues(1);
+
+stimulusParameters.rampDuration=0.005;
+
+% instructions to user
+%   single interval up/down no cue
+stimulusParameters.instructions{1}= [{'YES if you hear the tone clearly'}, { }, { 'NO if not (or you are uncertain'}];
+%   single interval up/down with cue
+stimulusParameters.instructions{2}= [{'count the tones you hear clearly'}, { }, { 'ignore indistinct tones'}];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/paradigms/reserve team/paradigm_OHIOtemp.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,44 @@
+function paradigm_OHIOtemp(handles)
+global stimulusParameters experiment betweenRuns
+
+paradigm_training(handles) % default
+
+% find the  threshold for a tonecomplex  consisting of a sequence of 10-ms tones
+%   whose frequencies are chosen at random from a list (OHIOfrequencies)
+% All tones are presented at the same level (SL) computed using absolute
+%   threshols specified in OHIOthresholds;
+% The duration of the complex is increased across runs and the number of tones is
+%   controlled by OHIOdurations, (for each 20 ms a further tone is added.
+% The frequency of the tones is changed on each trial
+
+% fetch thresholds and frequencies
+experiment=OHIOthresholds(experiment);
+
+stimulusParameters.WRVname='targetLevel';
+stimulusParameters.WRVstartValues=0 ;
+stimulusParameters.WRVsteps=[10 2];
+stimulusParameters.WRVlimits=[-30 110];
+% target variable: slope=1, start going down.
+stimulusParameters.cueTestDifference=10;
+experiment.psyFunSlope= 1;
+withinRuns.direction='down';
+
+betweenRuns.variableName1='numOHIOtones';
+betweenRuns.variableList1= [1 2 4 8 12];
+betweenRuns.variableName2='stimulusDelay';
+betweenRuns.variableList2=0.1;
+betweenRuns.randomizeSequence=2; % not random sequence
+
+stimulusParameters.targetType='OHIO';
+stimulusParameters.targetPhase='sin';
+stimulusParameters.targetFrequency=experiment.OHIOfrequencies;
+stimulusParameters.targetDuration=betweenRuns.variableList2;
+stimulusParameters.targetLevel=stimulusParameters.WRVstartValues(1);
+
+stimulusParameters.rampDuration=0.005;
+
+% instructions to user
+%   single interval up/down no cue
+stimulusParameters.instructions{1}= [{'YES if you hear the tone clearly'}, { }, { 'NO if not (or you are uncertain'}];
+%   single interval up/down with cue
+stimulusParameters.instructions{2}= [{'count the tones you hear clearly'}, { }, { 'ignore indistinct tones'}];
Binary file multithreshold 1.46/paradigms/stimulus.wav has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/printReport.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,319 @@
+function printReport(fileName, printTracks)
+
+% End of run report (no args)
+% *or*
+% reprint previous report from file
+
+global experiment stimulusParameters betweenRuns withinRuns statsModel   audio
+global LevittControl expGUIhandles
+
+
+global inputStimulusParams OMEParams DRNLParams
+global IHC_VResp_VivoParams IHCpreSynapseParams  AN_IHCsynapseParams
+global MacGregorParams MacGregorMultiParams  filteredSACFParams
+global experiment % used by calls from multiThreshold only
+global IHC_cilia_RPParams
+
+
+printReportGuide.structures=1;
+printReportGuide.showPsychometric=0;
+printReportGuide.HorizontalTracks=1;
+
+if nargin==0
+    % print new report
+    printReportGuide.showTracks=experiment.printTracks;
+    printReportGuide.fileName=[];
+    if experiment.saveData
+        saveFileName=['savedData/' experiment.name '_' experiment.date '_' experiment.paradigm];
+    else
+        % overwrite existing file just in case
+        saveFileName=['savedData/mostRecentResults'];
+    end
+    experiment.minElapsed=etime(clock, betweenRuns.timeNow)/60;
+    save(saveFileName, 'experiment', 'stimulusParameters', 'betweenRuns', 'withinRuns', 'statsModel', 'expGUIhandles')
+    disp(['data saved as: ' saveFileName]);
+    
+else
+    % reprint request
+    printReportGuide.fileName=fileName;
+    load(printReportGuide.fileName)
+    saveFileName=printReportGuide.fileName;
+    if nargin>1
+        printReportGuide.showTracks=printTracks;
+    else
+        printReportGuide.showTracks=experiment.printTracks;
+    end
+end
+
+fprintf('******** multithreshold ')
+x=pwd; disp(['version ' x(end-3:end)])
+fprintf('\nName:\t%s ', experiment.name)
+fprintf('\nparadigm:\t%s ', experiment.paradigm)
+fprintf('\nEar:\t%s ', experiment.ear)
+method=experiment.threshEstMethod;
+if stimulusParameters.includeCue && ~strcmp(method(1:6),'2I2AFC')
+    method=[method '/ withCue'];
+end
+fprintf('\nmethod:\t%s ', method)
+fprintf('\ndate:\t%s ', experiment.date)
+
+fprintf('\n\n')
+
+if isempty(betweenRuns.thresholds)
+    disp('no thresholds found')
+end
+
+% prepare results as matrices ready to print
+[idx1, idx2, var1values, var2values]=...
+    sortVariables(betweenRuns.variableList1, betweenRuns.variableList2, betweenRuns.var1Sequence, betweenRuns.var2Sequence);
+
+% if strcmp(betweenRuns.variableName2, 'none')
+%     betweenRuns.variableName2=' ';
+% end
+header1=betweenRuns.variableName1;
+header2=betweenRuns.variableName2;
+header1 = strrep(header1, 'none', ' '); % none is not a useful header
+header2 = strrep(header2, 'none', ' '); % none is not a useful header
+headers=strvcat([header1 '/'], header2);
+
+disp('thresholds')
+msg=printTabTable(sortTablesForPrinting(idx1,idx2,var1values,var2values, betweenRuns.thresholds),  headers);
+addToMsg(msg,0)
+fprintf('\n')
+
+% sort tracks into the same order
+betweenRuns.levelTracks=betweenRuns.levelTracks(idx1);
+betweenRuns.responseTracks=betweenRuns.responseTracks(idx1);
+betweenRuns.bestThresholdTracks=betweenRuns.bestThresholdTracks(idx1);
+
+betweenRuns.levelTracks=betweenRuns.levelTracks(idx2);
+betweenRuns.responseTracks=betweenRuns.responseTracks(idx2);
+betweenRuns.bestThresholdTracks=betweenRuns.bestThresholdTracks(idx2);
+
+if printReportGuide.structures
+    maxNoArrayValues=30;
+    showStructureSummary(stimulusParameters, 'stimulusParameters', maxNoArrayValues)
+    showStructureSummary(experiment, 'experiment',maxNoArrayValues)
+    showStructureSummary(betweenRuns, 'betweenRuns',maxNoArrayValues)
+    showStructureSummary(withinRuns, 'withinRuns')
+    
+    switch experiment.threshEstMethod
+        case {'2I2AFC++', '2I2AFC+++'}
+            showStructureSummary(LevittControl, 'LevittControl', maxNoArrayValues)
+    end
+    
+    switch experiment.ear
+        case {'statsModelLogistic','statsModelRareEvent'}
+            showStructureSummary(statsModel, 'statsModel', maxNoArrayValues)
+    end
+end
+
+if printReportGuide.showTracks
+    % NB this procedure can only be used if all the tracks are present and
+    % of equal length
+    bigTable=[]; header=[];
+    disp(' '); disp('Leveltracks starting from 1 response before the first reversal')
+    for i=1:length(betweenRuns.levelTracks)
+        if printReportGuide.HorizontalTracks
+            printTabTable(betweenRuns.levelTracks{i});
+        end
+        header=strvcat(header, 'level');
+    end
+    
+    disp(' '); disp('Response tracks starting from 1 response before the first reversal')
+    for i=1:length(betweenRuns.responseTracks)
+        if printReportGuide.HorizontalTracks
+            printTabTable(betweenRuns.responseTracks{i});
+        end
+        header=strvcat(header, 'resp');
+    end
+    
+    disp(' '); disp('threshold tracks starting from the first reversal')
+    for i=1:length(betweenRuns.bestThresholdTracks)
+        if printReportGuide.HorizontalTracks
+        end
+        printTabTable(betweenRuns.bestThresholdTracks{i});
+        header=strvcat(header, 'mean');
+    end
+    
+    disp(' '); disp('threshold (mean) tracks starting from the first reversal')
+    for i=1:length(betweenRuns.bestThresholdTracks)
+        if printReportGuide.HorizontalTracks
+        end
+        printTabTable(betweenRuns.bestThresholdMeanTracks{i});
+        header=strvcat(header, 'mean');
+    end
+    disp(' '); disp('threshold tracks (median) starting from the first reversal')
+    for i=1:length(betweenRuns.bestThresholdMedianTracks)
+        if printReportGuide.HorizontalTracks
+        end
+        printTabTable(betweenRuns.bestThresholdTracks{i});
+        header=strvcat(header, 'mean');
+    end
+    
+end
+
+switch experiment.ear
+    case  {'MAPmodelMultiCh', 'MAPmodelSingleCh'}
+        % show all parameters but do not compute the model
+        nm=UTIL_paramsList(whos);
+        for i=1:length(nm)
+            try
+                eval(['UTIL_showStruct(' nm{i} ', ''' nm{i} ''')'])
+            catch
+            end
+        end
+end
+
+if experiment.saveData
+    fprintf('\n')
+    disp('To reprint this report with tracks use:')
+    disp([ 'printReport(''' saveFileName ''',1)'])
+end
+
+% print final summary (repeat of above)
+fprintf('\n')
+fprintf('\n')
+disp('thresholds')
+msg=printTabTable(sortTablesForPrinting(idx1,idx2,var1values,var2values, betweenRuns.thresholds),  headers);
+addToMsg(msg,0)
+fprintf('\n')
+
+if length(var1values)==1 && length(var2values)==1 && experiment.maxTrials>49
+    [psy, levelsBinVector, binFrequencies, nNo, nYes]= ...
+        psychometricFunction(withinRuns.levelsPhaseTwo,withinRuns.responsesPhaseTwo, experiment.psyBinWidth);
+    disp('Psychometric function')
+    fprintf(' level  \tfreq\tprob\n')
+    fprintf('%6.0f\t%6.2f\t%6.0f\n', [levelsBinVector; binFrequencies; psy])
+    fprintf('\n')
+    fprintf('k \t %6.2f\n',logistic.bestK)
+    fprintf('g  \t%7.5f\n',rareEvent.bestGain)
+    fprintf('\n')
+    
+end
+% resultsSoFar=[betweenRuns.var1Sequence(betweenRuns.runNumber)'...
+%     betweenRuns.var2Sequence(betweenRuns.runNumber)'...
+%     betweenRuns.thresholds(betweenRuns.runNumber)'    ];
+% fprintf('%10.3f \t%10.3f \t%10.1f  \n', resultsSoFar')
+
+% ------------------------------------------------------- sortTablesForPrinting
+function table= sortTablesForPrinting(idx1,idx2, var1values,var2values, x)
+% table converts a vector to a table
+% after sorting according to idx1 and idx2
+% the table is completed by adding row and column values
+x=x(idx1);
+x=x(idx2);
+xMatrix=reshape(x,length(var1values),length(var2values));
+
+table=[[-1000 var2values]; [var1values' xMatrix]];
+
+% ------------------------------------------------------- showStructureSummary
+function showStructureSummary(structure, name, maxNoArrayValues)
+% showStructureSummary prints out the values of a single structure
+% The header is the structure name and each row is a field
+% e.g. showStructureSummary(params,'params')
+% This not the same as 'UTIL_showstruct'
+
+
+if nargin<3
+    maxNoArrayValues=20;
+end
+
+fprintf('\n%s:', name)
+
+fields=fieldnames(eval('structure'));
+% for each field in the structure
+for i=1:length(fields)
+    y=eval([ 'structure.' fields{i}]);
+    if isstr(y),
+        % strings
+        fprintf('\n%s=\t''%s''',  fields{i},y)
+    elseif isnumeric(y)
+        % arrays
+        if length(y)>1
+            % vectors
+            [r c]=size(y);
+            if r>c, y=y'; end
+            
+            [r c]=size(y);
+            if r>1
+                %                 fprintf('\n%s.%s=\t%g x %g matrix',name, fields{i}, r, c)
+                fprintf('\n%s=\t%g x %g matrix',fields{i}, r, c)
+                
+            elseif c<maxNoArrayValues
+                %                     fprintf('\n%s=\t[%s]',  fields{i},num2str(y))
+                fprintf('\n%s=',  fields{i})
+                fprintf('\t%g',y)
+                
+            else
+                fprintf('\n%s=\t %g...   [%g element array]', fields{i}, y(1),c)
+            end
+        else
+            % single valued arrays
+            %             fprintf('\n%s.%s=\t%s;', name, fields{i},num2str(y))
+            fprintf('\n%s=\t%s', fields{i},num2str(y))
+        end
+    elseif iscell(y)
+        fprintf('\n%s=\t cell array', fields{i})
+        
+    elseif isstruct(y)
+        fprintf('\n%s=\t structure', fields{i})
+    end,
+    
+end,
+fprintf('\n')
+
+
+% ------------------------------------------------------- printTabTable
+function strings= printTabTable(M, headers)
+% printTabTable prints a matrix as a table with tabs
+%headers are optional
+%headers=strvcat('firstname', 'secondname')
+%  printTabTable([1 2; 3 4],strvcat('a1','a2'));
+stringCount=1; strings{stringCount}=[];
+
+if nargin>1
+    [r c]=size(headers);
+    for no=1:r
+        % print all headers in a row
+        fprintf('%s\t',headers(no,:))
+        strings{stringCount}=sprintf('%s\t',headers(no,:)); stringCount=stringCount+1;
+    end
+    fprintf('\n')
+end
+
+[r c]=size(M);
+
+for row=1:r
+    string=[];
+    for col=1:c
+        if row==1 & col==1 & M(1,1)==-1000
+            %   Print nothing (tab follows below)
+        else
+            fprintf('%s',num2str(M(row,col)))
+            string=[string ' ' sprintf('%s',num2str(M(row,col)))];
+        end
+        if col<c
+            fprintf('\t')
+            % 			strings{stringCount}=sprintf('\t'); stringCount=stringCount+1;
+        end
+    end % col
+    strings{stringCount}=string; stringCount=stringCount+1;
+    fprintf('\n')
+end % row
+
+% ------------------------------------------------------- sortVariables
+function [idx1, idx2, var1values, var2values]= ...
+    sortVariables(var1values, var2values, var1Sequence, var2Sequence)
+
+[x idx1]= sort(var1Sequence);
+var1Sequence= x;
+var2Sequence= var2Sequence(idx1);
+depVarName= 'th';
+
+[x idx2]=sort(var2Sequence);
+var2Sequence=x;
+var1Sequence=var1Sequence(idx2);
+
+var1values=sort(var1values);
+var2values=sort(var2values);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/psychoLogisticRareEvent.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,307 @@
+function psycho 
+
+% DATA from AbsThresholdCM, LS
+
+levelSequence=[16.0836	6.0836	11.0836	12.725	13.4995	11.6559	12.7168	13.9507	12.0632	11.3845	11.7754	12.8639	14.1061	14.5545	13.5589	13.4736	14.1554	13.5123	13.1537	11.5334	12.6921	11.4461	10.7112	11.9171	10.8412	12.0536	13.06	14.2345	13.8535	14.0575	14.0145	15.6385	13.7959	14.0397	12.2497	11.4383	12.7685	12.7317	11.6741	10.3955	9.0334	10.4787	11.1883	11.4687	12.0583	13.8982	13.0644	14.4722	14.0304	14.7569	13.8571	12.1521	14.0865	13.2258	11.6988	12.2186	12.2561	12.2711	13.0345	14.2948	13.7838	12.9155	12.6927	12.5757	13.4818	12.8397	14.1803	12.7524	12.3169	13.0973	14.9722	14.4422	15.8944	17.2728	16.8621	15.3074	13.7319	11.7716	12.1233	12.1576	13.0023	13.2442	12.1454	13.8298	13.3997	11.7799	12.3834	12.8387	14.3718	12.7063	14.4002	14.3674	14.7882	15.0271	13.5737	15.2095	14.1789	13.4982	14.3926	13.6277	15.0551	13.493	15.3368	16.9437	16.1645	15.9275	15.7577	14.2939	14.1069	13.6184	12.728	14.4283	15.6494	14.2216	15.8188	14.3906	12.7635	13.2973	11.9934	11.1053	12.2359	11.439	12.4735	12.5466	12.9186	13.6937	13.792	13.085	12.5016	13.8401	11.9688	13.0676	14.3708	13.4891	14.4394	15.8265	17.1478	15.2337	13.6512	12.7727	14.4818	13.7045	14.5207	13.8211	13.2874	14.9221	14.3822	14.3562	13.3132	13.5015	13.1372	14.4495	13.957	15.2124	16.6607	15.114	13.8978	12.6665	12.3469	13.3699	14.1991	15.2259	13.2326	11.9325	13.1954	12.2766	13.7996	15.5274	14.7623	13.21	12.5874	10.6431	12.2121	10.4043	11.9979	10.2153	10.7945	11.5215	12.7081	14.2288	14.4475	13.9777	13.8564	14.1923	15.393	14.5229	15.3377	13.9385	13.6328	14.2861	15.0021	15.5488	13.8067	13.0269	13.3644	13.6195	14.5834	15.6554	13.8914	13.3657	14.0566	12.9857	12.9343	14.0372	14.0156	15.6395	15.4225	14.6514	14.6498	13.6421	13.4263	13.227	14.0428	14.681	15.1661	13.5285	14.9074	13.5498	14.4265	14.0798	14.6391	12.8226	12.225	13.7883	12.7012	12.7932	13.5318	14.9207	14.064	12.9551	14.2066	14.3463	13.4565	13.9379	15.7189	14.3516	12.6425	12.8485	12.2879	13.1142	11.8093	12.0037	10.2154	11.8395	12.4643	13.0501	13.5452	13.2338	12.6246	13.292	11.5661	11.6015	13.2896	15.2506	15.5295	14.523	13.6199	13.083	12.1714	12.5977	14.2862	15.7924	14.0221	14.4042	16.0364	16.6967	14.7112	14.7594	13.9874	13.3428	13.5231	14.441	13.9983	13.6414	11.862	13.2632	13.1065	12.8701	12.2578	13.7517	14.3268	13.3849	13.9609	13.3239	14.6694	14.8172	13.654	13.8144	13.5015	14.34	14.0139	15.1029	13.3895	13.3701	13.4554	11.9646	12.2519	12.4145	13.1343	14.9372	13.2483
+];
+
+
+responseSequence=[1	0	0	0	1	0	0	1	1	0	0	0	0	1	1	0	1	1	1	0	1	1	0	1	0	0	0	1	0	1	0	1	0	1	1	0	1	1	1	1	0	0	0	0	0	1	0	1	0	1	1	0	1	1	0	0	0	0	0	1	1	1	1	0	1	0	1	1	0	0	1	0	0	1	1	1	1	0	0	0	0	1	0	1	1	0	0	0	1	0	1	0	0	1	0	1	1	0	1	0	1	0	0	1	1	1	1	1	1	1	0	0	1	0	1	1	0	1	1	0	1	0	0	0	0	0	1	1	0	1	0	0	1	0	0	0	1	1	1	0	1	0	1	1	0	1	1	1	0	1	0	1	0	0	1	1	1	1	0	0	0	1	1	0	1	0	0	1	1	1	1	0	1	0	1	0	0	0	0	0	1	1	0	0	1	0	1	1	0	0	0	1	1	0	0	0	0	1	1	0	1	1	0	1	0	1	1	1	1	1	1	0	0	0	1	0	1	0	1	0	1	1	0	1	0	0	0	1	1	0	0	1	0	0	1	1	0	1	0	1	0	1	0	0	0	0	1	1	0	1	0	0	0	0	1	1	1	1	0	0	0	1	0	0	0	1	0	1	1	0	0	1	1	1	0	1	1	1	0	0	1	0	1	0	0	1	0	1	0	1	0	1	1	0	1	0	0	0	0	1	1
+];
+
+
+duration=0.008;
+
+
+% levelSequence=[23.3987	13.3987	18.9769	25.9114	18.6243	16.4689	23.7829	20.4015	19.3156	25.1232	21.4541	24.353	22.1732	24.83	21.8257	19.3798	17.885	26.0332	23.3135	20.7889	20.1446	22.3504	25.7491	25.8517	23.2701	25.2773	24.8727	26.416	23.9425	21.4652	25.3512	18.3484	26.0988	23.2303	17.0335	26.7833	17.1426	21.1627	21.8802	24.8192	18.2626
+% ];    
+% responseSequence=[1	0	0	1	0	0	1	0	0	1	0	1	1	1	0	0	0	1	1	0	0	1	1	1	1	1	1	1	0	0	1	0	1	1	0	1	0	0	0	1	0
+% ];
+% duration=0.016;
+
+
+% levelSequence=[24.9709	14.9709	18.3185	20.893	19.1644	17.8633	12.8493	20.2354	19.4386	14.4227	14.3361	12.0587	18.6425	20.1803	18.1533	20.8734	19.0579	20.4904	18.3061	14.8561	16.6948	19.2928	17.8098	17.6181	21.7709	16.6804	15.2661	17.967	20.0085	20.7096	15.7485	20.0475	16.0825	11.8798	19.4383	13.838	18.3323	15.8729	12.066	15.4367	12.4179
+% ];   
+% responseSequence=[1	0	1	1	1	1	0	1	1	0	0	0	1	1	0	1	1	1	1	0	1	1	1	0	1	1	1	1	1	1	0	1	0	0	1	0	1	1	0	1	0
+% ];
+% duration=0.512;
+% 
+% 
+% levelSequence=[20.9248	10.9248	17.6621	16.5301	12.8652	8.4223	7.2398	13.566	14.5773	15.7202	13.4907	15.5048	10.9308	11.9566	13.3548	18.6419	15.8288	13.6961	12.8613	11.1181	10.7736	14.6912	11.3496	18.4924	16.9867	14.6383	17.4752	19.0135	14.7333	14.0739	14.637	11.7261	10.1013	17.7782	18.4642	14.1431	18.7764	19.312	10.9071	17.2639	17.9951
+% ];   
+% responseSequence=[1	0	1	1	1	0	0	1	0	0	0	1	0	0	0	1	0	1	0	0	0	0	0	1	1	1	1	1	1	0	0	0	0	1	0	1	1	1	0	1	1
+% ];
+% duration=0.256;
+
+
+functionType='logistic';
+functionType='rareEvent';
+
+[R C]=size(levelSequence);
+levelSequence=reshape(levelSequence',1,R*C);
+
+[R C]=size(responseSequence);
+responseSequence=reshape(responseSequence',1,R*C);
+
+figure(2),clf
+figure(3),clf
+figure(2), plot(levelSequence,responseSequence,'k.'),hold on
+set(gca,'ytick',[0 1])
+set(gca,'yticklabel',{'0'; '1'})
+ylim([-.5 1.5])
+figure(3), plot(levelSequence,responseSequence,'k.'),hold on
+
+figure(2), xlabel('dB SPL'), ylabel('p(yes)')
+figure(3), xlabel('dB SPL'), ylabel('p(yes)')
+
+set(gca,'ytick',[0 1])
+set(gca,'yticklabel',{'0'; '1'})
+ylim([-.5 1.5])
+binWidth=1;
+minBinCenter=-10;
+maxBinCenter=100;
+binCenters=minBinCenter:binWidth:maxBinCenter;
+noPointers=find(responseSequence==0);
+noLevels=levelSequence(noPointers);
+yesPointers=find(responseSequence==1);
+yesLevels=levelSequence(yesPointers);
+noHist=hist(noLevels,binCenters);
+yesHist=hist(yesLevels,binCenters);
+warning off MATLAB:divideByZero
+yesHist=hist(yesLevels,binCenters);
+proportions=yesHist./(yesHist+noHist);
+warning on MATLAB:divideByZero
+
+idx=find(noHist | yesHist);
+noHist=noHist(idx);
+yesHist=yesHist(idx);
+proportions=proportions(idx);
+binCenters=binCenters(idx);
+
+for i=1:length(noHist)
+    marker=10*(noHist(i)+yesHist(i))/max(noHist);
+    figure(2), plot(binCenters(i),proportions(i),'ko','markersize',marker), hold on
+    figure(3), plot(binCenters(i),proportions(i),'ko','markersize',marker), hold on
+end
+
+
+
+
+
+
+
+rareEventProfile= fitRareEvent2(levelSequence,responseSequence, duration)
+figure(2), hold on
+plot(rareEventProfile.predictionLevels, rareEventProfile.predictionsRE,'g')
+xlim([min(binCenters) max(binCenters)])
+figure(3), hold on
+plot(rareEventProfile.predictionLevels, rareEventProfile.predictionsRE,'g')
+xlim([20 35])
+
+
+
+[bestVmin, bestG, smallestEuclid]=...
+    rareEvent(levelSequence,responseSequence, duration);
+
+[bestThreshold, bestSlope, smallestEuclid]=...
+    logistic(levelSequence,responseSequence);
+
+% -------------------------------------------- rareEvent
+function [bestVmin, bestG, smallestEuclid]=...
+    rareEvent(levelSequence,responseSequence, duration)
+'rare event'
+gs=.01:.01:4;
+
+Vmins=1:10:5000;
+P=28*10.^(levelSequence/20);
+allSmallestEuclid=[ ];
+allBestGs=[];
+
+for Vmin=Vmins
+    Euclids=[];
+    x=[];y=[];
+    for G=gs;
+        predictions= 1-exp(-duration*(G*P-Vmin));
+        idx=find(predictions<0); predictions(idx)=0;
+        Euclid=mean((predictions - responseSequence).^2);
+        Euclids=[Euclids Euclid];
+    end
+    
+    [smallestEuclid idx]=min(Euclids);
+    % disp(num2str([idx smallestEuclid]))
+    allSmallestEuclid=[allSmallestEuclid smallestEuclid];
+    bestG=gs(idx);
+    allBestGs=[allBestGs bestG];
+    
+end
+[smallestEuclid idx2]=min(allSmallestEuclid)
+bestVmin=Vmins(idx2);
+bestG=allBestGs(idx2);
+% [bestVmin bestG smallestEuclid]
+
+% predictions= 1-exp(-duration*(bestG*P-Vmin));
+% errors=responseSequence-predictions;
+% rho=corr([errors;  levelSequence]');
+% disp(['correlation=' num2str(rho(1,2))])
+
+
+levels=[min(levelSequence):max(levelSequence)];
+P=28*10.^(levels/20);
+predictions= 1-exp(-duration*(bestG*P-bestVmin));
+idx=find(predictions<0); predictions(idx)=0;
+figure(2), plot(levels,predictions,'r'), hold off
+title(['g=' num2str(bestG) ':  Vmin=' num2str(bestVmin) ':  Euclid= ' num2str(smallestEuclid)])
+figure(4), plot(levels(1:end-1), diff(predictions))
+
+xlim([levels(1)-10 levels(end)+10])
+ylim([-0.5 1.5])
+pause(.1)
+
+% -------------------------------------------- logistic
+function [bestThreshold, bestSlope, smallestEuclid]=...
+    logistic(levelSequence,responseSequence)
+'logistic'
+candidateThresholds=-20:1:50;
+candidateSlopes=.01:.01:10;
+
+allSmallestEuclid=[ ];
+allThresholds=[];
+
+for thisSlope=candidateSlopes;
+    Euclids=[];
+    for thisThreshold=candidateThresholds;
+        predictions=1./(1+exp(-thisSlope.*(levelSequence-thisThreshold)));
+        Euclid=mean((predictions - responseSequence).^2);
+        Euclids=[Euclids Euclid];
+    end
+    [smallestEuclid idx]=min(Euclids);
+    % disp(num2str([idx smallestEuclid]))
+    allSmallestEuclid=[allSmallestEuclid smallestEuclid];
+    bestThreshold=candidateThresholds(idx);
+    allThresholds=[allThresholds bestThreshold];
+end
+[smallestEuclid idx2]=min(allSmallestEuclid)
+bestSlope=candidateSlopes(idx2);
+bestThreshold=allThresholds(idx2);
+% [bestThreshold bestSlope smallestEuclid]
+
+% predictions= 1-exp(-duration*(bestG*P-Vmin));
+% errors=responseSequence-predictions;
+% rho=corr([errors;  levelSequence]');
+% disp(['correlation=' num2str(rho(1,2))])
+
+
+levels=[min(levelSequence):max(levelSequence)];
+bestLogistic=1./(1+exp(-bestSlope*(levels-bestThreshold)));
+figure(3), plot(levels,bestLogistic,'r'), hold off
+title(['k=' num2str(bestSlope) ':  threshold=' num2str(bestThreshold) ':  Euclid= ' num2str(smallestEuclid)])
+% figure(2), hold on, plot(levels,bestLogistic,'g'), hold off
+figure(4), hold on, plot(levels(1:end-1), diff(bestLogistic), 'r')
+
+
+xlim([levels(1)-10 levels(end)+10])
+ylim([-0.5 1.5])
+
+
+
+% --------------------------------------------------- fitRareEvent
+function rareEvent=fitRareEvent2(stimulusLevels, responses, duration, gains, Vmins)
+% least squares estimate of *rare event* function
+% p(event)=gain*levelmPa -Vmin
+% 'responses' is a binary vector of subject's decision.
+% 'stimulusLevels' are the corresponding signal levesl (values)
+% duration is required to compute the expectation of an event occurring
+% gains is an optional list of gains to be tried
+% Vmins is an optional list of Vmins to be tried
+
+global experiment
+if nargin<5
+    minVmin=1; maxVmin=100000; nVmins=30;
+    Vmins=[0 logspace(log10(minVmin),log10(maxVmin),nVmins)];
+    % disp(Vmins)
+    nGains=10;
+    dGain=1/nGains;
+    gains=dGain:dGain:20;
+end
+
+nVmins=length(Vmins);
+nGains=length(gains);
+
+rareEvent.bestGain=NaN;
+rareEvent.bestVMin=NaN;
+rareEvent.thresholddB=0;
+rareEvent.bestPaMindB=NaN;
+rareEvent.predictionLevels=[];
+rareEvent.predictionsRE=[];
+rareEvent.Euclid=NaN;
+
+if isempty(stimulusLevels), return, end
+
+% expected slope is negative, rareEvent can not be used
+% if experiment.psyFunSlope<0
+%     return
+% end
+
+% NB calculations in microPascals!
+stimulusLevelsAsPressure=28 * 10.^(stimulusLevels/20);
+
+allGains=reshape(repmat(gains,nVmins,1), 1, nVmins*nGains);
+allVmins=repmat(Vmins, 1, nGains);
+
+for repeat=1:2
+    predictions=NaN(1,length(stimulusLevels));
+    gainCount=0; VminCount=0;
+    Euclid=inf; bestVmin=0; bestGain=0;
+    for gain= gains
+        gainCount=gainCount+1;
+        VminCount=0;
+        for Vmin=Vmins
+            VminCount=VminCount+1;
+            % all levels are simultaneously assessed
+            gP_Vmin=gain*stimulusLevelsAsPressure-Vmin;
+            idx=(gP_Vmin>0);
+            predictions(idx)= 1-exp(-duration*(gP_Vmin(idx)));
+            predictions(~idx)=0;
+
+            error=(predictions - responses).^2;
+            error=mean(error(~isnan(error)));
+            if error<Euclid
+                Euclid=error;
+                bestVmin=Vmin;
+                bestVminCount=VminCount;
+                bestGainCount=gainCount;
+                bestGain=gain;
+            end
+        end
+    end
+    if repeat==1
+        if bestVminCount>1 & bestVminCount<nVmins
+            minVmin=Vmins(bestVminCount-1); maxVmin=Vmins(bestVminCount+1); nVmins=30;
+            Vmins=[0 logspace(log10(minVmin),log10(maxVmin),nVmins)];
+        elseif bestVminCount==1
+            Vmins=0:Vmins(2)/30:Vmins(2);
+        else
+            disp('rareEvent: Vmin estimate may be out of range')
+        end
+    end
+    % disp(Vmins)
+end
+
+if bestGainCount==1 | bestGainCount==nGains
+    disp('gain estimate may be out of range')
+end
+
+
+[rareEvent.Euclid idx]=min(Euclid);
+rareEvent.bestGain=bestGain;
+rareEvent.bestVMin=round(bestVmin);
+rareEvent.thresholdPa=(-log(0.5)/duration + rareEvent.bestVMin)/rareEvent.bestGain;
+rareEvent.thresholddB=20*log10(rareEvent.thresholdPa/28);
+rareEvent.bestPaMindB=20*log10((rareEvent.bestVMin/rareEvent.bestGain)/28);
+
+predictionLevels= -50:1:120;
+rareEvent.predictionLevels=predictionLevels;
+rareEvent.predictionsRE=...
+    1-exp(-duration*(rareEvent.bestGain*28 * 10.^(predictionLevels/20)-rareEvent.bestVMin));
+rareEvent.predictionsRE(rareEvent.predictionsRE<0)=0;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/psychometricFunction.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,49 @@
+% ------------------------------------------------------- psychometricFunction
+function [psy, levelsBinVector, binFrequencies, nNo, nYes]=...
+    psychometricFunction(levels, responses, psyBinWidth)
+% computes a psychometric function from rwo vectors (levels and responses)
+% responses is a binary vectory (1=yes)
+% psyBinWidth is the bin width (dB) of the output psychometric function
+% this function is called by both fitPsychometricFunction and subjGUI
+% for this reason it should notbe bundled with fitPsychometricFunction
+
+binFrequencies=[]; nNo=[]; nYes=[];
+if min(levels)+abs(psyBinWidth) < max(levels)
+    % create a set of bins for the psychometric function
+    levelsBinVector= min(levels): abs(psyBinWidth): max(levels);
+else
+    psy=[]; levelsBinVector=[];
+    return
+end
+
+idx0=find(responses==0);	% isolate 'no'
+z=levels(idx0);
+nNo=hist(z, levelsBinVector);
+
+idx1=find(responses>0);	% isolate 'yes'
+y=levels(idx1);
+nYes=hist(y, levelsBinVector);
+
+if sum(nNo)==0 | sum(nYes)==0
+        psy=[]; levelsBinVector=[];
+    return             % yesses and nos required for a function
+end
+
+binFrequencies=nNo+nYes;
+
+warning off MATLAB:divideByZero
+psy=nYes./binFrequencies;        % psy is the proportion of 'yes' responses
+warning on MATLAB:divideByZero
+lastwarn('');
+
+idx=~isnan(psy);	%remove empty bins
+idx=(nYes>0) |(nNo>0);	%remove empty bins
+psy=psy(idx);
+levelsBinVector=levelsBinVector(idx);
+binFrequencies=binFrequencies(idx);
+nNo=nNo(idx);
+nYes=nYes(idx);
+
+% [nNo' nYes']
+% [levelsBinVector' psy']
+% plot(levelsBinVector,psy,['o'])
\ No newline at end of file
Binary file multithreshold 1.46/savedData/mostRecentResults.mat has changed
Binary file multithreshold 1.46/speech.wav has changed
Binary file multithreshold 1.46/stimulus.wav has changed
Binary file multithreshold 1.46/subjGUI_MT.fig has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/subjGUI_MT.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,1741 @@
+function varargout = subjGUI_MT(varargin)
+
+% Begin initialization code - DO NOT EDIT
+gui_Singleton = 1;
+gui_State = struct('gui_Name',       mfilename, ...
+    'gui_Singleton',  gui_Singleton, ...
+    'gui_OpeningFcn', @subjGUI_MT_OpeningFcn, ...
+    'gui_OutputFcn',  @subjGUI_MT_OutputFcn, ...
+    'gui_LayoutFcn',  [] , ...
+    'gui_Callback',   []);
+if nargin && isstr(varargin{1})
+    gui_State.gui_Callback = str2func(varargin{1});
+end
+
+if nargout
+    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
+else
+    gui_mainfcn(gui_State, varargin{:});
+end
+% End initialization code - DO NOT EDIT
+
+% --- Executes just before subjGUI_MT is made visible.
+function subjGUI_MT_OpeningFcn(hObject, eventdata, handles, varargin)
+
+% Choose default command line output for subjGUI_MT
+handles.output = hObject;
+initializeGUI(handles)
+guidata(hObject, handles);
+
+function varargout = subjGUI_MT_OutputFcn(hObject, eventdata, handles)
+% Get default command line output from handles structure
+varargout{1} = handles.output;
+
+% -----------------------------------------------------initializeGUI
+function initializeGUI(handles)
+global experiment
+global subjectGUIHandles expGUIhandles
+        addpath (['..' filesep 'MAP'], ['..' filesep 'utilities'], ...
+    ['..' filesep 'parameterStore'],  ['..' filesep 'wavFileStore'],...
+    ['..' filesep 'testPrograms'])
+
+dbstop if error
+
+% subjectGUI size and location         % [left bottom width height]
+scrnsize=get(0,'screensize');
+set(0, 'units','pixels')
+switch experiment.ear
+    % use default size unless...
+    case {'MAPmodel',  'MAPmodelMultich', 'MAPmodelSingleCh', ...
+            'statsModelLogistic','statsModelRareEvent'}
+        % 	subjectGUI not needed for modelling so minimize subject GUI
+        set(gcf, 'units','pixels')
+        y=[0*scrnsize(3) 0.8*scrnsize(4) 0.1*scrnsize(3) 0.2*scrnsize(4)];
+        set(gcf,'position',y, 'color',[.871 .961 .996])
+        
+
+        
+    case 'MAPmodelListen',
+        % 	subjectGUI is needed for display purposes. Make it large
+        set(gcf, 'units','pixels')
+        y=[.665*scrnsize(3) 0.02*scrnsize(4) ...
+            0.33*scrnsize(3) 0.5*scrnsize(4)]; % alongside
+        set(gcf,'position',y, 'color',[.871 .961 .996])
+end
+
+switch experiment.ear
+    case{'left', 'right','diotic', 'dichoticLeft','dichoticRight'}
+        % Look to see if the button box exists and, if so, initialise it
+        buttonBoxIntitialize		% harmless if no button box attached
+end
+
+% function varargout = subjGUI_MT(varargin)
+% 
+% % Begin initialization code - DO NOT EDIT
+% gui_Singleton = 1;
+% gui_State = struct('gui_Name',       mfilename, ...
+%     'gui_Singleton',  gui_Singleton, ...
+%     'gui_OpeningFcn', @subjGUI_MT_OpeningFcn, ...
+%     'gui_OutputFcn',  @subjGUI_MT_OutputFcn, ...
+%     'gui_LayoutFcn',  [] , ...
+%     'gui_Callback',   []);
+% if nargin && isstr(varargin{1})
+%     gui_State.gui_Callback = str2func(varargin{1});
+% end
+% 
+% if nargout
+%     [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
+% else
+%     gui_mainfcn(gui_State, varargin{:});
+% end
+% % End initialization code - DO NOT EDIT
+% 
+% % --- Executes just before subjGUI_MT is made visible.
+% function subjGUI_MT_OpeningFcn(hObject, eventdata, handles, varargin)
+% 
+% % Choose default command line output for subjGUI_MT
+% handles.output = hObject;
+% initializeGUI(handles)
+% guidata(hObject, handles);
+% 
+% function varargout = subjGUI_MT_OutputFcn(hObject, eventdata, handles)
+% % Get default command line output from handles structure
+% varargout{1} = handles.output;
+% 
+% % -----------------------------------------------------initializeGUI
+% function initializeGUI(handles)
+% global experiment
+% global subjectGUIHandles expGUIhandles
+% 
+% dbstop if error
+% 
+% % subjectGUI size and location         % [left bottom width height]
+% scrnsize=get(0,'screensize');
+% set(0, 'units','pixels')
+% switch experiment.ear
+%     % use default size unless...
+%     case {'MAPmodel',  'MAPmodelMultiCh','MAPmodelSingleCh',  ...
+%             'statsModelLogistic','statsModelRareEvent'}
+%         % 	subjectGUI not needed for modelling so minimize subject GUI
+%         set(gcf, 'units','pixels')
+%         y=[0*scrnsize(3) 0.8*scrnsize(4) 0.1*scrnsize(3) 0.2*scrnsize(4)];
+%         set(gcf,'position',y, 'color',[.871 .961 .996])
+%         
+%     case 'MAPmodelListen',
+%         % 	subjectGUI is needed for display purposes. Make it large
+%         set(gcf, 'units','pixels')
+%         y=[.665*scrnsize(3) 0.02*scrnsize(4) ...
+%             0.33*scrnsize(3) 0.5*scrnsize(4)]; % alongside
+%         set(gcf,'position',y, 'color',[.871 .961 .996])
+% end
+% 
+% switch experiment.ear
+%     case{'left', 'right','diotic', 'dichoticLeft','dichoticRight'}
+%         % Look to see if the button box exists and, if so, initialise it
+%         buttonBoxIntitialize		% harmless if no button box attached
+% end
+
+% clear display of previous mean values. This is a new measurement series
+axes(expGUIhandles.axes4), cla           
+reset (expGUIhandles.axes4)
+
+% handles needed in non-callback routines below
+subjectGUIHandles=handles;
+
+% start immediately
+startNewExperiment(handles, expGUIhandles)
+% This is the end of the experiment. Exit here and return to ExpGUI.
+
+% ----------------------------------------------------- startNewExperiment
+function startNewExperiment(handles, expGUIhandles)
+% An experiment consists of a series of 'runs'.
+% Resets all relevant variables at the beginning of a new experiment.
+global experiment stimulusParameters betweenRuns
+
+% 'start new experiment' button is the only valid action now
+experiment.status='waitingForStart';
+
+switch experiment.threshEstMethod
+    % add appropriate labels to subject GUI buttons
+    case {'2I2AFC++', '2I2AFC+++'}
+        set(handles.pushbutton3,'string','')
+        set(handles.pushbutton2,'string','2')
+        set(handles.pushbutton1,'string','1')
+        set(handles.pushbutton0,'string','0')
+    case {'MaxLikelihood', 'oneIntervalUpDown'}
+        if stimulusParameters.includeCue
+            set(handles.pushbutton3,'string','')
+            set(handles.pushbutton2,'string','2')
+            set(handles.pushbutton1,'string','1')
+            set(handles.pushbutton0,'string','0')
+        else
+            set(handles.pushbutton3,'string','')
+            set(handles.pushbutton2,'string','YES')
+            set(handles.pushbutton1,'string','NO')
+            set(handles.pushbutton0,'string','')
+        end
+end
+
+switch experiment.paradigm
+    case 'discomfort'
+        set(handles.pushbutton3,'string','')
+        set(handles.pushbutton2,'string','uncomfortable')
+        set(handles.pushbutton1,'string','loud')
+        set(handles.pushbutton0,'string','comfortable')
+            experiment.allowCatchTrials=0;
+end
+
+% experiment.subjGUIfontSize is set on expGUI
+set(handles.pushbutton3,'FontSize',experiment.subjGUIfontSize)
+set(handles.pushbutton2,'FontSize',experiment.subjGUIfontSize)
+set(handles.pushbutton1,'FontSize',experiment.subjGUIfontSize)
+set(handles.pushbutton0,'FontSize',experiment.subjGUIfontSize)
+set(handles.pushbuttoNotSure,'FontSize',experiment.subjGUIfontSize)
+set(handles.pushbuttonGO,'FontSize',experiment.subjGUIfontSize)
+set(handles.textMSG,'FontSize',experiment.subjGUIfontSize)
+
+set(handles.pushbutton19,'visible','off') % unused button
+
+% start command window summary of progress
+fprintf(' \n ----------- NEW MEASUREMENTS\n')
+disp(['paradigm:   ' experiment.paradigm])
+cla(expGUIhandles.axes1)
+cla(expGUIhandles.axes2)
+cla(expGUIhandles.axes4)
+cla(expGUIhandles.axes5)
+
+experiment.stop=0;              % status of 'stop' button
+experiment.pleaseRepeat=0;      % status of 'repeat' button
+experiment.buttonBoxStatus='not busy';
+
+% date and time and replace ':' with '_'
+date=datestr(now);idx=findstr(':',date);date(idx)='_'; 
+experiment.date=date;
+timeNow=clock; betweenRuns.timeNow= timeNow;
+experiment.timeAtStart=[num2str(timeNow(4)) ':' num2str(timeNow(5))];
+experiment.minElapsed=0; 
+
+% unpack catch trial rates. The rate declines from the start rate 
+%  to the base rate using a time constant.
+stimulusParameters.catchTrialRate=stimulusParameters.catchTrialRates(1);
+stimulusParameters.catchTrialBaseRate=...
+    stimulusParameters.catchTrialRates(2);
+stimulusParameters.catchTrialTimeConstant=...
+    stimulusParameters.catchTrialRates(3);
+if stimulusParameters.catchTrialBaseRate==0
+    stimulusParameters.catchTrialRate=0;
+end
+
+% for human measurements only, identify the start catch trial rate
+switch experiment.ear
+    case{'left', 'right','diotic', 'dichoticLeft','dichoticRight'}
+        fprintf('stimulusParameters.catchTrialRate= %6.3f\n', ...
+            stimulusParameters.catchTrialRate)
+end
+
+% Reset betweenRuns parameters. this occurs only at experiment start
+% withinRuns values are reset in 'startNewRun'
+% this approach creates a more readable structure summary printout.
+betweenRuns.thresholds=[];
+betweenRuns.thresholds_mean=[];
+betweenRuns.thresholds_median=[];
+betweenRuns.forceThresholds=[];
+betweenRuns.observationCount=[];
+betweenRuns.catchTrials=[];
+betweenRuns.timesOfFirstReversals=[];
+betweenRuns.bestThresholdTracks=[];
+betweenRuns.bestThresholdMeanTracks=[];
+betweenRuns.bestThresholdMedianTracks=[];
+betweenRuns.levelTracks=[];
+betweenRuns.responseTracks=[];
+betweenRuns.slopeKTracks=[];
+betweenRuns.gainTracks=[];
+betweenRuns.VminTracks=[];
+betweenRuns.bestGain=[];
+betweenRuns.bestVMin=[];
+betweenRuns.bestPaMin=[];
+betweenRuns.bestLogisticM=[];
+betweenRuns.bestLogisticK=[];
+betweenRuns.resets=0;
+betweenRuns.runNumber=0;
+
+% Up to two parameters can be changed between runs
+% Find the variable parameters and randomize them
+% e.g. 'variableList1 = stimulusParameters.targetFrequency;'
+eval(['variableList1=stimulusParameters.' betweenRuns.variableName1 ';']);
+eval(['variableList2=stimulusParameters.' betweenRuns.variableName2 ';']);
+nVar1=length(variableList1);
+nVar2=length(variableList2);
+
+% Create two sequence vectors to represent the sequence of var1 and var2 
+% values. 'var1' changes most rapidly.
+switch betweenRuns.randomizeSequence
+    case 'fixed sequence'
+        var1Sequence=repmat(betweenRuns.variableList1, 1,nVar2);
+        var2Sequence=reshape(repmat(betweenRuns.variableList2, ...
+            nVar1,1),1,nVar1*nVar2);
+    case 'randomize within blocks'
+        % the blocks are not randomized
+        var1Sequence=betweenRuns.variableList1;
+        ranNums=rand(1, length(var1Sequence)); [x idx]=sort(ranNums);
+        var1Sequence=var1Sequence(idx);
+        betweenRuns.variableList1=variableList1(idx);
+        var1Sequence=repmat(var1Sequence, 1,nVar2);
+        var2Sequence=reshape(repmat(betweenRuns.variableList2, nVar1,1)...
+            ,1,nVar1*nVar2);
+    case 'randomize across blocks'
+        var1Sequence=repmat(betweenRuns.variableList1, 1,nVar2);
+        var2Sequence=reshape(repmat(betweenRuns.variableList2, nVar1,1),...
+            1,nVar1*nVar2);
+        ranNums=rand(1, nVar1*nVar2);
+        [x idx]=sort(ranNums);
+        var1Sequence=var1Sequence(idx);
+        var2Sequence=var2Sequence(idx);
+        % there should be one start value for every combination 
+        %  of var1/ var2. In principle this allows these values to be 
+        % programmed. Not currently in use.
+        stimulusParameters.WRVstartValues=...
+            stimulusParameters.WRVstartValues(idx);
+end
+betweenRuns.var1Sequence=var1Sequence;
+betweenRuns.var2Sequence=var2Sequence;
+
+% caught out vector needs to be linked to the length of the whole sequence
+betweenRuns.caughtOut=zeros(1,length(var1Sequence));
+
+disp('planned sequence:')
+if min(var1Sequence)>1
+    % use decidaml places only if necessary
+disp([betweenRuns.variableName1 ': ' num2str(var1Sequence,'%6.0f')  ])
+else
+disp([betweenRuns.variableName1 ': ' num2str(var1Sequence,'%8.3f')  ])
+end
+if min(var1Sequence)>1
+disp([betweenRuns.variableName2 ': ' num2str(var2Sequence,'%6.0f') ])
+else
+disp([betweenRuns.variableName2 ': ' num2str(var2Sequence,'%8.3f') ])
+end
+
+fprintf('\nvariable1 \t  variable2\t  \n')
+fprintf('%s \t  %s\t  Threshold  \n',betweenRuns.variableName1,...
+    betweenRuns.variableName2)
+
+% Light up 'GO' on subjGUI and advise.
+set(handles.editdigitInput,'visible','off')
+switch experiment.ear
+    case {'statsModelLogistic', 'statsModelRareEvent',...
+            'MAPmodel',  'MAPmodelMultiCh','MAPmodelSingleCh'}
+        % no changes required if model used
+    otherwise
+        set(handles.pushbuttonGO,'backgroundcolor','y')
+        set(handles.pushbuttonGO,'visible','on')
+        set(handles.frame1,'visible','off')
+        set(handles.textMSG,'backgroundcolor', 'w')
+        msg=[{'Ready to start new Experiment'}, {' '}, {'Please, click on the GO button'}];
+        set(handles.textMSG,'string', msg)
+        
+        set(handles.pushbuttoNotSure,'visible','off')
+        set(handles.pushbuttonWrongButton,'visible','off')
+        set(handles.pushbutton3,'visible','off')
+        set(handles.pushbutton2,'visible','off')
+        set(handles.pushbutton1,'visible','off')
+        set(handles.pushbutton0,'visible','off')
+        pause(.1) % to allow display to be drawn
+end
+
+% Selecting the 'GO' button is the only valid operation action now
+experiment.status='waitingForGO'; 	% i.e. waiting for new run
+
+% control is now either manual, model (MAP) or randomization
+switch experiment.ear
+    case {'MAPmodel','MAPmodelMultiCh','MAPmodelSingleCh','MAPmodelListen'}                                     % MAP model is now the subject
+        stimulusParameters.calibrationdB=0;             % Pascals required!
+        MAPmodelRunsGUI(handles)
+        % model is now the subject
+    case  {'statsModelLogistic', 'statsModelRareEvent'}	
+        % no catch trials for the statistical model
+        stimulusParameters.catchTrialBaseRate=0;		
+        stimulusParameters.catchTrialRate=0;
+        statsModelRunsGUI(handles)
+    otherwise
+        %manual operation; wait for user to click on 'GO'
+end
+
+% Experiment complete (after MAP or randomization)
+% return to  'initializeGUI' and then back to expGUI
+% Manual control finds its own way home. Program control assumed when
+% the user hits the GO button
+
+% -----------------------------------------------------------------   startNewRun
+function startNewRun(handles)
+% There are many ways to arrive here.
+%  Under manual control this is achieved by hitting the GO button
+%   either via the button box or a mouse click
+%  MAP and randomization methods call this too
+
+global experiment stimulusParameters betweenRuns withinRuns expGUIhandles
+global LevittControl rareEvent
+
+figure(handles.figure1) % guarantee subject GUI visibility
+
+% ignore call if program is not ready
+if ~strcmp(experiment.status,'waitingForGO'), return, end
+
+set(handles.pushbuttonGO,'visible','off')
+
+% append message to expGUI message box to alert experimenter that the user
+% is active
+addToMsg('Starting new trial',0)
+
+cla(expGUIhandles.axes1),  title(''); % stimulus
+cla(expGUIhandles.axes2),  title(''); % WRV track
+drawnow
+
+betweenRuns.runNumber=betweenRuns.runNumber + 1;
+
+withinRuns.trialNumber=1;
+withinRuns.variableValue=...
+    stimulusParameters.WRVstartValues(betweenRuns.runNumber);
+% add random jitter to start level
+if ~experiment.singleShot
+    % SS or single shot allows the user to precisely set the WRV
+    withinRuns.variableValue=withinRuns.variableValue +...
+        (rand-0.5)*stimulusParameters.jitterStartdB;
+end
+
+withinRuns.peaks=[];
+withinRuns.troughs=[];
+withinRuns.levelList=[];
+withinRuns.meanEstTrack=[];
+withinRuns.bestSlopeK=[];
+withinRuns.bestGain=[];
+withinRuns.bestVMin=[];
+withinRuns.forceThreshold=NaN;
+withinRuns.responseList=[];
+withinRuns.caughtOut=0;
+withinRuns.wrongButton=0;
+withinRuns.catchTrialCount=0;
+withinRuns.thresholdEstimateTrack=[];
+
+withinRuns.beginningOfPhase2=0;
+withinRuns.nowInPhase2=0;
+withinRuns.thisIsRepeatTrial=0;
+
+rareEvent.Euclid=NaN;
+rareEvent.bestGain=NaN;
+rareEvent.bestVMin=NaN;
+rareEvent.thresholddB=0;
+rareEvent.bestPaMindB=NaN;
+rareEvent.predictionLevels=[];
+rareEvent.predictionsRE=[];
+
+LevittControl.sequence=[];
+
+% on-screen count of number of runs still to complete
+trialsToGo=length(betweenRuns.var1Sequence)-betweenRuns.runNumber;
+set(handles.toGoCounter,'string', trialsToGo);
+
+switch experiment.threshEstMethod
+    case {'2I2AFC++', '2I2AFC+++'}
+        % For 2I2AFC the buttons need to be on the screen ab initio
+        Levitt2      % inititalize Levitt2 procedure
+end
+
+switch experiment.ear
+    case{'left', 'right','diotic', 'dichoticLeft','dichoticRight'}
+        % allow subject time to recover from 'go' press
+        pause(experiment.clickToStimulusPause)
+end
+
+errormsg=nextStimulus(handles);				% get the show on the road
+
+% switch experiment.paradigm
+%     case 'SRT'
+%         set(handles.editdigitInput,'visible','on')
+%         uicontrol(handles.editdigitInput)
+% end
+
+% terminate if there is any kind of problem
+if ~isempty(errormsg)
+    % e.g. limits exceeded, clipping
+    disp(errormsg)
+    runCompleted(handles)
+    return
+end
+
+% return route is variable (see intro to this function)
+
+% -----------------------------------------------------buttonBox_callback
+function buttonBox_callback(obj, info)
+global experiment
+global serobj
+global subjectGUIHandles
+
+% do not accept callback if one is already in process
+if strcmp(experiment.buttonBoxStatus,'busy')
+    disp(' ignored button press')
+    return
+end
+experiment.buttonBoxStatus='busy';
+% fclose(serobj)
+
+% identify the code of the button pressed
+buttonPressedNo = fscanf(serobj,'%c',1);
+
+% This is the map from the button to the Cedrus codes
+switch experiment.buttonBoxType
+    case 'horizontal'
+        pbGo='7'; 		pb0='1';		
+        pb1='2';		pb2='3';		
+        pbRepeat='4';	pbWrong='6';	pbBlank='5';
+    case 'square'
+        pbGo='7';		pb0='1';		
+        pb1='3';		pb2='4';		
+        pbRepeat='8';	pbWrong='6';	pbBlank='5';
+end
+
+% decide what to do
+switch experiment.status
+    case {'presentingStimulus', 'waitingForStart', 'trialcompleted', ...
+            'endOfExperiment'}
+        disp(' ignored button press')
+        
+    case 'waitingForGO'
+        % i.e. waiting for new run
+        if strcmp(buttonPressedNo,pbGo)			% only GO button  accepted
+            startNewRun(subjectGUIHandles)
+        else
+            disp(' ignored button press')
+        end
+        
+    case 'waitingForResponse'
+        % response to stimuli
+        switch buttonPressedNo
+            case pb0						% button 0 (top left)
+                switch experiment.threshEstMethod
+                    case {'2I2AFC++', '2I2AFC+++'}
+                        disp(' ignored button press')
+                    otherwise
+                        set(subjectGUIHandles.pushbutton0,...
+                            'backgroundcolor','r')
+                        pause(.1)
+                        set(subjectGUIHandles.pushbutton0,...
+                            'backgroundcolor',get(0,...
+                            'defaultUicontrolBackgroundColor'))
+                        userSelects0or1(subjectGUIHandles)
+                end
+                
+            case pb1						% button 1 (bottom left)
+                switch experiment.threshEstMethod
+                    case {'2I2AFC++', '2I2AFC+++'}
+                        userSelects0or1(subjectGUIHandles)   
+                    otherwise
+                        set(subjectGUIHandles.pushbutton1,...
+                            'backgroundcolor','r')
+                        pause(.1)
+                        set(subjectGUIHandles.pushbutton1,...
+                            'backgroundcolor',get(0,...
+                            'defaultUicontrolBackgroundColor'))
+                        userSelects0or1(subjectGUIHandles)
+                end
+                
+            case pb2						% button 2 (bottom right)
+                switch experiment.threshEstMethod
+                    case {'2I2AFC++', '2I2AFC+++'}
+                        userSelects2 (subjectGUIHandles)
+                    otherwise
+                        set(subjectGUIHandles.pushbutton2,...
+                            'backgroundcolor','r')
+                        pause(.1)
+                        set(subjectGUIHandles.pushbutton2,...
+                            'backgroundcolor',get(0,...
+                            'defaultUicontrolBackgroundColor'))
+                        userSelects2 (subjectGUIHandles)
+                end
+                
+            case pbRepeat                   % extreme right button
+                switch experiment.threshEstMethod
+                    case {'2I2AFC++', '2I2AFC+++'}
+                        disp(' ignored button press')
+                    otherwise
+                        
+                        set(subjectGUIHandles.pushbuttoNotSure,...
+                            'backgroundcolor','r')
+                        pause(.1)
+                        set(subjectGUIHandles.pushbuttoNotSure,...
+                            'backgroundcolor',get(0,...
+                            'defaultUicontrolBackgroundColor'))
+                        userSelectsPleaseRepeat (subjectGUIHandles)
+                end
+                
+            case {pbWrong, pbBlank}
+                disp(' ignored button press')
+                
+            otherwise						% unrecognised button
+                disp('ignored button press')
+        end									% end (button press number)
+    otherwise
+        disp('ignored button press')
+end											% experiment status
+
+% All processing returns through here. 
+% 	fopen(serobj);		% flushes the input buffer
+
+% buttonPressedNo = fscanf(serobj,'%c',1);
+
+% button box remains 'busy' until after the stimulus has been presented
+experiment.buttonBoxStatus='not busy';
+
+% -------------------------------------------------- pushbuttonGO_Callback
+function pushbuttonGO_Callback(hObject, eventdata, handles)
+% This is a mouse click path
+% GO function is also called directly from button box
+%  and from MAP model and stats model
+
+set(handles.pushbuttonGO,'visible','off')
+startNewRun(handles)
+
+% ---------------------------------------------------pushbutton0_Callback
+function pushbutton0_Callback(hObject, eventdata, handles)
+global experiment
+% This is a mouse click path
+
+% ignore 0 button if 2I2AFC used
+if findstr(experiment.threshEstMethod,'2I2AFC'), return, end   	
+
+% userDoesNotHearTarget(handles)		% only possible interpretation
+userDecides(handles, false)
+
+% -------------------------------------------------- pushbutton1_Callback
+function pushbutton1_Callback(hObject, eventdata, handles)
+userSelects0or1(handles)				% also called from buttonBox
+
+% ---------------------------------------------------pushbutton2_Callback
+function pushbutton2_Callback(hObject, eventdata, handles)
+userSelects2(handles)					% also called from buttonBox
+
+% --------------------------------------------- pushbuttoNotSure_Callback
+function pushbuttoNotSure_Callback(hObject, eventdata, handles)
+userSelectsPleaseRepeat(handles)		% also called from buttonBox
+
+% -------------------------------------------------- pushbutton3_Callback
+function pushbutton3_Callback(hObject, eventdata, handles)
+
+% ------------------------------------------------- pushbutton19_Callback
+function pushbutton19_Callback(hObject, eventdata, handles)
+% should be invisible (ignore)
+
+% --------------------------------------- pushbuttonWrongButton_Callback
+function pushbuttonWrongButton_Callback(hObject, eventdata, handles)
+userSelectsWrongButton(handles)
+
+% --------------------------------------- editdigitInput_Callback
+function editdigitInput_Callback(hObject, eventdata, handles)
+userSelects0or1(handles)				% after digit string input
+
+
+
+% ----------------------------------------------------- userSelects0or1
+function userSelects0or1(handles)
+global experiment withinRuns
+
+switch experiment.threshEstMethod			
+    case {'2I2AFC++', '2I2AFC+++'}
+        switch withinRuns.stimulusOrder
+            case 'targetFirst';
+                %                 userHearsTarget(handles)
+                userDecides(handles, true)
+            otherwise
+                %                 userDoesNotHearTarget(handles)
+                userDecides(handles, false)
+        end
+    otherwise
+        % single interval
+        % 0 or 1 are treated as equivalent (i.e. target is not heard)
+        userDecides(handles, false)
+end
+% return to pushButton1 callback
+
+% ----------------------------------------------------- userSelects2
+function userSelects2(handles)
+global experiment withinRuns
+switch experiment.threshEstMethod			
+    case {'2I2AFC++', '2I2AFC+++'}
+        switch withinRuns.stimulusOrder
+            case 'targetSecond';
+                %                 userDoesNotHearTarget(handles)
+                userDecides(handles, true)
+            otherwise
+                %                 userHearsTarget(handles)
+                userDecides(handles, false)
+        end
+    otherwise
+        % single interval (2 targets heard)
+        userDecides(handles, true)
+end
+% return to pushButton2 callback
+
+% ----------------------------------------------------- ---- userDecides
+function userDecides(handles, saidYes)
+global experiment stimulusParameters betweenRuns withinRuns
+global rareEvent logistic psy levelsBinVector
+
+if experiment.singleShot
+    return
+end
+
+% ignore click if not 'waitingForResponse'
+if ~strcmp(experiment.status,'waitingForResponse')
+    disp('ignored click')
+    return
+end
+
+% speech reception threshold
+if strcmp(stimulusParameters.targetType,'digitStrings')
+    digitsInput=get(handles.editdigitInput,'string');
+    % must be three digits
+    if ~(length(digitsInput)==3)
+        addToMsg(['error message: Wrong no of digits'], 0, 1)
+        set(handles.textMSG,'string', 'Wrong no of digits', ...
+            'BackgroundColor','r', 'ForegroundColor', 'w')
+        set(handles.editdigitInput,'string','')
+
+        return
+    end
+    % obtain correct answer from file name
+    x=stimulusParameters.digitString;
+    idx=find(x=='O'); x(idx)='0'; % replace 'oh' with zero
+
+    disp([x '   ' digitsInput])
+
+    if x==digitsInput
+        saidYes=1;
+    else
+        saidYes=0;
+    end
+set(handles.editdigitInput,'string','')
+set(handles.editdigitInput,'visible','off')
+pause(0.1)
+end
+
+
+
+% no button presses accepted while processing
+experiment.status='processingResponse';
+
+% catch trials. Restart trial if caught
+if withinRuns.catchTrial
+    if saidYes
+        disp('catch trial - caught out')
+        withinRuns.caughtOut=withinRuns.caughtOut+1;
+        
+        % special: estimate caught out rate by allowing the trial 
+        %  to continue after catch
+        if stimulusParameters.catchTrialBaseRate==0.5
+            %  To use this facility, set the catchTrialRate and the 
+            %   catchTrialBaseRate both to 0.5
+            %    update false positive rate
+            betweenRuns.caughtOut(betweenRuns.runNumber)=...
+                withinRuns.caughtOut;         
+            plotProgressThisTrial(handles)
+            nextStimulus(handles);
+            return
+        end
+        
+        % Punishment: restart the trial
+        set(handles.frame1,'backgroundColor','r')
+        set(handles.pushbuttonGO, ...
+            'visible','on', 'backgroundcolor','y') % and go again
+        msg=[{'Start again: catch trial error'}, {' '},...
+            {'Please,click on the GO button'}];
+        set(handles.textMSG,'string',msg)
+        [y,fs]=wavread('ding.wav');
+        wavplay(y/100,fs)
+        
+        % raise catch trial rate temporarily. 
+        %  this is normally reduced on each new trial (see GO)
+        stimulusParameters.catchTrialRate=...
+            stimulusParameters.catchTrialRate+0.1;
+        if stimulusParameters.catchTrialRate>0.5 
+            stimulusParameters.catchTrialRate=0.5; 
+        end
+        fprintf('stimulusParameters.catchTrialRate= %6.3f\n', ...
+            stimulusParameters.catchTrialRate)
+        
+        betweenRuns.caughtOut(betweenRuns.runNumber)=...
+            1+betweenRuns.caughtOut(betweenRuns.runNumber);
+        betweenRuns.runNumber=betweenRuns.runNumber-1;
+        experiment.status='waitingForGO';
+        return % unwind and wait for button press
+    else % (said No)
+        % user claims not to have heard target. fortunate as it was not
+        %  present. So, repeat the stimulus (possibly with target)
+        %  and behave as if the last trial did not occur
+        errormsg=nextStimulus(handles);
+        
+        % terminate if there is any kind of problem
+        if ~isempty(errormsg)
+            % e.g. limits exceeded, clipping
+            disp(['Error nextStimulus: ' errormsg])
+            runCompleted(handles)
+            return
+        end
+        return      % no further action - next trial
+    end
+end
+
+% This section analyses the responses, makes tracks and defines next stim.
+
+% Define response and update response list
+if saidYes
+    % target was heard, so response=1;
+    withinRuns.responseList=[withinRuns.responseList 1];	% 'heard it!'
+else
+    % target was not hear heard, so response=0;
+    withinRuns.responseList=[withinRuns.responseList 0];
+end
+withinRuns.levelList=[withinRuns.levelList withinRuns.variableValue];
+trialNumber=length(withinRuns.responseList);
+
+% keep track of peaks and troughs;
+% identify direction of change during initial period
+if saidYes
+    % default step size before first reversal
+    WRVinitialStep=-stimulusParameters.WRVinitialStep; 
+    WRVsmallStep=-stimulusParameters.WRVsmallStep;
+    % if the previous direction was 'less difficult', this must be a peak
+    if strcmp(withinRuns.direction,'less difficult') ...
+            && length(withinRuns.levelList)>1
+        withinRuns.peaks=[withinRuns.peaks withinRuns.variableValue];
+    end
+    withinRuns.direction='more difficult';
+    
+else
+    % said 'no'
+    % default step size before first reversal
+    WRVinitialStep=stimulusParameters.WRVinitialStep; 
+    WRVsmallStep=stimulusParameters.WRVsmallStep;
+    
+    % if the previous direction was 'up', this must be a peak
+    if strcmp(withinRuns.direction,'more difficult') ...
+            && length(withinRuns.levelList)>1
+        withinRuns.troughs=[withinRuns.troughs withinRuns.variableValue];
+    end
+    withinRuns.direction='less difficult';
+end
+
+% phase 2 is all the levels after and incuding the first reversal 
+%  plus the level before that
+if ~withinRuns.nowInPhase2 && length(withinRuns.peaks)+ ...
+        length(withinRuns.troughs)>0
+% if ~withinRuns.nowInPhase2 && (~isempty(withinRuns.peaks) ...
+%         || ~isempty(withinRuns.troughs))
+    % define phase 2
+    withinRuns.beginningOfPhase2=trialNumber-1;
+    withinRuns.nowInPhase2=1;
+    WRVsmallStep=WRVinitialStep/2;
+end
+
+if withinRuns.nowInPhase2
+    % keep a record of all levels and responses in phase 2 only
+    withinRuns.levelsPhaseTwo=...
+        withinRuns.levelList(withinRuns.beginningOfPhase2:end);
+    withinRuns.responsesPhaseTwo=...
+        withinRuns.responseList(withinRuns.beginningOfPhase2:end);
+else
+    withinRuns.levelsPhaseTwo=[];
+end
+
+
+% get (or substitute) threshold estimate
+switch experiment.threshEstMethod
+    case {'2I2AFC++', '2I2AFC+++'}
+        % for plotting psychometric function only
+        if withinRuns.beginningOfPhase2>0
+            [psy, levelsBinVector, logistic, rareEvent]= ...
+                bestFitPsychometicFunctions...
+                (withinRuns.levelsPhaseTwo,  withinRuns.responsesPhaseTwo);
+        end
+        
+        if ~isempty(withinRuns.peaks) && ~isempty(withinRuns.troughs)
+            thresholdEstimate= ...
+                mean([mean(withinRuns.peaks) mean(withinRuns.troughs)]);
+        else
+            thresholdEstimate=NaN;
+        end
+    otherwise
+        % single interval methods
+        try
+            % using the s trial after the first reversal
+            [psy, levelsBinVector, logistic, rareEvent]= ...
+                bestFitPsychometicFunctions(withinRuns.levelsPhaseTwo,...
+                withinRuns.responsesPhaseTwo);
+        catch
+            logistic.bestThreshold=NaN;
+        end
+end
+
+if withinRuns.nowInPhase2
+    % save tracks of threshold estimates for plotting andprinting
+    switch experiment.functionEstMethod
+        case {'logisticLS', 'logisticML'}
+            if withinRuns.nowInPhase2
+                withinRuns.meanEstTrack=...
+                    [withinRuns.meanEstTrack ...
+                    mean(withinRuns.levelsPhaseTwo)];
+                withinRuns.thresholdEstimateTrack=...
+                    [withinRuns.thresholdEstimateTrack ...
+                    logistic.bestThreshold];
+            end
+        case 'rareEvent'
+            withinRuns.meanEstTrack=...
+                [withinRuns.meanEstTrack rareEvent.thresholddB];
+            withinRuns.thresholdEstimateTrack=...
+                [withinRuns.thresholdEstimateTrack logistic.bestThreshold];
+        case 'peaksAndTroughs'
+            withinRuns.meanEstTrack=...
+                [withinRuns.meanEstTrack thresholdEstimate];
+            withinRuns.thresholdEstimateTrack=...
+                [withinRuns.thresholdEstimateTrack thresholdEstimate];
+    end
+end
+
+% special discomfort condition
+% run is completed when subject hits '2' button
+switch experiment.paradigm
+    case 'discomfort'
+        if saidYes
+            runCompleted(handles)
+            return
+        end
+end
+
+% choose the next level for the stimulus
+switch experiment.threshEstMethod
+    case {'2I2AFC++', '2I2AFC+++'}
+        if saidYes
+            [WRVinitialStep, msg]=Levitt2('hit', withinRuns.variableValue);
+        else
+            [WRVinitialStep, msg]=Levitt2('miss',withinRuns.variableValue);
+        end
+        
+        % empty message means continue as normal
+        if ~isempty(msg)				
+            runCompleted(handles)
+            return
+        end
+        newWRVvalue=withinRuns.variableValue-WRVinitialStep;
+        
+    case {'MaxLikelihood', 'oneIntervalUpDown'}
+        % run completed by virtue of number of trials               
+        % or restart because listener is in trouble
+        if length(withinRuns.levelsPhaseTwo)== experiment.maxTrials
+            % Use bonomial test to decide if there is an imbalance in the
+            % number of 'yes'es and 'no's
+            yesCount=sum(withinRuns.responseList);
+            noCount=length(withinRuns.responseList)-yesCount;
+            z=abs(yesCount-noCount)/(yesCount+noCount)^0.5;
+            if z>1.96
+                betweenRuns.resets=betweenRuns.resets+1;
+                disp([ 'reset / z= ' num2str( z)  ...
+                    '   Nresets= ' num2str( betweenRuns.resets) ] )
+                withinRuns.peaks=[];
+                withinRuns.troughs=[];
+                withinRuns.levelList=withinRuns.levelList(end);
+                withinRuns.meanEstTrack=withinRuns.meanEstTrack(end);
+                withinRuns.forceThreshold=NaN;
+                withinRuns.responseList=withinRuns.responseList(end);
+                withinRuns.beginningOfPhase2=0;
+                withinRuns.nowInPhase2=0;
+                withinRuns.thresholdEstimateTrack=...
+                    withinRuns.thresholdEstimateTrack(end);
+            else
+                runCompleted(handles)
+                return
+            end
+        end
+        
+        % set new value for WRV
+        if withinRuns.nowInPhase2
+            % phase 2
+            currentMeanEst=withinRuns.thresholdEstimateTrack(end);
+            switch experiment.threshEstMethod
+                case 'MaxLikelihood'
+                    newWRVvalue=currentMeanEst;                    
+                case {'oneIntervalUpDown'}
+                    newWRVvalue=withinRuns.variableValue+WRVsmallStep;
+            end
+        else
+            % phase 1
+            if withinRuns.variableValue+2*WRVinitialStep>...
+                    stimulusParameters.WRVlimits(2)
+                % use smaller steps when close to maximum
+                WRVinitialStep=WRVinitialStep/2;
+            end
+            newWRVvalue=withinRuns.variableValue+WRVinitialStep;
+        end
+    otherwise
+        error(  'assessment method not recognised')
+end
+
+switch experiment.paradigm
+    % prevent unrealistic gap durations 'gapDetection' tasks.
+    % Note that the gap begins when the ramp ends not when stimulus ends
+    case 'gapDetection'
+        if newWRVvalue<-2*stimulusParameters.rampDuration
+            newWRVvalue=-2*stimulusParameters.rampDuration;
+            addToMsg('gap duration fixed at - 2 * ramp!',1, 1)
+        end
+end
+
+withinRuns.variableValue=newWRVvalue;
+withinRuns.trialNumber=withinRuns.trialNumber+1;
+
+% Trial continues
+plotProgressThisTrial(handles)
+
+% next stimulus and so the cycle continues
+errormsg=nextStimulus(handles);
+% after the stimulus is presented, control returns here and the system
+% waits for user action.
+
+% terminate if there is any kind of problem
+if ~isempty(errormsg)
+    % e.g. limits exceeded, clipping
+    disp(['Error nextStimulus: ' errormsg])
+    runCompleted(handles)
+    return
+end
+
+% ------------------------------------------------ userSelectsPleaseRepeat
+function userSelectsPleaseRepeat(handles)
+global experiment withinRuns
+% ignore click if not 'waitingForResponse'
+if ~strcmp(experiment.status,'waitingForResponse')
+    disp('ignored click')
+    return
+end
+% Take no action other than to make a 
+%  tally of repeat requests
+experiment.pleaseRepeat=experiment.pleaseRepeat+1;
+withinRuns.thisIsRepeatTrial=1;
+nextStimulus(handles);
+
+% ------------------------------------------------ userSelectsWrongButton
+function userSelectsWrongButton(handles)
+global withinRuns experiment
+% restart is the simplest solution for a 'wrong button' request
+withinRuns.wrongButton=withinRuns.wrongButton+1;
+set(handles.pushbuttonGO, 'visible','on', 'backgroundcolor','y') 
+msg=[{'Start again: wrong button pressed'}, {' '},...
+    {'Please,click on the GO button'}];
+set(handles.textMSG,'string',msg)
+experiment.status='waitingForGO';
+
+% ------------------------------------------------- plotProgressThisTrial
+function plotProgressThisTrial(handles)
+
+% used for all responses
+global experiment stimulusParameters betweenRuns withinRuns expGUIhandles
+global  psy levelsBinVector binFrequencies rareEvent logistic statsModel
+
+
+% plot the levelTrack and the threshold track
+
+% Panel 2
+% plot the levelList
+axes(expGUIhandles.axes2); cla
+plot( withinRuns.levelList,'o','markerFaceColor','k'), hold on
+% plot the best threshold estimate tracks
+if length(withinRuns.meanEstTrack)>=1
+    % The length of the levelList is 2 greater than number of thresholds
+    ptr=withinRuns.beginningOfPhase2+1;
+    plot(ptr: ptr+length(withinRuns.meanEstTrack)-1, ...
+        withinRuns.meanEstTrack, 'r')
+    plot( ptr: ptr+length(withinRuns.thresholdEstimateTrack)-1, ...
+        withinRuns.thresholdEstimateTrack, 'g')
+    hold off
+    estThresh=withinRuns.thresholdEstimateTrack(end);
+    switch experiment.threshEstMethod
+        % add appropriate labels to subject GUI buttons
+        case {'2I2AFC++', '2I2AFC+++'}
+            title([stimulusParameters.WRVname ' = ' ...
+                num2str(withinRuns.variableValue, '%5.1f')])
+        otherwise
+            title([stimulusParameters.WRVname ' = ' ...
+                num2str(withinRuns.variableValue, '%5.1f') ...
+                ';    TH= ' num2str(estThresh, '%5.1f')])
+    end
+end
+xlim([0 experiment.maxTrials+withinRuns.beginningOfPhase2]);
+ylim(stimulusParameters.WRVlimits)
+grid on
+
+% Panel 4: Summary of threshold estimates (not used here)
+% Earlier estimates are set in 'runCompleted'
+% However, title shows runs/trials remaining
+
+axes(expGUIhandles.axes4)
+runsToGo=length(betweenRuns.var1Sequence)-betweenRuns.runNumber;
+if withinRuns.beginningOfPhase2>0
+    trialsToGo= experiment.singleIntervalMaxTrials(1) ...
+        + withinRuns.beginningOfPhase2- withinRuns.trialNumber;
+    title(['trials remaining = ' num2str(trialsToGo) ...
+        ':    runs to go= ' num2str(runsToGo)])
+end
+
+% plot psychometric function   - panel 5
+axes(expGUIhandles.axes5), cla
+plot(withinRuns.levelList, withinRuns.responseList,'b.'), hold on
+ylim([0 1])
+title('')
+
+switch experiment.threshEstMethod
+    case {'MaxLikelihood', 'oneIntervalUpDown'}
+        if withinRuns.beginningOfPhase2>0
+            % display only when in phase 2.
+            withinRuns.levelsPhaseTwo=...
+                withinRuns.levelList(withinRuns.beginningOfPhase2:end);
+            withinRuns.responsesPhaseTwo=...
+                withinRuns.responseList(withinRuns.beginningOfPhase2:end);
+            
+            % organise data as psychometric function
+            [psy, levelsBinVector, binFrequencies]= ...
+                psychometricFunction(withinRuns.levelsPhaseTwo,...
+                withinRuns.responsesPhaseTwo, experiment.psyBinWidth);
+            
+            % Plot the function
+            %   point by point with circles of appropiate weighted size
+            hold on,
+            for i=1:length(psy)
+                plot(levelsBinVector(i), psy(i), 'ro', ...
+                    'markersize', 50*binFrequencies(i)/sum(binFrequencies))
+            end
+            % save info for later
+            betweenRuns.psychometicFunction{betweenRuns.runNumber}=...
+                [levelsBinVector; psy];
+            
+            % fitPsychometric functions is  computed in 'userDecides'
+            % plot(rareEvent.predictionLevels, rareEvent.predictionsRE,'k')
+            plot(logistic.predictionLevels, logistic.predictionsLOG, 'r')
+            plot(rareEvent.predictionLevels, rareEvent.predictionsRE, 'k')
+            if ~isnan(logistic.bestThreshold )
+%                 xlim([ (logistic.bestThreshold -20) ...
+%                     (logistic.bestThreshold +20) ])
+                xlim([ 0 100 ])
+%                 if logistic.bestK< max(experiment.possLogSlopes)
+                    title(['k= ' num2str(logistic.bestK, '%6.2f') ' g= '...
+                        num2str(rareEvent.bestGain,'%6.3f') '  A=' ...
+                        num2str(rareEvent.bestVMin,'%8.1f')])
+%                     title('')
+%                 end
+            else
+                title(' ')
+            end
+            
+            switch experiment.ear
+                %plot green line for statsModel a priori model
+                case 'statsModelLogistic'
+                    % plot proTem logistic (green) used by stats model
+                    p= 1./(1+exp(-statsModel.logisticSlope...
+                        *(levelsBinVector-logistic.bestThreshold)));
+                    if experiment.psyFunSlope<0, p=1-p;end
+                    titleText=[ ',  statsModel: logistic'];
+                    hold on,    plot(levelsBinVector, p,'g')
+                case  'statsModelRareEvent'
+                    pressure=28*10.^(levelsBinVector/20);
+                    p=1-exp(-stimulusParameters.targetDuration...
+                        *(statsModel.rareEvenGain...
+                        * pressure-statsModel.rareEventVmin));
+                    p(p<0)=0;
+                    if experiment.psyFunSlope<0, p=1-p;end
+                    hold on,    plot(levelsBinVector, p,'g')
+            end %(estMethod)
+        end
+    otherwise           % 2A2IFC
+        
+        message3= ...
+            ([ 'peaks='  num2str(withinRuns.peaks) ...
+            'troughs='  num2str(withinRuns.troughs)]);
+        ylimRM([-0.1 1.1])	% 0=no / 1=yes
+        set(gca,'ytick',[0 1], 'yTickLabel', {'no';'yes'})
+        ylabel('psychometric function'), xlabel('target level')
+        if length(levelsBinVector)>1
+            xlim([ min(levelsBinVector) max(levelsBinVector)])
+            xlim([ 0 100])
+        end
+end
+
+% command window summary
+% Accumulate things to say in the message window
+message1= (['responses:      ' num2str(withinRuns.responseList,'%9.0f')]);
+switch experiment.paradigm
+    % more decimal places needed on GUI
+    case { 'gapDetection', 'frequencyDiscrimination', 'forwardMaskingD'}
+        message2= ([stimulusParameters.WRVname  ...
+            ':       ' num2str(withinRuns.levelList,'%7.3f')]);
+        message3= (['Thresh (logistic mean):   ' ...
+            num2str(withinRuns.thresholdEstimateTrack,'%7.3f')]);
+    otherwise
+        message2= ([stimulusParameters.WRVname ':      ' ...
+            num2str(withinRuns.levelList,'%7.1f')]);
+        message3= (['Thresh (logistic mean):   ' ...
+            num2str(withinRuns.thresholdEstimateTrack,'%7.1f')]);
+end
+
+addToMsg(str2mat(message1, message2, message3), 0)
+
+% -----------------------------------------------------runCompleted
+function runCompleted(handles)
+% Used at the end of each run
+global experiment stimulusParameters betweenRuns withinRuns
+global rareEvent expGUIhandles
+% disp('run completed')
+
+experiment.status='runCompleted';
+
+plotProgressThisTrial(handles)
+
+switch experiment.ear
+    case {'statsModelLogistic', 'statsModelRareEvent','MAPmodel', ...
+            'MAPmodelMultiCh','MAPmodelSingleCh', 'MAPmodelListen'}
+        % no changes required if model used
+    otherwise
+        set(handles.frame1,'visible','off')
+        set(handles.pushbuttoNotSure,'visible','off')
+        set(handles.pushbuttonWrongButton,'visible','off')
+        set(handles.pushbutton3,'visible','off')
+        set(handles.pushbutton2,'visible','off')
+        set(handles.pushbutton1,'visible','off')
+        set(handles.pushbutton0,'visible','off')
+        set(handles.pushbuttonGO,'visible','off')
+end
+
+if isnan(withinRuns.forceThreshold)
+    % the experiment has been aborted for some reason
+    threshold=withinRuns.forceThreshold;
+    stdev=NaN;
+    logistic.bestK=NaN;
+    logistic.bestThreshold=NaN;
+    medianThreshold=NaN;
+    meanThreshold=NaN;
+else
+    % use only phase 2 levels and responses for calculating thresholds
+    withinRuns.levelsPhaseTwo=...
+        withinRuns.levelList(withinRuns.beginningOfPhase2:end);
+    withinRuns.responsesPhaseTwo=...
+        withinRuns.responseList(withinRuns.beginningOfPhase2:end);
+    [psy, levelsPhaseTwoBinVector, logistic, rareEvent]= ...
+        bestFitPsychometicFunctions...
+        (withinRuns.levelsPhaseTwo, withinRuns.responsesPhaseTwo);
+    
+    % plot final psychometric function
+    axes(expGUIhandles.axes5),cla
+    hold on, plot(rareEvent.predictionLevels, rareEvent.predictionsRE, 'k')
+    hold on, plot(logistic.predictionLevels, logistic.predictionsLOG, 'r')
+    % organise data as psychometric function
+    [psy, levelsBinVector, binFrequencies]= ...
+        psychometricFunction(withinRuns.levelsPhaseTwo,...
+        withinRuns.responsesPhaseTwo, experiment.psyBinWidth);
+    %   point by point with circles of appropiate weighted size
+    hold on,
+    for i=1:length(psy)
+        plot(levelsBinVector(i), psy(i), 'ro', ...
+            'markersize', 50*binFrequencies(i)/sum(binFrequencies))
+    end
+
+    
+    % experimental
+    medianThreshold=median(withinRuns.levelsPhaseTwo);
+    warning off
+    meanThreshold=mean(withinRuns.levelsPhaseTwo);
+    
+    % identify the current threshold estimate
+    switch experiment.paradigm
+        case 'discomfort'
+            % most recent value (not truely a mean value)
+            threshold=withinRuns.levelList(end);
+            stdev=NaN;            
+        otherwise
+            switch experiment.threshEstMethod
+                case {'MaxLikelihood', 'oneIntervalUpDown'}
+                    % last value in the list
+                    threshold=withinRuns.meanEstTrack(end);
+                    threshold=withinRuns.thresholdEstimateTrack(end);
+                    stdev=NaN;
+                    
+                case {'2I2AFC++', '2I2AFC+++'}
+                    % use peaks and troughs
+                    try		% there may not be enough values to use
+                        peaksUsed=experiment.peaksUsed;
+                        threshold=...
+                            mean(...
+                            [withinRuns.peaks(end-peaksUsed+1:end) ...
+                            withinRuns.troughs(end-peaksUsed+1:end)]);
+                        stdev=...
+                            std([withinRuns.peaks(end-peaksUsed +1:end) ...
+                            withinRuns.troughs(end-peaksUsed:end)]);
+                    catch
+                        threshold=NaN;
+                        stdev=NaN;
+                    end
+            end
+    end
+end
+
+% Store thresholds
+betweenRuns.thresholds=[betweenRuns.thresholds threshold];
+betweenRuns.thresholds_mean=[betweenRuns.thresholds_mean meanThreshold];
+betweenRuns.thresholds_median=...
+    [betweenRuns.thresholds_median medianThreshold];
+betweenRuns.forceThresholds=...
+    [betweenRuns.forceThresholds withinRuns.forceThreshold];
+
+% count observations after the startup phase for record keeping
+betweenRuns.observationCount=...
+    [betweenRuns.observationCount length(withinRuns.levelList)];
+betweenRuns.timesOfFirstReversals=...
+    [betweenRuns.timesOfFirstReversals withinRuns.beginningOfPhase2];
+betweenRuns.catchTrials=...
+    [betweenRuns.catchTrials withinRuns.catchTrialCount];
+
+% add variable length tracks to cell arrays
+if withinRuns.beginningOfPhase2>0
+    betweenRuns.bestThresholdTracks{length(betweenRuns.thresholds)}=...
+        withinRuns.thresholdEstimateTrack;
+    betweenRuns.bestThresholdMeanTracks...
+        {length(betweenRuns.thresholds_mean)}=...
+        withinRuns.thresholdEstimateTrack;
+    betweenRuns.bestThresholdMedianTracks...
+        {length(betweenRuns.thresholds_median)}=...
+        withinRuns.thresholdEstimateTrack;
+    
+    betweenRuns.levelTracks{length(betweenRuns.thresholds)}=...
+        withinRuns.levelList(withinRuns.beginningOfPhase2:end);
+    betweenRuns.responseTracks{length(betweenRuns.thresholds)}=...
+        withinRuns.responseList(withinRuns.beginningOfPhase2:end);
+else
+    betweenRuns.bestThresholdTracks{length(betweenRuns.thresholds)}=[];
+    betweenRuns.bestThresholdMeanTracks{length(betweenRuns.thresholds)}=[];
+    betweenRuns.bestThresholdMedianTracks{length(betweenRuns.thresholds)}=...
+        [];
+    betweenRuns.levelTracks{length(betweenRuns.thresholds)}=[];
+    betweenRuns.responseTracks{length(betweenRuns.thresholds)}=[];
+end
+
+betweenRuns.bestGain=[betweenRuns.bestGain rareEvent.bestGain];
+betweenRuns.bestVMin=[betweenRuns.bestVMin rareEvent.bestVMin];
+betweenRuns.bestPaMin=[betweenRuns.bestPaMin rareEvent.bestPaMindB];
+betweenRuns.bestLogisticM=...
+    [betweenRuns.bestLogisticM logistic.bestThreshold];
+betweenRuns.bestLogisticK=[betweenRuns.bestLogisticK logistic.bestK];
+
+resultsSoFar=[betweenRuns.var1Sequence(betweenRuns.runNumber)'...
+    betweenRuns.var2Sequence(betweenRuns.runNumber)'...
+    betweenRuns.thresholds(betweenRuns.runNumber)'
+    ];
+
+fprintf('%10.3f \t%10.3f \t%10.1f  \n', resultsSoFar')
+
+switch experiment.ear
+    case {'left', 'right', 'diotic', 'dichoticLeft','dichoticRight'}
+        disp(['caught out= ' num2str(betweenRuns.caughtOut)])
+end
+
+% plot history of thresholds in panel 4
+axes(expGUIhandles.axes4), cla
+plotColors='rgbmckywrgbmckyw';
+for i=1:length(betweenRuns.thresholds)
+    faceColor=plotColors(floor(i/length(betweenRuns.variableList1)-.01)+1);
+    switch betweenRuns.variableName1
+        case {'targetFrequency', 'maskerRelativeFrequency'}
+            if min(betweenRuns.var1Sequence)>0
+                %             semilogx(betweenRuns.var1Sequence(1:betweenRuns.runNumber), ...
+                %                 betweenRuns.thresholds,  'o', ...
+                %                 'markerSize', 5,'markerFaceColor',faceColor)
+                semilogx(betweenRuns.var1Sequence(i), ...
+                    betweenRuns.thresholds(i),  'o', ...
+                    'markerSize', 5,'markerFaceColor',faceColor)
+            else
+                plot(betweenRuns.var1Sequence(1:betweenRuns.runNumber),  ...
+                    betweenRuns.thresholds,  'o', ...
+                    'markerSize', 5,'markerFaceColor',faceColor)
+                plot(betweenRuns.var1Sequence(i),  ...
+                    betweenRuns.thresholds(i),  'o', ...
+                    'markerSize', 5,'markerFaceColor',faceColor)
+            end
+        otherwise
+            %         plot(betweenRuns.var1Sequence(1:betweenRuns.runNumber),  ...
+            %             betweenRuns.thresholds,  'o', 'markerSize', 5,...
+            %             'markerFaceColor',faceColor)
+            plot(betweenRuns.var1Sequence(i),  ...
+                betweenRuns.thresholds(i),  'o', 'markerSize', 5,...
+                'markerFaceColor',faceColor)
+    end
+    hold on
+end
+xlimRM([ min(betweenRuns.variableList1) max(betweenRuns.variableList1) ])
+ylim(stimulusParameters.WRVlimits)
+ylabel('thresholds')
+xlabel(betweenRuns.variableName1)
+set(gca,'ytick', [0 20 40 60 80 100])
+try
+    % problems if only one x value
+    set(gca,'XTick', sort(betweenRuns.variableList1))
+catch
+end
+grid on, set(gca,'XMinorGrid', 'off')
+
+% If comparison data is available in pearmeter file, plot it now
+if ~isempty (experiment.comparisonData)
+    comparisonData=experiment.comparisonData(:,1:end-1); % ignore final BF
+    [x, ncols]=size(comparisonData);
+    if  length(betweenRuns.variableList1)==ncols
+        hold on
+        plot (sort(betweenRuns.variableList1), comparisonData, 'r')
+        hold off
+    end
+end
+
+% End of the Experiment also?
+if betweenRuns.runNumber==length(betweenRuns.var1Sequence)
+    % yes, end of experiment
+    fileName=['savedData/' experiment.name experiment.date ...
+        experiment.paradigm];
+    % 	save (fileName, 'experiment', 'stimulusParameters', 'betweenRuns', 'withinRuns', 'variableNames', 'paradigmNames', 'LevittControl')
+    disp('Experiment completed')
+    
+    % update subject GUI to acknowledge end of run
+    subjGUImsg=[{'Experiment completed'}, {' '}, {'Thank you!'}];
+    set(handles.textMSG,'string', subjGUImsg   )
+    % play 'Tada'
+    [y,fs,nbits]=wavread('TADA.wav');
+    musicGain=10^(stimulusParameters.musicLeveldB/20);
+    y=y*musicGain;
+    wavplay(y/100,fs, 'async')
+    
+    % update experimenter GUI
+    addToMsg('Experiment completed.',1)
+    
+    printReport
+    experiment.status='endOfExperiment';  
+    return
+else
+    % No, hang on.
+    switch experiment.ear
+        case {'statsModelLogistic', 'statsModelRareEvent','MAPmodel', ...
+                'MAPmodelMultiCh','MAPmodelSingleCh', 'MAPmodelListen'}
+            % no changes required if model used
+        otherwise
+            % decrement catchTrialRate towards baseRate
+            stimulusParameters.catchTrialRate=...
+                stimulusParameters.catchTrialBaseRate + ...
+                (stimulusParameters.catchTrialRate...
+                -stimulusParameters.catchTrialBaseRate)...
+                *(1-exp(-stimulusParameters.catchTrialTimeConstant));
+            fprintf('stimulusParameters.catchTrialRate= %6.3f\n', ...
+                stimulusParameters.catchTrialRate)
+            
+            % and go again
+            set(handles.pushbuttonGO,'backgroundcolor','y') 
+            set(handles.frame1,'visible','off')
+            set(handles.pushbuttonGO,'visible','on')
+            msg=[{'Ready to start new trial'}, {' '},...
+                {'Please,click on the GO button'}];
+            set(handles.textMSG,'string',msg)
+    end
+    experiment.status='waitingForGO';
+    %     fprintf('\n')
+    
+    [y,fs,nbits]=wavread('CHIMES.wav');
+    musicGain=10^(stimulusParameters.musicLeveldB/20);
+    y=y*musicGain;
+    wavplay(y/100,fs,'async')
+end
+
+% -----------------------------------------------------MAPmodelRunsGUI
+% The computer presses the buttons
+function 	MAPmodelRunsGUI(handles)
+global experiment stimulusParameters method expGUIhandles
+global AN_IHCsynapseParams
+method=[];
+
+while strcmp(experiment.status,'waitingForGO') 
+    % no catch trials for MAP model
+    experiment.allowCatchTrials=0;
+    
+    % initiates run and plays first stimulus and it returns 
+    %  without waiting for button press
+    startNewRun(handles)	
+
+    if sum(strcmp(experiment.ear,...
+            {'MAPmodelMultiCh', 'MAPmodelListen'}))
+        % use BFlist specified in MAPparams file
+        BFlist= -1;
+    else
+        BFlist=stimulusParameters.targetFrequency;
+    end
+    showParams=0;
+    %  find model parameters using the 'name' box (e.g. CTa ->MAPparamsCTa)
+    paramFunctionName=['method=MAPparams' experiment.name ...
+        '(BFlist, stimulusParameters.sampleRate, showParams);'];
+    eval(paramFunctionName) % go and fetch the parameters
+    
+
+    % show sample Rate on GUI; it must be set in MAPparams
+    set(expGUIhandles.textsampleRate,'string',...
+        num2str(stimulusParameters.sampleRate))
+    
+    if experiment.singleShot
+%         AN_IHCsynapseParams.showSummaryStatistics=1;
+        method.showSummaryStatistics=1;
+        AN_IHCsynapseParams.plotSynapseContents=1;
+    else
+        method.showSummaryStatistics=0;
+        AN_IHCsynapseParams.plotSynapseContents=0;
+    end
+    
+    if strcmp(experiment.ear, 'MAPmodelSingleCh')
+    method.MGmembranePotentialSave=1;
+    end
+    
+    % continuous loop until the program stops itself
+    while strcmp(experiment.status,'waitingForResponse')
+        %  NB at this point the stimulus has been played
+        pause(0.1)  % to allow interrupt with CTRL/C
+        
+        switch experiment.ear
+            case { 'MAPmodelListen'}
+            set(handles.pushbutton1,'backgroundcolor','y','visible','on')
+            set(handles.pushbutton2,'backgroundcolor','y','visible','on')
+        end
+
+AN_IHCsynapseParams.mode=	'spikes';
+
+% Analayse the current stimulus using MAP
+        [modelResponse earObject]= MAPmodel( experiment.MAPplot, method);
+        
+        if experiment.stop || experiment.singleShot
+            % trap for single trial or user interrupt using 'stop' button.
+            experiment.status= 'waitingForStart';
+            experiment.stop=0;
+            addToMsg('manually stopped',1);
+            return
+        end
+        
+        switch modelResponse
+            case 1
+                %     userDoesNotHearTarget(handles)
+                switch experiment.ear
+                    case {'MAPmodelListen'}
+                        % illuminate appropriate button
+                        set(handles.pushbutton1,...
+                            'backgroundcolor','r','visible','on')
+                        set(handles.pushbutton2,'backgroundcolor','y')
+                end
+                userDecides(handles, false)
+                if experiment.singleShot, return, end
+
+            case 2
+                %   userHearsTarget(handles)
+                switch experiment.ear
+                    case {'MAPmodelListen'}
+                        % illuminate appropriate button (DEMO only)
+                        set(handles.pushbutton2,'backgroundcolor',...
+                            'r','visible','on')
+                        set(handles.pushbutton1,'backgroundcolor','y')
+                end
+                
+                switch experiment.paradigm
+                    case 'discomfort'
+                        % always treat discomfort as 'not heard'
+                        userDecides(handles, false)
+                    otherwise
+                        userDecides(handles, true)
+                end
+            otherwise
+                % probably an abort
+                return
+        end
+    end
+end
+
+
+% -----------------------------------------------------statsModelRunsGUI
+% The computer presses the buttons
+function 	statsModelRunsGUI(handles)
+% Decision are made at random using a prescribe statistical function
+% to set probabilities as a function of signal level.
+global experiment
+
+experiment.allowCatchTrials=0;
+
+while strcmp(experiment.status,'waitingForGO')
+    % i.e. waiting for new run
+    if experiment.stop
+        % user has requested an abort
+        experiment.status= 'waitingForStart';
+        addToMsg('manually stopped',1)
+        return
+    end
+    
+    % initiates run and plays first stimulus and it returns
+    %  without waiting for button press
+    % NB stimulus is not actually generated (for speed)
+    startNewRun(handles)
+    
+    while strcmp(experiment.status,'waitingForResponse')
+        % create artificial response here
+        modelResponse=statsModelGetResponse;
+        switch modelResponse
+            case 1
+                %                 userDoesNotHearTarget(handles)
+                userDecides(handles, false)
+            case 2
+                %                 userHearsTarget(handles)
+                userDecides(handles, true)
+        end
+    end
+end
+
+% -----------------------------------------------------statsModelGetResponse
+function modelResponse=statsModelGetResponse(handles)
+global experiment  withinRuns  statsModel stimulusParameters
+% use the generating function to decide if a detection occurs or not
+
+% pause(0.1)  % to allow stopping with CTRL/C but slows things down
+
+% first compute the probability that a detection occurs
+switch experiment.ear
+    case {'statsModelLogistic'}
+        prob= 1./(1+exp(-statsModel.logisticSlope.*(withinRuns.variableValue-statsModel.logisticMean)));
+        %         if experiment.psyFunSlope<0,
+        %             prob=1-prob;
+        %         end
+        
+    case 'statsModelRareEvent'
+        if experiment.psyFunSlope<0
+            addToMsg('statsModelRareEvent cannot be used with negative slope',0)
+            error('statsModelRareEvent cannot be used with negative slope')
+        end
+        
+        % standard formula is prob = 1 – exp(-d (g P – A))
+        % here A->A;  To find Pmin use A/gain
+        pressure=28*10^(withinRuns.variableValue/20);
+        gain=statsModel.rareEvenGain;
+        A=statsModel.rareEventVmin;
+        d=stimulusParameters.targetDuration;
+        gP_Vmin=gain*pressure-A;
+        if gP_Vmin>0
+            prob=1-exp(-d*(gP_Vmin));
+        else
+            prob=0;
+        end
+end
+
+% Use the probability to choose whether or not a detection has occurred
+switch experiment.threshEstMethod
+    case {'MaxLikelihood', 'oneIntervalUpDown'}
+        if rand<prob
+            modelResponse=2; %bingo
+        else
+            modelResponse=1; %nothing heard
+        end
+        
+    case {'2I2AFC++', '2I2AFC+++'}
+        if rand<prob
+            modelResponse=2; %bingo
+        else %if the stimulus is not audible, take a 50:50 chance of getting it right
+            if rand<0.5
+                modelResponse=2; %bingo
+            else
+                modelResponse=1; %nothing heard
+            end
+        end
+end
+
+
+% ------------------------------------------------------- printTabTable
+function printTabTable(M, headers)
+% printTabTable prints a matrix as a table with tabs
+%headers are optional
+%headers=strvcat('firstname', 'secondname')
+%  printTabTable([1 2; 3 4],strvcat('a1','a2'));
+
+if nargin>1
+    [r c]=size(headers);
+    for no=1:r
+        fprintf('%s\t',headers(no,:))
+    end
+    fprintf('\n')
+end
+
+[r c]=size(M);
+
+for row=1:r
+    for col=1:c
+        if row==1 && col==1 && M(1,1)==-1000
+            %   Print nothing (tab follows below)
+        else
+            fprintf('%s',num2str(M(row,col)))
+        end
+        if col<c
+            fprintf('\t')
+        end
+    end
+    fprintf('\n')
+end
+
+% ------------------------------------------------------- xlimRM
+function xlimRM(x)
+try
+    xlim([x(1) x(2)])
+catch
+end
+
+% ------------------------------------------------------- ylimRM
+function ylimRM(x)
+try
+    ylim([x(1) x(2)])
+catch
+end
+
+
+function editdigitInput_CreateFcn(hObject, eventdata, handles)
+
+% Hint: edit controls usually have a white background on Windows.
+%       See ISPC and COMPUTER.
+if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+    set(hObject,'BackgroundColor','white');
+end
+
+
+% -----------------------------------------------------buttonBoxIntitialize
+function buttonBoxIntitialize
+% initialize button box
+global  serobj
+try
+    fclose(serobj);
+catch
+end
+
+try
+    serobj = serial('COM4') ;           	% Creating serial port object now its connected to COM4 !!! button boxes in booths are connected to COM2
+    serobj.Baudrate = 9600;           		% Set the baud rate at the specific value
+    set(serobj, 'Parity', 'none') ;     	% Set parity as none
+    set(serobj, 'Databits', 8) ;          	% set the number of data bits
+    set(serobj, 'StopBits', 1) ;         	% set number of stop bits as 1
+    set(serobj, 'Terminator', 'CR') ; 		% set the terminator value to carriage return
+    set(serobj, 'InputBufferSize', 512) ;  	% Buffer for read operation, default it is 512
+    set(serobj,'timeout',10);           	% 10 sec timeout on button press
+    set(serobj, 'ReadAsyncMode', 'continuous')
+    set(serobj, 'BytesAvailableFcn', @buttonBox_callback)
+    set(serobj, 'BytesAvailableFcnCount', 1)
+    set(serobj, 'BytesAvailableFcnMode', 'byte')
+    % set(serobj, 'BreakInterruptFcn', '@buttonBox_Calback')
+    
+    fopen(serobj);
+    buttonBoxStatus=get(serobj,'status');
+catch
+    disp('** no button box found - use mouse **')
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/testAN.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,289 @@
+function testAN
+% testIHC used either for IHC I/O function ...
+%  or receptive field (doReceptiveFields=1)
+
+global experiment method stimulusParameters
+global IHC_VResp_VivoParams IHCpreSynapseParams
+global AN_IHCsynapseParams
+% global saveMembranePotential MacGregorMultiParams
+dbstop if error
+
+addpath (['..' filesep 'MAP'], ['..' filesep 'utilities'], ...
+    ['..' filesep 'parameterStore'],  ['..' filesep 'wavFileStore'],...
+    ['..' filesep 'testPrograms'])
+
+levels=-10:10:80;
+% levels=80:10:90;
+nLevels=length(levels);
+
+toneDuration=.2;
+rampDuration=0.002;
+silenceDuration=.02;
+localPSTHbinwidth=0.001;
+
+% Use only the first frequency in the GUI targetFrequency box to defineBF
+targetFrequency=stimulusParameters.targetFrequency(1);
+BFlist=targetFrequency;
+
+AN_HSRonset=zeros(nLevels,1);
+AN_HSRsaturated=zeros(nLevels,1);
+AN_LSRonset=zeros(nLevels,1);
+AN_LSRsaturated=zeros(nLevels,1);
+CNLSRrate=zeros(nLevels,1);
+CNHSRsaturated=zeros(nLevels,1);
+ICHSRsaturated=zeros(nLevels,1);
+ICLSRsaturated=zeros(nLevels,1);
+vectorStrength=zeros(nLevels,1);
+
+AR=zeros(nLevels,1);
+MOC=zeros(nLevels,1);
+
+% ANoutput=zeros(200,200);
+
+figure(15), clf
+set(gcf,'position',[980   356   401   321])
+figure(5), clf
+ set(gcf,'position', [980 34 400 295])
+drawnow
+
+levelNo=0;
+for leveldB=levels
+    levelNo=levelNo+1;
+
+    % sample rate should be amultiple of the targetFrequency for PSTH below
+    sampleRate=50000;
+    dt=1/sampleRate;
+    period=1/targetFrequency;
+    dt=dt*(dt/period)*round(period/dt);
+
+    fprintf('%4.0f\t', leveldB)
+    amp=28e-6*10^(leveldB/20);
+
+    time=dt:dt:toneDuration;
+    rampTime=dt:dt:rampDuration;
+    ramp=[0.5*(1+cos(2*pi*rampTime/(2*rampDuration)+pi)) ...
+        ones(1,length(time)-length(rampTime))];
+    ramp=ramp.*fliplr(ramp);
+
+    silence=zeros(1,round(silenceDuration/dt));
+
+    % create signal (leveldB/ targetFrequency)
+    inputSignal=amp*sin(2*pi*targetFrequency'*time);
+    inputSignal= ramp.*inputSignal;
+    inputSignal=[silence inputSignal];
+
+    %% run the model
+    AN_spikesOrProbability='spikes';
+    MAPparamsName=experiment.name;
+    showPlotsAndDetails=0;
+
+    global ANoutput CNoutput ICoutput ICmembraneOutput tauCas
+    global ARattenuation MOCattenuation
+    
+    MAP1_14(inputSignal, 1/dt, targetFrequency, ...
+        MAPparamsName, AN_spikesOrProbability);
+
+    nTaus=length(tauCas);
+
+    %LSR (same as HSR if no LSR fibers present)
+    [nANFibers nTimePoints]=size(ANoutput);
+    dt=dt* length(inputSignal)/nTimePoints;
+
+    numLSRfibers=nANFibers/nTaus;
+    numHSRfibers=numLSRfibers;
+
+    LSRspikes=ANoutput(1:numLSRfibers,:);
+    PSTH=UTIL_makePSTH(LSRspikes, dt, localPSTHbinwidth);
+    PSTHLSR=mean(PSTH,1)/localPSTHbinwidth;  % across fibers rates
+    PSTHtime=localPSTHbinwidth:localPSTHbinwidth:...
+        localPSTHbinwidth*length(PSTH);
+    AN_LSRonset(levelNo)= max(PSTHLSR); % peak in 5 ms window
+    AN_LSRsaturated(levelNo)= mean(PSTHLSR(round(length(PSTH)/2):end));
+
+    % HSR
+    HSRspikes= ANoutput(end- numHSRfibers+1:end, :);
+    PSTH=UTIL_makePSTH(HSRspikes, dt, localPSTHbinwidth);
+    PSTH=mean(PSTH,1)/localPSTHbinwidth; % sum across fibers (HSR only)
+    AN_HSRonset(levelNo)= max(PSTH);
+    AN_HSRsaturated(levelNo)= mean(PSTH(round(length(PSTH)/2): end));
+
+    figure(5), subplot(2,2,2)
+    hold off, bar(PSTHtime,PSTH, 'b')
+    hold on,  bar(PSTHtime,PSTHLSR,'r')
+    ylim([0 1000])
+xlim([0 length(PSTH)*localPSTHbinwidth])
+    
+    % AN - CV
+    %  CV is computed 5 times. Use the middle one (3) as most typical
+    cvANHSR=  UTIL_CV(HSRspikes, dt);
+
+    % AN - vector strength
+    PSTH=sum(HSRspikes);
+    [PH, binTimes]=UTIL_periodHistogram...
+        (PSTH, dt, targetFrequency);
+    VS=UTIL_vectorStrength(PH);
+    vectorStrength(levelNo)=VS;
+    disp(['sat rate= ' num2str(AN_HSRsaturated(levelNo)) ...
+        ';   phase-locking VS = ' num2str(VS)])
+    title(['AN HSR: CV=' num2str(cvANHSR(3),'%5.2f') ...
+        'VS=' num2str(VS,'%5.2f')])
+
+    % CN - first-order neurons
+
+    % CN LSR
+    [nCNneurons c]=size(CNoutput);
+    nLSRneurons=round(nCNneurons/nTaus);
+    CNLSRspikes=CNoutput(1:nLSRneurons,:);
+    PSTH=UTIL_makePSTH(CNLSRspikes, dt, localPSTHbinwidth);
+    PSTH=sum(PSTH)/nLSRneurons;
+    CNLSRrate(levelNo)=mean(PSTH(round(length(PSTH)/2):end))/localPSTHbinwidth;
+
+    %CN HSR
+    MacGregorMultiHSRspikes=...
+        CNoutput(end-nLSRneurons:end,:);
+    PSTH=UTIL_makePSTH(MacGregorMultiHSRspikes, dt, localPSTHbinwidth);
+    PSTH=sum(PSTH)/nLSRneurons;
+    PSTH=mean(PSTH,1)/localPSTHbinwidth; % sum across fibers (HSR only)
+
+    CNHSRsaturated(levelNo)=mean(PSTH(length(PSTH)/2:end));
+
+    figure(5), subplot(2,2,3)
+    bar(PSTHtime,PSTH)
+    ylim([0 1000])
+    xlim([0 length(PSTH)*localPSTHbinwidth])
+    cvMMHSR= UTIL_CV(MacGregorMultiHSRspikes, dt);
+    title(['CN    CV= ' num2str(cvMMHSR(3),'%5.2f')])
+
+    % IC LSR
+    [nICneurons c]=size(ICoutput);
+    nLSRneurons=round(nICneurons/nTaus);
+    ICLSRspikes=ICoutput(1:nLSRneurons,:);
+    PSTH=UTIL_makePSTH(ICLSRspikes, dt, localPSTHbinwidth);
+    ICLSRsaturated(levelNo)=mean(PSTH(round(length(PSTH)/2):end))/localPSTHbinwidth;
+
+    %IC HSR
+    MacGregorMultiHSRspikes=...
+        ICoutput(end-nLSRneurons:end,:);
+    PSTH=UTIL_makePSTH(MacGregorMultiHSRspikes, dt, localPSTHbinwidth);
+    PSTH=sum(PSTH)/nLSRneurons;
+    PSTH=mean(PSTH,1)/localPSTHbinwidth; % sum across fibers (HSR only)
+
+    ICHSRsaturated(levelNo)=mean(PSTH(length(PSTH)/2:end));
+
+    AR(levelNo)=min(ARattenuation);
+    MOC(levelNo)=min(MOCattenuation(length(MOCattenuation)/2:end));
+
+    time=dt:dt:dt*size(ICmembraneOutput,2);
+    figure(5), subplot(2,2,4)
+    plot(time,ICmembraneOutput(2, 1:end),'k')
+    ylim([-0.07 0])
+    xlim([0 max(time)])
+    title(['IC  ' num2str(leveldB,'%4.0f') 'dB'])
+    drawnow
+    
+    figure(5), subplot(2,2,1)
+    plot(20*log10(MOC), 'k'),
+    title(' MOC'), ylabel('dB attenuation')
+    ylim([-30 0])
+
+
+end % level
+figure(5), subplot(2,2,1)
+    plot(levels,20*log10(MOC), 'k'),
+    title(' MOC'), ylabel('dB attenuation')
+    ylim([-30 0])
+xlim([0 max(levels)])
+
+fprintf('\n')
+toneDuration=2;
+rampDuration=0.004;
+silenceDuration=.02;
+nRepeats=200;   % no. of AN fibers
+fprintf('toneDuration  %6.3f\n', toneDuration)
+fprintf(' %6.0f  AN fibers (repeats)\n', nRepeats)
+fprintf('levels')
+fprintf('%6.2f\t', levels)
+fprintf('\n')
+
+
+% ---------------------------------------------------- display parameters
+
+figure(15), clf
+set(gcf,'position',[1000   356   381   321])
+nRows=2; nCols=2;
+
+% AN rate - level ONSET functions
+subplot(nRows,nCols,1)
+plot(levels,AN_LSRonset,'ro'), hold on
+plot(levels,AN_HSRonset,'ko'), hold off
+ylim([0 1000]),  xlim([min(levels) max(levels)])
+ttl=['tauCa= ' num2str(IHCpreSynapseParams.tauCa)];
+title( ttl)
+xlabel('level dB SPL'), ylabel('peak rate (sp/s)'), grid on
+text(0, 800, 'AN onset', 'fontsize', 16)
+
+% AN rate - level ADAPTED function
+subplot(nRows,nCols,2)
+plot(levels,AN_LSRsaturated, 'ro'), hold on
+plot(levels,AN_HSRsaturated, 'ko'), hold off
+ylim([0 400])
+set(gca,'ytick',0:50:300)
+xlim([min(levels) max(levels)])
+set(gca,'xtick',[levels(1):20:levels(end)])
+%     grid on
+ttl=[   'spont=' num2str(mean(AN_HSRsaturated(1,:)),'%4.0f')...
+    '  sat=' num2str(mean(AN_HSRsaturated(end,1)),'%4.0f')];
+title( ttl)
+xlabel('level dB SPL'), ylabel ('adapted rate (sp/s)')
+text(0, 340, 'AN adapted', 'fontsize', 16), grid on
+
+% CN rate - level ADAPTED function
+subplot(nRows,nCols,3)
+plot(levels,CNLSRrate, 'ro'), hold on
+plot(levels,CNHSRsaturated, 'ko'), hold off
+ylim([0 400])
+set(gca,'ytick',0:50:300)
+xlim([min(levels) max(levels)])
+set(gca,'xtick',[levels(1):20:levels(end)])
+%     grid on
+ttl=[   'spont=' num2str(mean(CNHSRsaturated(1,:)),'%4.0f') '  sat=' ...
+    num2str(mean(CNHSRsaturated(end,1)),'%4.0f')];
+title( ttl)
+xlabel('level dB SPL'), ylabel ('adapted rate (sp/s)')
+text(0, 350, 'CN', 'fontsize', 16), grid on
+
+% IC rate - level ADAPTED function
+subplot(nRows,nCols,4)
+plot(levels,ICLSRsaturated, 'ro'), hold on
+plot(levels,ICHSRsaturated, 'ko'), hold off
+ylim([0 400])
+set(gca,'ytick',0:50:300)
+xlim([min(levels) max(levels)])
+set(gca,'xtick',[levels(1):20:levels(end)]), grid on
+
+ttl=['spont=' num2str(mean(ICHSRsaturated(1,:)),'%4.0f') ...
+    '  sat=' num2str(mean(ICHSRsaturated(end,1)),'%4.0f')];
+title( ttl)
+xlabel('level dB SPL'), ylabel ('adapted rate (sp/s)')
+text(0, 350, 'IC', 'fontsize', 16)
+set(gcf,'name',' AN CN IC rate/level')
+
+UTIL_showStruct(IHCpreSynapseParams, 'IHCpreSynapseParams')
+UTIL_showStruct(AN_IHCsynapseParams, 'AN_IHCsynapseParams')
+
+fprintf('\n')
+disp('levels vectorStrength')
+fprintf('%3.0f \t %6.4f \n', [levels; vectorStrength'])
+fprintf('\n')
+fprintf('Phase locking, max vector strength= %6.4f\n\n',...
+    max(vectorStrength))
+
+allData=[ levels'  AN_HSRonset AN_HSRsaturated...
+    AN_LSRonset AN_LSRsaturated ...
+    CNHSRsaturated CNLSRrate...
+    ICHSRsaturated ICLSRsaturated];
+fprintf('\n levels \tANHSR Onset \tANHSR adapted\tANLSR Onset \tANLSR adapted\tCNHSR\tCNLSR\tICHSR  \tICLSR \n');
+UTIL_printTabTable(round(allData))
+fprintf('VS (phase locking)= \t%6.4f\n\n',...
+    max(vectorStrength))
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/testBM.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,160 @@
+function testBM (BMlocations, paramsName)
+% testBM generates input output functions for DRNL model for any number
+% of locations.
+% Computations are bast on a single channel model (channelBFs=BF)
+% peak displacement (peakAmp) is measured.
+%  if DRNLParams.useMOC is chosen, the full model is run (slow)
+%  otherwise only DRNL is computed.
+% Tuning curves are generated based on a range of frequencies reletove to
+% the BF of the location.
+%
+
+global    DRNLParams
+
+savePath=path;
+
+addpath (['..' filesep 'utilities'],['..' filesep 'MAP'])
+
+levels=-10:10:90;   nLevels=length(levels);
+% levels= 50;   nLevels=length(levels);
+
+relativeFrequencies=[0.25    .5   .75  1  1.25 1.5    2];
+relativeFrequencies=1;
+
+% refBMdisplacement is the displacement of the BM at threshold
+% 1 nm disp at  threshold (9 kHz, Ruggero)
+refBMdisplacement= 1e-8;            % adjusted for 10 nm at 1 kHz
+
+toneDuration=.200;
+rampDuration=0.01;
+silenceDuration=0.01;
+
+sampleRate=30000;
+
+dbstop if error
+figure(3), clf
+% set(gcf,'position',[276    33   331   645])
+set(gcf,'name','DRNL - BM')
+
+finalSummary=[];
+nBFs=length(BMlocations);
+BFno=0; plotCount=0;
+for BF=BMlocations
+    BFno=BFno+1;
+    plotCount=plotCount+nBFs;
+    stimulusFrequencies=BF* relativeFrequencies;
+    nFrequencies=length(stimulusFrequencies);
+
+    peakAmpBM=zeros(nLevels,nFrequencies);
+    peakAmpBMdB=NaN(nLevels,nFrequencies);
+    peakEfferent=NaN(nLevels,nFrequencies);
+    peakAREfferent=NaN(nLevels,nFrequencies);
+
+
+    levelNo=0;
+    for leveldB=levels
+        disp(['level= ' num2str(leveldB)])
+        levelNo=levelNo+1;
+
+        freqNo=0;
+        for frequency=stimulusFrequencies
+            freqNo=freqNo+1;
+
+            % Generate stimuli
+            globalStimParams.FS=sampleRate;
+            globalStimParams.overallDuration=...
+                toneDuration+silenceDuration;  % s
+            stim.phases='sin';
+            stim.type='tone';
+            stim.toneDuration=toneDuration;
+            stim.frequencies=frequency;
+            stim.amplitudesdB=leveldB;
+            stim.beginSilence=silenceDuration;
+            stim.rampOnDur=rampDuration;
+            % no offset ramp
+            stim.rampOffDur=rampDuration;
+            doPlot=0;
+            inputSignal=stimulusCreate(globalStimParams, stim, doPlot);
+            inputSignal=inputSignal(:,1)';
+
+            %% run the model
+            MAPparamsName=paramsName;
+            AN_spikesOrProbability='probability';
+            % spikes are slow but can be used to study MOC using IC units
+            AN_spikesOrProbability='spikes';
+
+            global DRNLoutput MOCattenuation ARattenuation
+            MAP1_14(inputSignal, sampleRate, BF, ...
+                MAPparamsName, AN_spikesOrProbability);
+
+            DRNLresponse=DRNLoutput;
+            peakAmp=max(max(...
+                DRNLresponse(:, end-round(length(DRNLresponse)/2):end)));
+            peakAmpBM(levelNo,freqNo)=peakAmp;
+            peakAmpBMdB(levelNo,freqNo)=...
+                20*log10(peakAmp/refBMdisplacement);
+            peakEfferent(levelNo,freqNo)=min(min(MOCattenuation));
+            peakAREfferent(levelNo,freqNo)=min(min(ARattenuation));
+
+        end  % tone frequency
+    end  % level
+
+    %% analyses results and plot
+
+    % BM I/O plot (top panel)
+    figure(3)
+    subplot(3,nBFs,BFno), cla
+    plot(levels,peakAmpBMdB, 'linewidth',2)
+    hold on, plot(levels, repmat(refBMdisplacement,1,length(levels)))
+    hold off
+    title(['BF=' num2str(BF,'%5.0f') ' - ' paramsName])
+    xlabel('level')
+    %     set(gca,'xtick',levels),  grid on
+    if length(levels)>1,xlim([min(levels) max(levels)]), end
+    ylabel(['dB re:' num2str(refBMdisplacement,'%6.1e') 'm'])
+    ylim([-20 50])
+    set(gca,'ytick',[-10 0 10 20 40])
+    grid on
+    %     legend({num2str(stimulusFrequencies')}, 'location', 'EastOutside')
+    UTIL_printTabTable([levels' peakAmpBMdB], ...
+        num2str([0 stimulusFrequencies]','%5.0f'), '%5.0f')
+    finalSummary=[finalSummary peakAmpBMdB];
+
+    % Tuning curve
+    if length(relativeFrequencies)>2
+        figure(3), subplot(3,nBFs, nBFs+BFno)
+        %         contour(stimulusFrequencies,levels,peakAmpBM,...
+        %             [refBMdisplacement refBMdisplacement],'r')
+        contour(stimulusFrequencies,levels,peakAmpBM,...
+            refBMdisplacement.*[1 5 10 50 100])
+        title(['tuning curve at ' num2str(refBMdisplacement) 'm']);
+        ylabel('level (dB) at reference')
+        xlim([100 10000])
+        grid on
+        hold on
+        set(gca,'xscale','log')
+    end
+
+
+    % MOC contribution
+    figure(3)
+    subplot(3,nBFs,2*nBFs+BFno), cla
+    plot(levels,20*log10(peakEfferent), 'linewidth',2)
+    ylabel('MOC (dB attenuation)'), xlabel('level')
+    title(['peak MOC: model= ' AN_spikesOrProbability])
+    grid on
+    if length(levels)>1, xlim([min(levels) max(levels)]), end
+
+    % AR contribution
+    hold on
+    plot(levels,20*log10(peakAREfferent), 'r')
+    hold off
+
+end % best frequency
+
+UTIL_showStructureSummary(DRNLParams, 'DRNLParams', 10)
+
+    UTIL_printTabTable([levels' finalSummary], ...
+        num2str([0 stimulusFrequencies]','%5.0f'), '%5.0f')
+
+path(savePath);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/testFM.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,247 @@
+function testFM(showPSTHs)
+%   specify whether you want AN 'probability' or 'spikes'
+%       spikes is more realistic but takes longer
+%       refractory effect is included only for spikes
+%
+
+% specify the AN ANresponse bin width (normally 1 ms).
+%      This can influence the measure of the AN onset rate based on the
+%      largest bin in the ANresponse
+%
+% Demonstration is based on Harris and Dallos
+
+global experiment  stimulusParameters
+global inputStimulusParams outerMiddleEarParams DRNLParams 
+global IHC_VResp_VivoParams IHCpreSynapseParams  AN_IHCsynapseParams
+
+dbstop if error
+% masker and probe levels are relative to this threshold
+thresholdAtCF=10; % dB SPL
+thresholdAtCF=5; % dB SPL
+
+if nargin<1, showPSTHs=1;end
+
+sampleRate=50000;
+
+% fetch BF from GUI: use only the first target frequency
+BFlist=stimulusParameters.targetFrequency(1);
+maskerFrequency=BFlist;
+maskerDuration=.1;
+
+targetFrequency=maskerFrequency;
+probeLeveldB=20+thresholdAtCF;	% H&D use 20 dB SL/ TMC uses 10 dB SL
+probeDuration=0.008; % HD use 15 ms probe (fig 3).
+probeDuration=0.015; % HD use 15 ms probe (fig 3).
+
+rampDuration=.001;  % HD use 1 ms linear ramp
+initialSilenceDuration=0.02;
+finalSilenceDuration=0.05;      % useful for showing recovery
+
+maskerLevels=[-80   10 20 30 40 60 ] + thresholdAtCF;
+% maskerLevels=[-80   40 60 ] + thresholdAtCF;
+
+dt=1/sampleRate;
+
+figure(7), clf
+set(gcf,'position',[613    36   360   247])
+set(gcf,'name', ['forward masking: thresholdAtCF=' num2str(thresholdAtCF)])
+
+if showPSTHs
+    figure(8), clf
+    set(gcf,'name', 'Harris and Dallos simulation')
+    set(gcf,'position',[980    36   380   249])
+end
+
+% Plot Harris and Dallos result for comparison
+gapDurations=[0.001	0.002	0.005	0.01	0.02	0.05	0.1	0.3];
+HDmaskerLevels=[+10	+20	+30	+40	+60];
+HDresponse=[
+    1 1 1 1 1 1 1 1;
+    0.8  	0.82	0.81	0.83	0.87	0.95	1	    1;
+    0.48	0.5	    0.54	0.58	0.7	    0.85	0.95	1;
+    0.3	    0.31	0.35	0.4	    0.5	    0.68	0.82	0.94;
+    0.2 	0.27	0.27	0.29	0.42	0.64	0.75	0.92;
+    0.15	0.17	0.18	0.23	0.3	     0.5	0.6	    0.82];
+
+figure(7)
+semilogx(gapDurations,HDresponse,'o'), hold on
+legend(strvcat(num2str(maskerLevels')),'location','southeast')
+title([ 'masker dB: ' num2str(HDmaskerLevels)])
+
+%% Run the trials
+maxProbeResponse=0;
+levelNo=0;
+resultsMatrix=zeros(length(maskerLevels), length(gapDurations));
+summaryFiringRates=[];
+
+% initial silence
+time=dt: dt: initialSilenceDuration;
+initialSilence=zeros(1,length(time));
+
+% probe
+time=dt: dt: probeDuration;
+amp=28e-6*10^(probeLeveldB/20);
+probe=amp*sin(2*pi.*targetFrequency*time);
+% ramps
+% catch rampTime error
+if rampDuration>0.5*probeDuration, rampDuration=probeDuration/2; end
+rampTime=dt:dt:rampDuration;
+% raised cosine ramp
+ramp=[0.5*(1+cos(2*pi*rampTime/(2*rampDuration)+pi)) ...
+    ones(1,length(time)-length(rampTime))];
+%  onset ramp
+probe=probe.*ramp;
+%  offset ramp makes complete ramp for probe
+ramp=fliplr(ramp);
+% apply ramp mask to probe. Probe does not change below
+probe=probe.*ramp;
+
+% final silence
+time=dt: dt: finalSilenceDuration;
+finalSilence=zeros(1,length(time));
+
+PSTHplotCount=0;
+longestSignalDuration=initialSilenceDuration + maskerDuration +...
+    max(gapDurations) + probeDuration + finalSilenceDuration ;
+for maskerLeveldB=maskerLevels
+    levelNo=levelNo+1;
+    allDurations=[];
+    allFiringRates=[];
+
+    %masker
+    time=dt: dt: maskerDuration;
+    masker=sin(2*pi.*maskerFrequency*time);
+    % masker ramps
+    if rampDuration>0.5*maskerDuration
+        % catch ramp duration error
+        rampDuration=maskerDuration/2;
+    end
+    % NB masker ramp (not probe ramp)
+    rampTime=dt:dt:rampDuration;
+    % raised cosine ramp
+    ramp=[0.5*(1+cos(2*pi*rampTime/(2*rampDuration)+pi))...
+        ones(1,length(time)-length(rampTime))];
+    %  onset ramp
+    masker=masker.*ramp;
+    %  offset ramp
+    ramp=fliplr(ramp);
+    % apply ramp
+    masker=masker.*ramp;
+    amp=28e-6*10^(maskerLeveldB/20);
+    maskerPa=amp*masker;
+
+    for gapDuration=gapDurations
+        time=dt: dt: gapDuration;
+        gap=zeros(1,length(time));
+
+        inputSignal=...
+            [initialSilence maskerPa gap probe finalSilence];
+
+        % **********************************  run MAP model
+        
+        global  ANprobRateOutput  tauCas  ...
+
+    MAPparamsName=experiment.name;
+    showPlotsAndDetails=0;
+
+AN_spikesOrProbability='probability';
+
+MAP1_14(inputSignal, 1/dt, targetFrequency, ...
+    MAPparamsName, AN_spikesOrProbability);
+ 
+    [nFibers c]=size(ANprobRateOutput);
+    nLSRfibers=nFibers/length(tauCas);
+            ANresponse=ANprobRateOutput(end-nLSRfibers:end,:);
+            ANresponse=sum(ANresponse)/nLSRfibers;
+    
+        % analyse results
+        probeStart=initialSilenceDuration+maskerDuration+gapDuration;
+        PSTHbinWidth=dt;
+        responseDelay=0.005;
+        probeTimes=probeStart+responseDelay:...
+            PSTHbinWidth:probeStart+probeDuration+responseDelay;
+        probeIDX=round(probeTimes/PSTHbinWidth);
+        probePSTH=ANresponse(probeIDX);
+        firingRate=mean(probePSTH);
+        % NB this only works if you start with the lowest level masker
+        maxProbeResponse=max([maxProbeResponse firingRate]);
+        allDurations=[allDurations gapDuration];
+        allFiringRates=[allFiringRates firingRate];
+        
+        %% show PSTHs
+        if showPSTHs
+            nLevels=length(maskerLevels);
+            nDurations=length(gapDurations);
+            figure(8)
+            PSTHbinWidth=1e-3;
+            PSTH=UTIL_PSTHmaker(ANresponse, dt, PSTHbinWidth);
+            PSTH=PSTH*dt/PSTHbinWidth;
+            PSTHplotCount=PSTHplotCount+1;
+            subplot(nLevels,nDurations,PSTHplotCount)
+            probeTime=PSTHbinWidth:PSTHbinWidth:...
+                PSTHbinWidth*length(PSTH);
+            bar(probeTime, PSTH)
+            if strcmp(AN_spikesOrProbability, 'spikes')
+                ylim([0 500])
+            else
+                ylim([0 500])
+            end
+            xlim([0 longestSignalDuration])
+            grid on
+
+            if PSTHplotCount< (nLevels-1) * nDurations+1
+                set(gca,'xticklabel',[])
+            end
+
+            if ~isequal(mod(PSTHplotCount,nDurations),1)
+                set(gca,'yticklabel',[])
+            else
+                ylabel([num2str(maskerLevels...
+                    (round(PSTHplotCount/nDurations) +1))])
+            end
+
+            if PSTHplotCount<=nDurations
+                title([num2str(1000*gapDurations(PSTHplotCount)) 'ms'])
+            end
+        end % showPSTHs
+
+    end     % gapDurations duration
+    summaryFiringRates=[summaryFiringRates allFiringRates'];
+
+    figure(7), hold on
+    semilogx(allDurations, allFiringRates/maxProbeResponse)
+    ylim([0 1]), hold on
+    ylim([0 inf]), xlim([min(gapDurations) max(gapDurations)])
+    xlim([0.001 1])
+    pause(0.1) % to allow for CTRL/C interrupts
+    resultsMatrix(levelNo,:)=allFiringRates;
+end          % maskerLevel
+
+disp('delay/ rates')
+disp(num2str(round( [1000*allDurations' summaryFiringRates])))
+
+% replot with best adjustment
+% figure(34), clf% use for separate plot
+figure(7), clf
+peakProbe=max(max(resultsMatrix));
+resultsMatrix=resultsMatrix/peakProbe;
+semilogx(gapDurations,HDresponse,'o'), hold on
+title(['FrMsk: probe ' num2str(probeLeveldB)...
+    'dB SL: peakProbe=' num2str(peakProbe,'%5.0f') ' sp/s'])
+xlabel('gap duration (s)'), ylabel ('probe response')
+semilogx(allDurations, resultsMatrix'), ylim([0 1])
+ylim([0 inf]),
+xlim([0.001 1])
+legend(strvcat(num2str(maskerLevels'-thresholdAtCF)), -1)
+
+% ------------------------------------------------- display parameters
+disp(['parameter file was: ' experiment.name])
+fprintf('\n')
+% UTIL_showStruct(inputStimulusParams, 'inputStimulusParams')
+% UTIL_showStruct(outerMiddleEarParams, 'outerMiddleEarParams')
+% UTIL_showStruct(DRNLParams, 'DRNLParams')
+% UTIL_showStruct(IHC_VResp_VivoParams, 'IHC_VResp_VivoParams')
+UTIL_showStruct(IHCpreSynapseParams, 'IHCpreSynapseParams')
+UTIL_showStruct(AN_IHCsynapseParams, 'AN_IHCsynapseParams')
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/testOME.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,85 @@
+function testOME
+
+global experiment
+savePath=path;
+addpath (['..' filesep 'utilities'],['..' filesep 'MAP'])
+
+sampleRate=50000;
+
+dt=1/sampleRate;
+leveldBSPL=80; 		% dB SPL as used by Huber (may trigger AR)
+amp=10^(leveldBSPL/20)*28e-6;
+duration=.05;
+time=dt: dt: duration;
+
+%% Comparison data (human)
+% These data are taken directly from Huber 2001 (Fig. 4)
+HuberFrequencies=[600	  800	 1000	 2000	 3000	4000 6000 8000];
+HuberDisplacementAt80dBSPL=[1.5E-9	1.5E-09	1.5E-09	1.0E-09	7.0E-10	...
+    3.0E-10	2.0E-10	1.0E-10]; % m;
+% HuberVelocityAt80dBSPL= 2*pi*HuberFrequencies.*HuberDisplacementAt80dBSPL;
+
+figure(2), clf, subplot(2,1,1)
+set(2,'position',[5   349   268   327])
+semilogx(HuberFrequencies, 20*log10(HuberDisplacementAt80dBSPL/1e-10),...
+    'ko', 'MarkerFaceColor','k', 'Marker','o', 'markerSize',6)
+% Generate test stimulus .................................................................
+
+%% independent test using discrete frequencies
+peakResponses=[];
+peakTMpressure=[];
+frequencies=[200 400 HuberFrequencies 10000];
+for toneFrequency=frequencies
+    inputSignal=amp*sin(2*pi*toneFrequency*time);
+
+    MAPparamsName=experiment.name;
+    showPlotsAndDetails=0;
+    AN_spikesOrProbability='probability';
+    % switch off AR & MOC (Huber's patients were deaf)
+    paramChanges{1}='OMEParams.rateToAttenuationFactorProb=0;';
+    paramChanges{2}='DRNLParams.rateToAttenuationFactorProb = 0;';
+
+    global OMEoutput  OMEextEarPressure TMoutput ARAttenuation
+    % BF is irrelevant
+    MAP1_14(inputSignal, sampleRate, -1, ...
+        MAPparamsName, AN_spikesOrProbability, paramChanges);
+
+    peakDisplacement=max(OMEoutput(floor(end/2):end));
+    peakResponses=[peakResponses peakDisplacement];
+
+    peakTMpressure=[peakTMpressure max(OMEextEarPressure)];
+    disp([' greatest AR attenuation:   ' num2str(min(ARAttenuation))])
+end
+
+%% Report
+disp('frequency displacement(m)')
+% disp(num2str([frequencies' peakResponses']))
+fprintf('%6.0f \t%10.3e\n',[frequencies' peakResponses']')
+
+% stapes peak displacement
+figure(2), subplot(2,1,1), hold on
+semilogx(frequencies, 20*log10(peakResponses/1e-10), 'r', 'linewidth',4)
+% ylim([1e-11 1e-8])
+xlim([100 10000]), ylim([0 30])
+grid on
+title(['stapes at ' num2str(leveldBSPL) ' (NB deaf)'])
+ylabel('disp: dB re 1e-10m')
+xlabel('stimulus frequency (Hz)')
+legend({'Huber et al','model'},'location','southWest')
+set(gcf,'name','OME')
+
+% external ear resonance
+figure(2), subplot(2,1,2),hold off
+semilogx(frequencies, 20*log10(peakTMpressure/28e-6)-leveldBSPL,...
+    'k', 'linewidth',2)
+xlim([100 10000]) %, ylim([-10 30])
+grid on
+title(['External ear resonances' ])
+ylabel('dB')
+xlabel('frequency')
+set(gcf,'name','OME: external resonances')
+% ---------------------------------------------------------- display parameters
+disp(['parameter file was: ' experiment.name])
+fprintf('\n')
+
+path(savePath);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/testPeriphery.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,161 @@
+function testPeriphery (BMlocations, paramsName)
+% testBM generates input output functions for DRNL model for any number
+% of locations.
+% Computations are bast on a single channel model (channelBFs=BF)
+% peak displacement (peakAmp) is measured.
+%  if DRNLParams.useMOC is chosen, the full model is run (slow)
+%  otherwise only DRNL is computed.
+% Tuning curves are generated based on a range of frequencies reletove to
+% the BF of the location.
+%
+
+global    DRNLParams
+
+savePath=path;
+
+addpath (['..' filesep 'utilities'],['..' filesep 'MAP'])
+
+levels=-10:10:90;   nLevels=length(levels);
+% levels= 50;   nLevels=length(levels);
+
+% relativeFrequencies=[0.25    .5   .75  1  1.25 1.5    2];
+relativeFrequencies=1;
+
+% refBMdisplacement is the displacement of the BM at threshold
+% 1 nm disp at  threshold (9 kHz, Ruggero)
+refBMdisplacement= 1e-8;            % adjusted for 10 nm at 1 kHz
+
+toneDuration=.200;
+rampDuration=0.01;
+silenceDuration=0.01;
+
+sampleRate=30000;
+
+dbstop if error
+figure(3), clf
+% set(gcf,'position',[276    33   331   645])
+set(gcf,'name','DRNL - BM')
+
+finalSummary=[];
+nBFs=length(BMlocations);
+BFno=0; plotCount=0;
+for BF=BMlocations
+    BFno=BFno+1;
+    plotCount=plotCount+nBFs;
+    stimulusFrequencies=BF* relativeFrequencies;
+    nFrequencies=length(stimulusFrequencies);
+
+    peakAmpBM=zeros(nLevels,nFrequencies);
+    peakAmpBMdB=NaN(nLevels,nFrequencies);
+    peakEfferent=NaN(nLevels,nFrequencies);
+    peakAREfferent=NaN(nLevels,nFrequencies);
+
+
+    levelNo=0;
+    for leveldB=levels
+        disp(['level= ' num2str(leveldB)])
+        levelNo=levelNo+1;
+
+        freqNo=0;
+        for frequency=stimulusFrequencies
+            freqNo=freqNo+1;
+
+            % Generate stimuli
+            globalStimParams.FS=sampleRate;
+            globalStimParams.overallDuration=...
+                toneDuration+silenceDuration;  % s
+            stim.type='tone';
+            stim.phases='sin';
+            stim.toneDuration=toneDuration;
+            stim.frequencies=frequency;
+            stim.amplitudesdB=leveldB;
+            stim.beginSilence=silenceDuration;
+            stim.rampOnDur=rampDuration;
+            stim.rampOffDur=rampDuration;
+            doPlot=0;
+            inputSignal=stimulusCreate(globalStimParams, stim, doPlot);
+            inputSignal=inputSignal(:,1)';
+
+            %% run the model
+            MAPparamsName=paramsName;
+            AN_spikesOrProbability='probability';
+            % spikes are slow but can be used to study MOC using IC units
+            % AN_spikesOrProbability='spikes';
+
+            global DRNLoutput MOCattenuation ARattenuation IHCoutput
+            MAP1_14(inputSignal, sampleRate, BF, ...
+                MAPparamsName, AN_spikesOrProbability);
+
+            DRNLresponse=IHCoutput;
+            peakAmp=max(max(...
+                DRNLresponse(:, end-round(length(DRNLresponse)/2):end)));
+            peakAmpBM(levelNo,freqNo)=peakAmp;
+            if peakAmp>0
+            peakAmpBMdB(levelNo,freqNo)=...
+                20*log10(peakAmp/refBMdisplacement);
+            else
+                peakAmpBMdB(levelNo,freqNo)=peakAmp;
+            end
+            peakEfferent(levelNo,freqNo)=min(min(MOCattenuation));
+            peakAREfferent(levelNo,freqNo)=min(min(ARattenuation));
+
+        end  % tone frequency
+    end  % level
+
+    %% analyses results and plot
+
+    % BM I/O plot (top panel)
+    figure(3)
+    subplot(3,nBFs,BFno), cla
+    plot(levels,peakAmpBMdB, 'linewidth',2)
+    hold on, plot(levels, repmat(refBMdisplacement,1,length(levels)))
+    hold off
+    title(['BF=' num2str(BF,'%5.0f') ' - ' paramsName])
+    xlabel('level')
+    %     set(gca,'xtick',levels),  grid on
+    if length(levels)>1,xlim([min(levels) max(levels)]), end
+    ylabel(['dB re:' num2str(refBMdisplacement,'%6.1e') 'm'])
+    ylim([-20 50])
+    set(gca,'ytick',[-10 0 10 20 40])
+    %     legend({num2str(stimulusFrequencies')}, 'location', 'EastOutside')
+    UTIL_printTabTable([levels' peakAmpBMdB], ...
+        num2str([0 stimulusFrequencies]','%5.0f'), '%5.0f')
+    finalSummary=[finalSummary peakAmpBMdB];
+
+    % Tuning curve
+    if length(relativeFrequencies)>2
+        figure(3), subplot(3,nBFs, nBFs+BFno)
+        %         contour(stimulusFrequencies,levels,peakAmpBM,...
+        %             [refBMdisplacement refBMdisplacement],'r')
+        contour(stimulusFrequencies,levels,peakAmpBM,...
+            refBMdisplacement.*[1 5 10 50 100])
+        title(['tuning curve at ' num2str(refBMdisplacement) 'm']);
+        ylabel('level (dB) at reference')
+        xlim([100 10000])
+        hold on
+        set(gca,'xscale','log')
+    end
+
+
+    % MOC contribution
+    figure(3)
+    subplot(3,nBFs,2*nBFs+BFno), cla
+    plot(levels,20*log10(peakEfferent), 'linewidth',2)
+    ylabel('MOC (dB attenuation)'), xlabel('level')
+    title(['peak MOC: model= ' AN_spikesOrProbability])
+    grid on
+    if length(levels)>1, xlim([min(levels) max(levels)]), end
+
+    % AR contribution
+    hold on
+    plot(levels,20*log10(peakAREfferent), 'r')
+    hold off
+
+end % best frequency
+
+UTIL_showStructureSummary(DRNLParams, 'DRNLParams', 10)
+
+    UTIL_printTabTable([levels' finalSummary], ...
+        num2str([0 stimulusFrequencies]','%5.0f'), '%5.0f')
+
+path(savePath);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/testRF.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,295 @@
+function testRF
+% testIHC used either for IHC I/O function or receptive field (doReceptiveFields=1)
+
+global experiment method stimulusParameters expGUIhandles
+global inputStimulusParams  IHC_ciliaParams
+global IHC_VResp_VivoParams IHCpreSynapseParams  AN_IHCsynapseParams
+dbstop if error
+% set(expGUIhandles.pushbuttonStop, 'backgroundColor', [.941 .941 .941])
+
+addpath (['..' filesep 'MAP'], ['..' filesep 'utilities'], ...
+    ['..' filesep 'parameterStore'],  ['..' filesep 'wavFileStore'],...
+    ['..' filesep 'testPrograms'])
+
+targetFrequency=stimulusParameters.targetFrequency(1);
+
+sampleRate=50000;
+doReceptiveFields=1;
+
+toneDuration=.05;
+rampDuration=0.004;
+silenceDuration=.02;
+
+nRepeats=100;   % no. of AN fibers
+
+plotGraphsForIHC=1;
+% number of MacGregor units is set in the parameter file.
+
+if doReceptiveFields
+    % show all receptive field
+    frequencies=targetFrequency*    [  0.5         0.7         0.9     1       1.1         1.3         1.6];
+    levels=0:20:80; nLevels=length(levels);
+    figure(14), clf
+    figure(15), clf
+else
+    % show only I/O function at BF
+    frequencies=targetFrequency;
+    levels=-20:10:90;
+    %         levels=10:.25:13;
+    %         levels=-20:1:-15
+    nLevels=length(levels);
+%     figure(13), clf,
+%     set (gcf, 'name', ['IHC/AN  input/output' num2str(AN_IHCsynapseParams.numFibers) ' repeats'])
+%     drawnow
+end
+nFrequencies=length(frequencies);
+
+IHC_RP_peak=zeros(nLevels,nFrequencies);
+IHC_RP_min=zeros(nLevels,nFrequencies);
+IHC_RP_dc=zeros(nLevels,nFrequencies);
+AN_HSRonset=zeros(nLevels,nFrequencies);
+AN_HSRsaturated=zeros(nLevels,nFrequencies);
+AN_LSRonset=zeros(nLevels,nFrequencies);
+AN_LSRsaturated=zeros(nLevels,nFrequencies);
+CNLSRsaturated=zeros(nLevels,nFrequencies);
+CNHSRsaturated=zeros(nLevels,nFrequencies);
+ICHSRsaturated=zeros(nLevels,nFrequencies);
+ICLSRsaturated=zeros(nLevels,nFrequencies);
+
+
+levelNo=0; PSTHplotCount=0;
+for leveldB=levels
+    fprintf('%4.0f\t', leveldB)
+    levelNo=levelNo+1;
+    amp=28e-6*10^(leveldB/20);
+    
+    freqNo=0;
+    for frequency=frequencies
+
+        paramFunctionName=['method=MAPparams' experiment.name ...
+            '(' num2str(targetFrequency) ');' ];
+        eval(paramFunctionName);  % read parameters afresh each pass
+
+        dt=method.dt;
+        time=dt:dt:toneDuration;        
+        rampTime=dt:dt:rampDuration;
+        ramp=[0.5*(1+cos(2*pi*rampTime/(2*rampDuration)+pi)) ones(1,length(time)-length(rampTime))];
+        ramp=ramp.*fliplr(ramp);
+        
+        silence=zeros(1,round(silenceDuration/dt));
+        
+        toneStartptr=length(silence)+1;
+        toneMidptr=toneStartptr+round(toneDuration/(2*dt)) -1;
+        toneEndptr=toneStartptr+round(toneDuration/dt) -1;
+        
+        % create signal (leveldB/ frequency)
+        freqNo=freqNo+1;
+        inputSignal=amp*sin(2*pi*frequency'*time);
+        inputSignal= ramp.*inputSignal;
+        inputSignal=[silence inputSignal silence];
+        
+        if doReceptiveFields  % receptive field
+            method.plotGraphs=	0; % plot only PSTHs
+        else
+            method.plotGraphs=	plotGraphsForIHC; % show progress
+        end
+        
+        targetChannelNo=1;
+        
+        % force parameters
+         % the number of AN fibers at each BF
+        AN_IHCsynapseParams.numFibers=	nRepeats;
+        AN_IHCsynapseParams. mode= 'spikes';
+        AN_IHCsynapseParams.plotSynapseContents=0;
+        AN_IHCsynapseParams.PSTHbinWidth=.001;
+        
+        method.DRNLSave=1;
+        method.IHC_cilia_RPSave=1;
+        method.PSTHbinWidth=1e-3; % useful 1-ms default for all PSTHs
+        method.AN_IHCsynapseSave=1;
+        method.MacGregorMultiSave=1;
+        method.MacGregorSave=1;
+        method.dt=dt;
+              
+        moduleSequence=[1:8];       
+
+        global ANdt ARAttenuation TMoutput OMEoutput ...
+    DRNLoutput IHC_cilia_output IHCrestingCiliaCond IHCrestingV...
+    IHCoutput ANprobRateOutput ANoutput savePavailable tauCas  ...
+    CNoutput  ICoutput ICmembraneOutput ICfiberTypeRates MOCattenuation
+
+AN_spikesOrProbability='spikes';
+AN_spikesOrProbability='probability';
+MAPparamsName='Normal';
+
+MAP1_14(inputSignal, 1/dt, targetFrequency, ...
+    MAPparamsName, AN_spikesOrProbability);
+        
+        % RP
+        IHC_RPData=IHC_cilia_output;
+        IHC_RPData=IHCoutput(targetChannelNo,:);
+        IHC_RP_peak(levelNo,freqNo)=max(IHC_RPData(toneStartptr:toneEndptr));
+        IHC_RP_min(levelNo,freqNo)=min(IHC_RPData(toneStartptr:toneEndptr));
+        IHC_RP_dc(levelNo,freqNo)=mean(IHC_RPData(toneStartptr:toneEndptr));
+        
+        % AN next
+        AN_IHCsynapseAllData=ANoutput;
+        method.PSTHbinWidth=0.001;
+        
+        nTaus=length(tauCas);
+        numANfibers=size(ANoutput,1);
+        numLSRfibers=numANfibers/nTaus;
+        
+        %LSR (same as HSR if no LSR fibers present)
+        channelPtr1=(targetChannelNo-1)*numANfibers+1;
+        channelPtr2=channelPtr1+numANfibers-1;
+        LSRspikes=AN_IHCsynapseAllData(channelPtr1:channelPtr2,:);
+        method.dt=method.AN_IHCsynapsedt;
+        PSTH=UTIL_PSTHmaker(LSRspikes, method);
+        PSTH=sum(PSTH,1); % sum across fibers (HSR only)
+        PSTHStartptr=round(silenceDuration/method.PSTHbinWidth)+1;
+        PSTHMidptr=PSTHStartptr+round(toneDuration/(2*method.PSTHbinWidth)) -1;
+        PSTHEndptr=PSTHStartptr+round(toneDuration/method.PSTHbinWidth) -1;
+        AN_LSRonset(levelNo,freqNo)=max(max(PSTH))/(method.PSTHbinWidth*method.numANfibers);
+        AN_LSRsaturated(levelNo,freqNo)=sum(PSTH(PSTHMidptr:PSTHEndptr))/(method.numANfibers*toneDuration/2);
+        
+        % HSR
+        channelPtr1=numLSRfibers+(targetChannelNo-1)*method.numANfibers+1;
+        channelPtr2=channelPtr1+method.numANfibers-1;
+        HSRspikes=AN_IHCsynapseAllData(channelPtr1:channelPtr2,:);
+        method.dt=method.AN_IHCsynapsedt;
+        PSTH=UTIL_PSTHmaker(HSRspikes, method);
+        PSTH=sum(PSTH,1); % sum across fibers (HSR only)
+        PSTHStartptr=round(silenceDuration/method.PSTHbinWidth)+1;
+        PSTHMidptr=PSTHStartptr+round(toneDuration/(2*method.PSTHbinWidth)) -1;
+        PSTHEndptr=PSTHStartptr+round(toneDuration/method.PSTHbinWidth) -1;
+        AN_HSRonset(levelNo,freqNo)=max(max(PSTH))/(method.PSTHbinWidth*method.numANfibers);
+        AN_HSRsaturated(levelNo,freqNo)=sum(PSTH(PSTHMidptr:PSTHEndptr))/(method.numANfibers*toneDuration/2);
+        [cvANHSR, cvTimes, allTimeStamps, allISIs]=  UTIL_CV(HSRspikes, method.AN_IHCsynapsedt);
+        
+        PSTHplotCount=PSTHplotCount+1;
+        if doReceptiveFields  % receptive field for HSR only
+            figure(14), set(gcf,'name','AN')
+            plotReceptiveFields(method, PSTH, PSTHplotCount, levels, frequencies)
+            ylim([0 method.numANfibers])
+            xlabel(['CV= ' num2str(max(cvANHSR),'%4.2f')],'fontsize',8)
+        end % doReceptiveFields
+        
+        % CN
+        MacGregorMultiAllData=method.MacGregorMultiData;
+        numLSRfibers=method.McGMultinNeuronsPerBF*length(method.nonlinCF)* (nTaus-1);
+        
+        %LSR (same as HSR if no LSR fibers present)
+        channelPtr1=(targetChannelNo-1)*method.McGMultinNeuronsPerBF+1;
+        channelPtr2=channelPtr1+method.McGMultinNeuronsPerBF-1;
+        MacGregorMultiLSRspikes=MacGregorMultiAllData(channelPtr1:channelPtr2,:);
+        method.dt=method.MacGregorMultidt;
+        PSTH=UTIL_PSTHmaker(MacGregorMultiLSRspikes, method);
+        PSTH=sum(PSTH,1); % sum across fibers (HSR only)
+        PSTHStartptr=round(silenceDuration/method.PSTHbinWidth)+1;
+        PSTHMidptr=PSTHStartptr+round(toneDuration/(2*method.PSTHbinWidth)) -1;
+        PSTHEndptr=PSTHStartptr+round(toneDuration/method.PSTHbinWidth) -1;
+        CNLSRsaturated(levelNo,freqNo)=sum(PSTH(PSTHMidptr:PSTHEndptr));
+        CNLSRsaturated(levelNo,freqNo)=CNLSRsaturated(levelNo,freqNo)...
+            /((toneDuration/2)*method.McGMultinNeuronsPerBF);
+        
+        %HSR
+        channelPtr1=numLSRfibers+(targetChannelNo-1)*method.McGMultinNeuronsPerBF+1;
+        channelPtr2=channelPtr1+method.McGMultinNeuronsPerBF-1;
+        MacGregorMultiHSRspikes=MacGregorMultiAllData(channelPtr1:channelPtr2,:);
+        method.dt=method.MacGregorMultidt;
+        PSTH=UTIL_PSTHmaker(MacGregorMultiHSRspikes, method);
+        PSTH=sum(PSTH,1); % sum across fibers (HSR only)
+        PSTHStartptr=round(silenceDuration/method.PSTHbinWidth)+1;
+        PSTHMidptr=PSTHStartptr+round(toneDuration/(2*method.PSTHbinWidth)) -1;
+        PSTHEndptr=PSTHStartptr+round(toneDuration/method.PSTHbinWidth) -1;
+        CNHSRsaturated(levelNo,freqNo)=sum(PSTH(PSTHMidptr:PSTHEndptr));
+        CNHSRsaturated(levelNo,freqNo)=CNHSRsaturated(levelNo,freqNo)...
+            /((toneDuration/2)*method.McGMultinNeuronsPerBF);
+        [cvMMHSR, cvTimes, allTimeStamps, allISIs]=  UTIL_CV(MacGregorMultiHSRspikes, method.MacGregorMultidt);
+        
+        if doReceptiveFields  % receptive field
+            figure(15), set(gcf,'name','CN HSR input')
+            plotReceptiveFields(method, PSTH, PSTHplotCount, levels, frequencies)
+            ylim([0 method.McGMultinNeuronsPerBF])
+            xlabel(['CV= ' num2str(max(cvMMHSR),'%4.2f')],'fontsize',8)
+        end
+        
+        MacGregorAllData=method.MacGregorData;
+        numLSRfibers=length(method.nonlinCF)* (nTaus-1);
+        
+        %LSR (same as HSR if no LSR fibers present)
+        channelPtr1=targetChannelNo;
+        MacGregorLSR=MacGregorAllData(channelPtr1,:);
+        method.dt=method.MacGregordt;
+        PSTH=UTIL_PSTHmaker(MacGregorLSR, method);
+        PSTHStartptr=round(silenceDuration/method.PSTHbinWidth)+1;
+        PSTHMidptr=PSTHStartptr+round(toneDuration/(2*method.PSTHbinWidth)) -1;
+        PSTHEndptr=PSTHStartptr+round(toneDuration/method.PSTHbinWidth) -1;
+        ICLSRsaturated(levelNo,freqNo)=sum(PSTH(PSTHMidptr:PSTHEndptr));
+        ICLSRsaturated(levelNo,freqNo)=ICLSRsaturated(levelNo,freqNo)/(toneDuration/2);
+        
+        %LSR (same as HSR if no LSR fibers present)
+        channelPtr1=numLSRfibers+targetChannelNo;
+        MacGregorHSR=MacGregorAllData(channelPtr1,:);
+        method.dt=method.MacGregordt;
+        PSTH=UTIL_PSTHmaker(MacGregorHSR, method);
+        PSTHStartptr=round(silenceDuration/method.PSTHbinWidth)+1;
+        PSTHMidptr=PSTHStartptr+round(toneDuration/(2*method.PSTHbinWidth)) -1;
+        PSTHEndptr=PSTHStartptr+round(toneDuration/method.PSTHbinWidth) -1;
+        ICHSRsaturated(levelNo,freqNo)=sum(PSTH(PSTHMidptr:PSTHEndptr));
+        ICHSRsaturated(levelNo,freqNo)=ICHSRsaturated(levelNo,freqNo)/(toneDuration/2);
+        [cvICHSR, cvTimes, allTimeStamps, allISIs]=  UTIL_CV(MacGregorHSR, method.MacGregordt);
+        
+%         if doReceptiveFields  % receptive field
+%             figure(16), set(gcf,'name','IC HSR input')
+%             plotReceptiveFields(method, PSTH, PSTHplotCount, levels, frequencies)
+%             ylim([0 method.McGMultinNeuronsPerBF])
+%             xlabel(['CV= ' num2str(max(cvICHSR),'%4.2f')],'fontsize',8)
+%         end
+    end % frequency
+end % level
+fprintf('\n')
+toneDuration=2;
+rampDuration=0.004;
+silenceDuration=.02;
+nRepeats=200;   % no. of AN fibers
+fprintf('toneDuration  %6.3f\n', toneDuration)
+fprintf(' %6.0f  AN fibers (repeats)\n', nRepeats)
+fprintf('levels')
+fprintf('%6.2f\t', levels)
+fprintf('\n')
+
+
+% ---------------------------------------------------------- display parameters
+disp(['parameter file was: ' experiment.name])
+fprintf('\n')
+UTIL_showStruct(IHC_VResp_VivoParams, 'IHC_cilia_RPParams')
+UTIL_showStruct(IHCpreSynapseParams, 'IHCpreSynapseParams')
+UTIL_showStruct(AN_IHCsynapseParams, 'AN_IHCsynapseParams')
+
+
+
+function plotReceptiveFields(method, PSTH, PSTHplotCount,  levels, frequencies)
+
+% show PSTH for each level/frequency combination
+nLevels=length(levels);
+nFrequencies=length(frequencies);
+
+PSTHtime=method.PSTHbinWidth:method.PSTHbinWidth:method.PSTHbinWidth*length(PSTH);
+subplot(nLevels,nFrequencies,PSTHplotCount)
+bar(PSTHtime, PSTH)
+xlim([0 max(PSTHtime)])
+% write axis labels only at left and bottom
+if PSTHplotCount< (nLevels-1) * nFrequencies+1
+    set(gca,'xticklabel',[])
+end
+if ~isequal(mod(PSTHplotCount,nFrequencies),1)
+    set(gca,'yticklabel',[])
+else
+    ylabel([num2str(levels(round(PSTHplotCount/nFrequencies) +1)) ' dB'])
+end
+% add titles only on top row
+if PSTHplotCount<=nFrequencies
+    title([num2str(frequencies(PSTHplotCount)) ' Hz'])
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/testRP.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,208 @@
+function testRP(BFs,MAPparamsName,paramChanges)
+% testIHC used for IHC I/O function
+
+global experiment method inputStimulusParams
+global stimulusParameters IHC_VResp_VivoParams IHC_cilia_RPParams
+savePath=path;
+addpath (['..' filesep 'utilities'],['..' filesep 'MAP'])
+dbstop if error
+
+figure(4), clf,
+set (gcf, 'name', ['IHC'])
+% set(gcf,'position',[613   354   360   322])
+drawColors='rgbkmcy';
+drawnow
+
+if nargin<3, paramChanges=[]; end
+
+levels=-20:10:100;
+nLevels=length(levels);
+toneDuration=.05;
+silenceDuration=.01;
+sampleRate=50000;
+dt=1/sampleRate;
+
+allIHC_RP_peak=[];
+allIHC_RP_dc=[];
+
+changes{1}=[];
+% changes{1}='IHC_cilia_RPParams.Et=	0.100;';
+% changes{2}='IHC_cilia_RPParams.Et=	0.070;';
+
+for changeNo=1:length(changes)
+    if isempty(changes{1})
+        paramChanges=[];
+    else
+        paramChanges{1}=changes{changeNo};
+    end
+for BFno=1:length(BFs)
+    BF=BFs(BFno);
+    targetFrequency=BF;
+    % OR
+    %Patuzzi and Sellick test (see ELP & AEM, 2006)
+    % targetFrequency=100;
+
+    IHC_RP_peak=zeros(nLevels,1);
+    IHC_RP_min=zeros(nLevels,1);
+    IHC_RP_dc=zeros(nLevels,1);
+
+    time=dt:dt:toneDuration;
+
+    rampDuration=0.004;
+    rampTime=dt:dt:rampDuration;
+    ramp=[0.5*(1+cos(2*pi*rampTime/(2*rampDuration)+pi)) ...
+        ones(1,length(time)-length(rampTime))];
+    ramp=ramp.*fliplr(ramp);
+
+    silence=zeros(1,round(silenceDuration/dt));
+
+    toneStartptr=length(silence)+1;
+    toneMidptr=toneStartptr+round(toneDuration/(2*dt)) -1;
+    toneEndptr=toneStartptr+round(toneDuration/dt) -1;
+
+    levelNo=0;
+    for leveldB=levels
+        levelNo=levelNo+1;
+        % replicate at all levels
+        amp=28e-6*10^(leveldB/20);
+
+        %% create signal (leveldB/ frequency)
+        inputSignal=amp*sin(2*pi*targetFrequency'*time);
+        inputSignal= ramp.*inputSignal;
+        inputSignal=[silence inputSignal silence];
+        inputStimulusParams.sampleRate=1/dt;
+%         global IHC_ciliaParams
+
+        %% disable efferent for fast processing
+        method.DRNLSave=1;
+        method.IHC_cilia_RPSave=1;
+        method.IHCpreSynapseSave=1;
+        method.IHC_cilia_RPSave=1;
+        method.segmentDuration=-1;
+        moduleSequence=1:4;
+
+        %% run the model
+        global  DRNLoutput IHC_cilia_output IHCrestingCiliaCond IHCrestingV...
+            IHCoutput
+        AN_spikesOrProbability='probability';
+
+        MAP1_14(inputSignal, sampleRate, BF, ...
+            MAPparamsName, AN_spikesOrProbability, paramChanges);
+
+        % DRNL
+        DRNLoutput=DRNLoutput;
+        DRNL_peak(levelNo,1)=max(DRNLoutput(toneMidptr:toneEndptr));
+        DRNL_min(levelNo,1)=min(DRNLoutput(toneMidptr:toneEndptr));
+        DRNL_dc(levelNo,1)=mean(DRNLoutput(toneMidptr:toneEndptr));
+
+        % cilia
+        IHC_ciliaData=IHC_cilia_output;
+        IHC_ciliaData=IHC_ciliaData;
+        IHC_cilia_peak(levelNo,1)=...
+            max(IHC_ciliaData(toneMidptr:toneEndptr));
+        IHC_cilia_min(levelNo,1)=...
+            min(IHC_ciliaData(toneMidptr:toneEndptr));
+        IHC_cilia_dc(levelNo,1)=...
+            mean(IHC_ciliaData(toneMidptr:toneEndptr));
+
+        % RP
+        IHC_RPData=IHCoutput;
+        IHC_RPData=IHC_RPData;
+        IHC_RP_peak(levelNo,1)=...
+            max(IHC_RPData(toneMidptr:toneEndptr));
+        IHC_RP_min(levelNo,1)=...
+            min(IHC_RPData(toneMidptr:toneEndptr));
+        IHC_RP_dc(levelNo,1)=...
+            mean(IHC_RPData(toneMidptr:toneEndptr));
+
+    end % level
+
+
+    disp(['parameter file was: ' MAPparamsName])
+    fprintf('\n')
+
+    %% plot DRNL
+    subplot(2,2,1)
+%     referenceDisp= 9e-9*1000/targetFrequency;
+%     plot(levels,20*log10(DRNL_peak/referenceDisp), drawColors(BFno), ...
+%         'linewidth',2), hold on
+    referenceDisp=10e-9;
+    plot(levels,20*log10(DRNL_peak/referenceDisp), drawColors(BFno), ...
+        'linewidth',2), hold on
+    title([' DRNL peak:  ' num2str(BFs) ' Hz'])
+    ylabel ('log10DRNL(m)'), xlabel('dB SPL')
+    xlim([min(levels) max(levels)]), ylim([-10 50])
+    grid on
+
+    %% plot cilia displacement
+    figure(4)
+    subplot(2,2,2)
+    restingIHC_cilia=IHCrestingCiliaCond;
+    plot(levels, IHC_cilia_peak,'k', 'linewidth',2), hold on
+    plot(levels, IHC_cilia_min,'r', 'linewidth',2)
+    hold on,
+    plot([min(levels) max(levels)], ...
+        [restingIHC_cilia restingIHC_cilia], 'g')
+    title(' IHC apical cond.')
+    ylabel ('IHCcilia(conductance)'), xlabel('dB SPL')
+    xlim([min(levels) max(levels)])
+    grid on
+
+    %% plot receptor potentials
+    figure(4)
+    subplot(2,2,3)
+    % RP I/O function min and max
+    restingRP=IHC_RP_peak(1);
+    restingRP=IHCrestingV;
+    toPlot= [fliplr(IHC_RP_min(:,1)') IHC_RP_peak(:,1)'];
+    microPa=   28e-6*10.^(levels/20);
+    microPa=[-fliplr(microPa) microPa];
+    plot(microPa,toPlot, drawColors(BFno), 'linewidth',2)
+    % ylim([0 300])
+
+    %% Dallos and Harris data
+    dallosx=[-0.9	-0.1	-0.001	0.001	0.01	0.9];
+    dallosy=[-8	-7.8	-6.5	11	16.5	22]/1000 + restingRP;
+    hold on, plot(dallosx,dallosy, 'o')
+    plot([-1 1], [restingRP restingRP], 'r')
+    title(' Dallos(86) data at 800 Hz')
+    ylabel ('receptor potential(V)'), xlabel('Pa')
+    ylim([-0.08 -0.02]), xlim([-1 1])
+    grid on
+
+    %% RP I/O function min and max
+    figure(4)
+    subplot(2,2,4)
+    restingRP=IHC_RP_peak(1);
+    peakRP=max(IHC_RP_peak);
+    plot(levels, IHC_RP_peak,drawColors(BFno), 'linewidth',2)
+    hold on
+    plot(levels, IHC_RP_dc, [drawColors(BFno) ':'], 'linewidth',2)
+    hold on,
+    plot([min(levels) max(levels)], [restingRP restingRP], 'r')
+    xlim([min(levels) max(levels)])
+    grid on
+    title(['Et= ' num2str(IHC_cilia_RPParams.Et) ':  RP (AC- / DC:'])
+    ylabel ('RP(V)'), xlabel('dB SPL')
+    ylim([-0.08 -0.02])
+    allIHC_RP_peak=[allIHC_RP_peak IHC_RP_peak];
+    allIHC_RP_dc=[allIHC_RP_dc IHC_RP_dc];
+
+    fprintf('level\t peak\t DC\n')
+    UTIL_printTabTable([levels' IHC_RP_peak IHC_RP_dc])
+    % disp(['restingIHC_cilia= ' num2str(restingIHC_cilia)])
+    fprintf('peakRP= \t%6.3f', peakRP)
+    fprintf('\nrestingRP= \t%6.3f', restingRP)
+    fprintf('\ndifference= \t%6.3f\n', (peakRP-restingRP))
+    drawnow
+end
+end
+% UTIL_showStruct(IHC_VResp_VivoParams, 'IHC_VResp_VivoParams')
+UTIL_showStruct(IHC_cilia_RPParams, 'IHC_cilia_RPParams')
+    fprintf('level\t peak\n')
+    UTIL_printTabTable([levels' allIHC_RP_peak])
+    fprintf('level\t DC\n')
+    UTIL_printTabTable([levels' allIHC_RP_dc])
+
+path(savePath);
+disp(paramChanges)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multithreshold 1.46/testSynapse.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,88 @@
+function testSynapse
+% testSynapse tracks the quantity of available transmitter vesicles
+%  the computations are single channel using the first frequency
+%  in the targetFrequency box of the expGUI.
+% For, speed this function uses only probability and HSR fibers.
+% This cannot be changed because of the way AN_IHCsynapse is coded.This).
+
+global experiment  method IHCpreSynapseParams
+global  AN_IHCsynapseParams  stimulusParameters
+savePath=path;
+addpath (['..' filesep 'utilities'],['..' filesep 'MAP'])
+
+figure(6),clf
+plotColors='rbgkrbgkrbgkrbgkrbgkrbgk';
+set(gcf,'position',[5    32   264   243])
+
+sampleRate=5e4; dt=1/sampleRate;
+
+maskerLevels=-0:10:100;
+
+BFlist=stimulusParameters.targetFrequency(1);
+targetFrequency=stimulusParameters.targetFrequency;
+targetFrequency=targetFrequency(1); % only one frequency used
+
+showParams=0;
+useEfferent=0;  % no efferent
+
+silenceDuration=0.005;
+maskerDuration=0.1;
+recoveryDuration=0.15;
+rampDuration=0.004;
+
+maskerTime=dt:dt:maskerDuration;
+
+rampTime=dt:dt:rampDuration;
+ramp=[0.5*(1+cos(2*pi*rampTime/(2*rampDuration)+pi)) ...
+    ones(1,length(maskerTime)-length(rampTime))];
+ramp=ramp.*fliplr(ramp);
+
+initialSilence=zeros(1,round(silenceDuration/dt));
+recoverySilence=zeros(1,round(recoveryDuration/dt));
+
+signal=sin(2*pi*targetFrequency'*maskerTime);
+signal= ramp.*signal;
+signal=[initialSilence signal  recoverySilence];
+
+levelCount=0;
+qtMatrix=[];
+for leveldB=maskerLevels
+    levelCount=levelCount+1;
+
+    amp=28e-6*10^(leveldB/20);
+    inputSignal=amp*signal;
+
+    AN_spikesOrProbability='probability';
+    MAPparamsName=experiment.name;
+    showPlotsAndDetails=0;
+
+    global savePavailable
+   
+        MAP1_14(inputSignal, 1/dt, targetFrequency, ...
+            MAPparamsName, AN_spikesOrProbability);
+
+    % ignore LSR channels (if any) at the top of the matrix
+    qt=savePavailable(end, :);
+
+    synapsedt=dt;
+    time=synapsedt:synapsedt:synapsedt*length(qt);
+
+    figure(6)
+    qtMatrix=[qtMatrix; qt];
+    plot(time,qt,  plotColors(levelCount))
+    hold on
+    xlim([0 max(time)])
+    ylim([0 AN_IHCsynapseParams.M])
+end
+
+set(gcf,'name','pre-synaptic available transmitter')
+title(['q - available vesicles:' num2str(BFlist) ' Hz'])
+legend(strvcat(num2str(maskerLevels')),'location','southeast')
+legend boxoff
+grid on
+
+figure(88), [c,H]=contour(time, maskerLevels,qtMatrix); clabel(c, H);
+set(gcf,'position',[ 276    31   264   243])
+xlabel('time'), ylabel('maskerLevels')
+
+path(savePath);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/parameterStore/MAPparamsNormal.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,345 @@
+function method=MAPparamsNormal ...
+    (BFlist, sampleRate, showParams)
+% MAPparams<> establishes a complete set of MAP parameters
+% Parameter file names must be of the form <MAPparams> <name>
+%
+% input arguments
+%  BFlist     (optional) specifies the desired list of channel BFs
+%    otherwise defaults set below
+%  sampleRate (optional), default is 50000.
+%  showParams (optional) =1 prints out the complete set of parameters
+% output argument
+%  method passes a miscelleny of values
+
+global inputStimulusParams OMEParams DRNLParams
+global IHC_VResp_VivoParams IHCpreSynapseParams  AN_IHCsynapseParams
+global MacGregorParams MacGregorMultiParams  filteredSACFParams
+global experiment % used by calls from multiThreshold only
+global IHC_cilia_RPParams
+
+currentFile=mfilename;                      % i.e. the name of this mfile
+method.parameterSource=currentFile(10:end); % for the record
+
+switchOffEfferent=0;
+efferentDelay=0.010;
+method.segmentDuration=efferentDelay;
+
+if nargin<3, showParams=0; end
+if nargin<2, sampleRate=50000; end
+if nargin<1 || BFlist(1)<0 % if BFlist= -1, set BFlist to default
+    lowestBF=250; 	highestBF= 8000; 	numChannels=21;
+    % 21 chs (250-8k)includes BFs at 250 500 1000 2000 4000 8000
+    BFlist=round(logspace(log10(lowestBF),log10(highestBF),numChannels));
+end
+% BFlist=1000;
+
+% preserve for backward campatibility
+method.nonlinCF=BFlist; 
+method.dt=1/sampleRate; 
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% set  model parameters
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%  #1 inputStimulus
+inputStimulusParams=[];
+inputStimulusParams.sampleRate= sampleRate; 
+
+%%  #2 outerMiddleEar
+OMEParams=[];  % clear the structure first
+% outer ear resonances band pass filter  [gain lp order  hp]
+OMEParams.externalResonanceFilters=      [ 10 1 1000 4000];
+                                       
+% highpass stapes filter  
+%  Huber gives 2e-9 m at 80 dB and 1 kHz (2e-13 at 0 dB SPL)
+OMEParams.OMEstapesLPcutoff= 1000;
+OMEParams.stapesScalar=	     45e-9;
+
+% Acoustic reflex: maximum attenuation should be around 25 dB Price (1966)
+% i.e. a minimum ratio of 0.056.
+if ~switchOffEfferent
+    % 'spikes' model: AR based on brainstem spiking activity (LSR)
+    OMEParams.rateToAttenuationFactor=0.003;   % * N(all ICspikes)
+%     OMEParams.rateToAttenuationFactor=0;   % * N(all ICspikes)
+    % 'probability model': Ar based on An firing probabilities (LSR)
+    OMEParams.rateToAttenuationFactorProb=0.005;% * N(all ANrates)
+%     OMEParams.rateToAttenuationFactorProb=0;% * N(all ANrates)
+else
+    OMEParams.rateToAttenuationFactor=0;        % 0= off
+    OMEParams.rateToAttenuationFactorProb=0;    % 0= off
+end
+% asymptote should be around 100-200 ms
+OMEParams.ARtau=.05; % AR smoothing function
+% delay must be longer than the segment length
+OMEParams.ARdelay=efferentDelay;  %Moss gives 8.5 ms latency
+OMEParams.ARrateThreshold=0;
+
+%%  #3 DRNL
+DRNLParams=[];  % clear the structure first
+DRNLParams.BFlist=BFlist;
+
+% DRNL nonlinear path
+DRNLParams.a=3e4;     % nonlinear path gain (below compression threshold)
+% DRNLParams.a=0;     % DRNL.a=0 means no OHCs (no nonlinear path)
+
+DRNLParams.b=8e-6;    % *compression threshold raised compression
+% DRNLParams.b=1;    % b=1 means no compression
+
+DRNLParams.c=0.2;     % compression exponent
+% nonlinear filters
+DRNLParams.nonlinCFs=BFlist;
+DRNLParams.nonlinOrder=	3;           % order of nonlinear gammatone filters
+p=0.2895;   q=170;  % human  (% p=0.14;   q=366;  % cat)
+DRNLParams.nlBWs=  p * BFlist + q;
+DRNLParams.p=p;   DRNLParams.q=q;   % save p and q for printing only
+
+% DRNL linear path:
+DRNLParams.g=100;     % linear path gain factor
+% linCF is not necessarily the same as nonlinCF
+minLinCF=153.13; coeffLinCF=0.7341;   % linCF>nonlinBF for BF < 1 kHz
+DRNLParams.linCFs=minLinCF+coeffLinCF*BFlist;
+DRNLParams.linOrder=	3;           % order of linear gammatone filters
+minLinBW=100; coeffLinBW=0.6531;
+DRNLParams.linBWs=minLinBW + coeffLinBW*BFlist; % bandwidths of linear  filters
+
+% DRNL MOC efferents
+DRNLParams.MOCdelay = efferentDelay;            % must be < segment length!
+if ~switchOffEfferent
+    % 'spikes' model: MOC based on brainstem spiking activity (HSR)
+    DRNLParams.rateToAttenuationFactor = .009;  % strength of MOC
+    DRNLParams.rateToAttenuationFactor = .009;  % strength of MOC
+%      DRNLParams.rateToAttenuationFactor = 0;  % strength of MOC
+
+    % 'spikes' model: MOC based on brainstem spiking activity (HSR)
+    DRNLParams.rateToAttenuationFactorProb = .002;  % strength of MOC
+else
+    DRNLParams.rateToAttenuationFactor = 0;     % 0 = MOC off (probability)
+    DRNLParams.rateToAttenuationFactorProb = 0; % 0 = MOC off (spikes)
+end
+DRNLParams.MOCtau =.03;                         % smoothing for MOC
+DRNLParams.MOCrateThreshold =50;                % set to AN rate threshold
+
+
+%% #4 IHC_cilia_RPParams
+
+IHC_cilia_RPParams.tc=	0.0003;   % 0.0003 filter time simulates viscocity
+% IHC_cilia_RPParams.tc=	0.0005;   % 0.0003 filter time simulates viscocity
+IHC_cilia_RPParams.C=	0.05;      % 0.1 scalar (C_cilia ) 
+IHC_cilia_RPParams.u0=	5e-9;       
+IHC_cilia_RPParams.s0=	30e-9;
+IHC_cilia_RPParams.u1=	1e-9;
+IHC_cilia_RPParams.s1=	1e-9;
+
+IHC_cilia_RPParams.Gmax= 5e-9;    % 2.5e-9 maximum conductance (Siemens)
+IHC_cilia_RPParams.Gu0=	1e-9;  % 4.3e-9 fixed apical membrane conductance
+
+%  #5 IHC_RP
+IHC_cilia_RPParams.Cab=	4e-012;         % IHC capacitance (F)
+IHC_cilia_RPParams.Et=	0.100;          % endocochlear potential (V)
+% IHC_cilia_RPParams.Et=	0.070;          % endocochlear potential (V)
+
+IHC_cilia_RPParams.Gk=	2e-008;         % 1e-8 potassium conductance (S)
+IHC_cilia_RPParams.Ek=	-0.08;          % -0.084 K equilibrium potential
+IHC_cilia_RPParams.Rpc=	0.04;           % combined resistances
+
+
+
+%%  #5 IHCpreSynapse
+IHCpreSynapseParams=[];
+IHCpreSynapseParams.GmaxCa=	14e-9;% maximum calcium conductance
+IHCpreSynapseParams.GmaxCa=	13e-9;% maximum calcium conductance
+IHCpreSynapseParams.ECa=	0.066;  % calcium equilibrium potential
+IHCpreSynapseParams.beta=	400;	% determine Ca channel opening
+IHCpreSynapseParams.gamma=	100;	% determine Ca channel opening
+IHCpreSynapseParams.tauM=	0.00005;	% membrane time constant ?0.1ms
+IHCpreSynapseParams.power=	3;
+% reminder: changing z has a strong effect on HF thresholds (like Et)
+IHCpreSynapseParams.z=	    2e42;   % scalar Ca -> vesicle release rate
+
+LSRtauCa=50e-6;            HSRtauCa=85e-6;            % seconds
+% LSRtauCa=35e-6;            HSRtauCa=70e-6;            % seconds
+IHCpreSynapseParams.tauCa= [LSRtauCa HSRtauCa]; %LSR and HSR fiber
+
+%%  #6 AN_IHCsynapse
+% c=kym/(y(l+r)+kl)	(spontaneous rate)
+% c=(approx)  ym/l  (saturated rate)
+AN_IHCsynapseParams=[];             % clear the structure first
+AN_IHCsynapseParams.M=	12;         % maximum vesicles at synapse
+AN_IHCsynapseParams.y=	4;          % depleted vesicle replacement rate
+AN_IHCsynapseParams.y=	6;          % depleted vesicle replacement rate
+
+AN_IHCsynapseParams.x=	30;         % replenishment from re-uptake store
+AN_IHCsynapseParams.x=	60;         % replenishment from re-uptake store
+
+% reduce l to increase saturated rate
+AN_IHCsynapseParams.l=	100; % *loss rate of vesicles from the cleft
+AN_IHCsynapseParams.l=	250; % *loss rate of vesicles from the cleft
+
+AN_IHCsynapseParams.r=	500; % *reuptake rate from cleft into cell
+% AN_IHCsynapseParams.r=	300; % *reuptake rate from cleft into cell
+
+AN_IHCsynapseParams.refractory_period=	0.00075;
+% number of AN fibers at each BF (used only for spike generation)
+AN_IHCsynapseParams.numFibers=	100; 
+AN_IHCsynapseParams.TWdelay=0.004;  % ?delay before stimulus first spike
+
+%%  #7 MacGregorMulti (first order brainstem neurons)
+MacGregorMultiParams=[];
+MacGregorMultiType='chopper'; % MacGregorMultiType='primary-like'; %choose
+switch MacGregorMultiType
+    case 'primary-like'
+        MacGregorMultiParams.nNeuronsPerBF=	10;   % N neurons per BF
+        MacGregorMultiParams.type = 'primary-like cell';
+        MacGregorMultiParams.fibersPerNeuron=4;   % N input fibers
+        MacGregorMultiParams.dendriteLPfreq=200;  % dendritic filter
+        MacGregorMultiParams.currentPerSpike=0.11e-6; % (A) per spike
+        MacGregorMultiParams.Cap=4.55e-9;   % cell capacitance (Siemens)
+        MacGregorMultiParams.tauM=5e-4;     % membrane time constant (s)
+        MacGregorMultiParams.Ek=-0.01;      % K+ eq. potential (V)
+        MacGregorMultiParams.dGkSpike=3.64e-5; % K+ cond.shift on spike,S
+        MacGregorMultiParams.tauGk=	0.0012; % K+ conductance tau (s)
+        MacGregorMultiParams.Th0=	0.01;   % equilibrium threshold (V)
+        MacGregorMultiParams.c=	0.01;       % threshold shift on spike, (V)
+        MacGregorMultiParams.tauTh=	0.015;  % variable threshold tau
+        MacGregorMultiParams.Er=-0.06;      % resting potential (V)
+        MacGregorMultiParams.Eb=0.06;       % spike height (V)
+
+    case 'chopper'
+        MacGregorMultiParams.nNeuronsPerBF=	10;   % N neurons per BF
+        MacGregorMultiParams.type = 'chopper cell';
+        MacGregorMultiParams.fibersPerNeuron=10;  % N input fibers
+        MacGregorMultiParams.fibersPerNeuron=6;  % N input fibers
+
+        MacGregorMultiParams.dendriteLPfreq=50;   % dendritic filter
+        MacGregorMultiParams.currentPerSpike=39e-9; % *per spike
+%         MacGregorMultiParams.currentPerSpike=45e-9; % *per spike
+        
+        MacGregorMultiParams.Cap=1.67e-8; % ??cell capacitance (Siemens)
+        MacGregorMultiParams.tauM=0.002;  % membrane time constant (s)
+        MacGregorMultiParams.Ek=-0.01;    % K+ eq. potential (V)
+        MacGregorMultiParams.dGkSpike=1.33e-4; % K+ cond.shift on spike,S
+        MacGregorMultiParams.tauGk=	0.0001;% K+ conductance tau (s)
+        MacGregorMultiParams.Th0=	0.01; % equilibrium threshold (V)
+        MacGregorMultiParams.c=	0;        % threshold shift on spike, (V)
+        MacGregorMultiParams.tauTh=	0.02; % variable threshold tau
+        MacGregorMultiParams.Er=-0.06;    % resting potential (V)
+        MacGregorMultiParams.Eb=0.06;     % spike height (V)
+        MacGregorMultiParams.PSTHbinWidth=	1e-4;
+end
+
+%%  #8 MacGregor (second-order neuron). Only one per channel
+MacGregorParams=[];                 % clear the structure first
+MacGregorParams.type = 'chopper cell';
+MacGregorParams.fibersPerNeuron=10; % N input fibers
+MacGregorParams.dendriteLPfreq=100; % dendritic filter
+MacGregorParams.currentPerSpike=120e-9;% *(A) per spike
+
+MacGregorParams.Cap=16.7e-9;        % cell capacitance (Siemens)
+MacGregorParams.tauM=0.002;         % membrane time constant (s)
+MacGregorParams.Ek=-0.01;           % K+ eq. potential (V)
+MacGregorParams.dGkSpike=1.33e-4;   % K+ cond.shift on spike,S
+MacGregorParams.tauGk=	0.0003;     % K+ conductance tau (s)
+MacGregorParams.Th0=	0.01;       % equilibrium threshold (V)
+MacGregorParams.c=	0;              % threshold shift on spike, (V)
+MacGregorParams.tauTh=	0.02;       % variable threshold tau
+MacGregorParams.Er=-0.06;           % resting potential (V)
+MacGregorParams.Eb=0.06;            % spike height (V)
+MacGregorParams.debugging=0;        % (special)
+% wideband accepts input from all channels (of same fiber type)
+% use wideband to create inhibitory units
+MacGregorParams.wideband=0;         % special for wideband units
+% MacGregorParams.saveAllData=0;
+
+%%  #9 filteredSACF
+minPitch=	300; maxPitch=	3000; numPitches=60;    % specify lags
+pitches=100*log10(logspace(minPitch/100, maxPitch/100, numPitches));
+filteredSACFParams.lags=1./pitches;     % autocorrelation lags vector
+filteredSACFParams.acfTau=	.003;       % time constant of running ACF
+filteredSACFParams.lambda=	0.12;       % slower filter to smooth ACF
+filteredSACFParams.plotFilteredSACF=1;  % 0 plots unfiltered ACFs
+filteredSACFParams.plotACFs=0;          % special plot (see code)
+%  filteredSACFParams.usePressnitzer=0; % attenuates ACF at  long lags
+filteredSACFParams.lagsProcedure=  'useAllLags';
+% filteredSACFParams.lagsProcedure=  'useBernsteinLagWeights';
+% filteredSACFParams.lagsProcedure=  'omitShortLags';
+filteredSACFParams.criterionForOmittingLags=3;
+
+% checks
+if AN_IHCsynapseParams.numFibers<MacGregorMultiParams.fibersPerNeuron
+    error('MacGregorMulti: too few input fibers for input to MacG unit')
+end
+
+
+%% write all parameters to the command window
+% showParams is currently set at the top of htis function
+if showParams
+    fprintf('\n %%%%%%%%\n')
+    fprintf('\n%s\n', method.parameterSource)
+    fprintf('\n')
+    nm=UTIL_paramsList(whos);
+    for i=1:length(nm)
+        %         eval(['UTIL_showStruct(' nm{i} ', ''' nm{i} ''')'])
+        if ~strcmp(nm(i), 'method')
+            eval(['UTIL_showStructureSummary(' nm{i} ', ''' nm{i} ''', 10)'])
+        end
+    end
+end
+
+
+
+% **********************************************************************  comparison data
+% store individual data here for display on the multiThreshold GUI (if used)
+% the final value in each vector is an identifier (BF or duration))
+if isstruct(experiment)
+    switch experiment.paradigm
+        case {'IFMC','IFMC_8ms'}
+            % based on MPa
+            comparisonData=[
+                66	51	49	48	46	45	54	250;
+                60	54	46	42	39	49	65	500;
+                64	51	38	32	33	59	75	1000;
+                59	51	36	30	41	81	93	2000;
+                71	63	53	44	36	76	95	4000;
+                70	64	43	35	35	66	88	6000;
+                110	110	110	110	110	110	110	8000;
+                ];
+            if length(BFlist)==1 && ~isempty(comparisonData)
+                availableFrequencies=comparisonData(:,end)';
+                findRow= find(BFlist==availableFrequencies);
+                if ~isempty (findRow)
+                    experiment.comparisonData=comparisonData(findRow,:);
+                end
+            end
+
+        case {'TMC','TMC_8ms'}
+            % based on MPa
+            comparisonData=[
+                48	58	63	68	75	80	85	92	99	250;
+                33	39	40	49	52	61	64	77	79	500;
+                39	42	50	81	83	92	96	97	110	1000;
+                24	26	32	37	46	51	59	71	78	2000;
+                65	68	77	85	91	93	110	110	110	4000;
+                20	19	26	44	80	95	96	110	110	6000;
+                ];
+            if length(BFlist)==1 && ~isempty(comparisonData)
+                availableFrequencies=comparisonData(:,end)';
+                findRow= find(BFlist==availableFrequencies);
+                if ~isempty (findRow)
+                    experiment.comparisonData=comparisonData(findRow,:);
+                end
+            end
+
+        case { 'absThreshold',  'absThreshold_8'}
+            % MPa thresholds
+            experiment.comparisonData=[
+                32	26	16	18	22	22 0.008;
+                16	13	6	9	15	11 0.500
+                ];
+
+
+        otherwise
+            experiment.comparisonData=[];
+    end
+end
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/testPrograms/showMAP.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,240 @@
+function showMAP (options)
+% defaults
+%     options.showModelParameters=1;
+%     options.showModelOutput=1;
+%     options.printFiringRates=1;
+%     options.showACF=1;
+%     options.showEfferent=1;
+
+dbstop if warning
+
+global dt ANdt saveAN_spikesOrProbability savedBFlist saveMAPparamsName...
+    savedInputSignal TMoutput OMEoutput ARattenuation ...
+    DRNLoutput IHC_cilia_output IHCrestingCiliaCond IHCrestingV...
+    IHCoutput ANprobRateOutput ANoutput savePavailable tauCas  ...
+    CNoutput  ICoutput ICmembraneOutput ICfiberTypeRates MOCattenuation
+
+restorePath=path;
+addpath ( ['..' filesep 'utilities'], ['..' filesep 'parameterStore'])
+
+if nargin<1
+    options.showModelParameters=1;
+    options.showModelOutput=1;
+    options.printFiringRates=1;
+    options.showACF=1;
+    options.showEfferent=1;
+end
+
+if options.showModelParameters
+    % Read parameters from MAPparams<***> file in 'parameterStore' folder
+    %  and print out all parameters
+    cmd=['MAPparams' saveMAPparamsName ...
+        '(-1, 1/dt, 1);'];
+    eval(cmd);
+end
+
+if options.printFiringRates
+    %% print summary firing rates
+    fprintf('\n\n')
+    disp('summary')
+    disp(['AR: ' num2str(min(ARattenuation))])
+    disp(['MOC: ' num2str(min(min(MOCattenuation)))])
+    nANfiberTypes=length(tauCas);
+    if strcmp(saveAN_spikesOrProbability, 'spikes')
+        nANfibers=size(ANoutput,1);
+        nHSRfibers=nANfibers/nANfiberTypes;
+        duration=size(TMoutput,2)*dt;
+        disp(['AN: ' num2str(sum(sum(ANoutput(end-nHSRfibers+1:end,:)))/...
+            (nHSRfibers*duration))])
+        
+        nCNneurons=size(CNoutput,1);
+        nHSRCNneuronss=nCNneurons/nANfiberTypes;
+        disp(['CN: ' num2str(sum(sum(CNoutput(end-nHSRCNneuronss+1:end,:)))...
+            /(nHSRCNneuronss*duration))])
+        disp(['IC: ' num2str(sum(sum(ICoutput)))])
+        disp(['IC by type: ' num2str(mean(ICfiberTypeRates,2)')])
+    else
+        disp(['AN: ' num2str(mean(mean(ANprobRateOutput)))])
+    end
+end
+
+
+%% figure (99) summarises main model output
+if options.showModelOutput
+    plotInstructions.figureNo=99;
+    signalRMS=mean(savedInputSignal.^2)^0.5;
+    signalRMSdb=20*log10(signalRMS/20e-6);
+    
+    % plot signal (1)
+    plotInstructions.displaydt=dt;
+    plotInstructions.numPlots=6;
+    plotInstructions.subPlotNo=1;
+    plotInstructions.title=...
+        ['stimulus: ' num2str(signalRMSdb, '%4.0f') ' dB SPL'];
+    r=size(savedInputSignal,1);
+    if r==1, savedInputSignal=savedInputSignal'; end
+    UTIL_plotMatrix(savedInputSignal', plotInstructions);
+    
+    % stapes (2)
+    plotInstructions.subPlotNo=2;
+    plotInstructions.title= ['stapes displacement'];
+    UTIL_plotMatrix(OMEoutput, plotInstructions);
+    
+    % DRNL (3)
+    plotInstructions.subPlotNo=3;
+    plotInstructions.title= ['BM displacement'];
+    plotInstructions.yValues= savedBFlist;
+    UTIL_plotMatrix(DRNLoutput, plotInstructions);
+    
+    switch saveAN_spikesOrProbability
+        case 'spikes'
+            % AN (4)
+            plotInstructions.displaydt=ANdt;
+            plotInstructions.title='AN';
+            plotInstructions.subPlotNo=4;
+            plotInstructions.yLabel='BF';
+            plotInstructions.yValues= savedBFlist;
+            plotInstructions.rasterDotSize=1;
+            plotInstructions.plotDivider=1;
+            if sum(sum(ANoutput))<100
+                plotInstructions.rasterDotSize=3;
+            end
+            UTIL_plotMatrix(ANoutput, plotInstructions);
+            
+            % CN (5)
+            plotInstructions.displaydt=ANdt;
+            plotInstructions.subPlotNo=5;
+            plotInstructions.title='CN spikes';
+            if sum(sum(CNoutput))<100
+                plotInstructions.rasterDotSize=3;
+            end
+            UTIL_plotMatrix(CNoutput, plotInstructions);
+            
+            % IC (6)
+            plotInstructions.displaydt=ANdt;
+            plotInstructions.subPlotNo=6;
+            plotInstructions.title='IC';
+            if size(ICoutput,1)>3
+                if sum(sum(ICoutput))<100
+                    plotInstructions.rasterDotSize=3;
+                end
+                UTIL_plotMatrix(ICoutput, plotInstructions);
+            else
+                plotInstructions.title='IC (HSR) membrane potential';
+                plotInstructions.displaydt=dt;
+                plotInstructions.yLabel='V';
+                plotInstructions.zValuesRange= [-.1 0];
+                UTIL_plotMatrix(ICmembraneOutput, plotInstructions);
+            end
+            
+        otherwise % probability (4-6)
+            plotInstructions.displaydt=dt;
+            plotInstructions.numPlots=2;
+            plotInstructions.subPlotNo=2;
+            plotInstructions.yLabel='BF';
+            if nANfiberTypes>1,
+                plotInstructions.yLabel='LSR    HSR';
+                plotInstructions.plotDivider=1;
+            end
+            plotInstructions.title='AN - spike probability';
+            UTIL_plotMatrix(ANprobRateOutput, plotInstructions);
+    end
+end
+
+%% plot efferent control values as dB
+if options.showEfferent
+    plotInstructions=[];
+    plotInstructions.figureNo=98;
+    figure(98), clf
+    plotInstructions.displaydt=dt;
+    plotInstructions.numPlots=2;
+    plotInstructions.subPlotNo=1;
+    plotInstructions.zValuesRange=[ -25 0];
+    plotInstructions.title= ['AR strength.  Signal level= ' ...
+        num2str(signalRMSdb,'%4.0f') ' dB SPL'];
+    UTIL_plotMatrix(20*log10(ARattenuation), plotInstructions);
+    
+    plotInstructions.subPlotNo=2;
+    plotInstructions.yValues= savedBFlist;
+    plotInstructions.yLabel= 'BF';
+    plotInstructions.title= ['MOC strength'];
+    plotInstructions.zValuesRange=[ -25 0];
+    subplot(2,1,2)
+    % imagesc(MOCattenuation)
+    UTIL_plotMatrix(20*log10(MOCattenuation), plotInstructions);
+    colorbar
+end
+
+
+%% ACF plot if required
+if options.showACF
+    tic
+    method.dt=dt;
+    method.segmentNo=1;
+    method.nonlinCF=savedBFlist;
+    
+    minPitch=	80; maxPitch=	4000; numPitches=100;    % specify lags
+    pitches=10.^ linspace(log10(minPitch), log10(maxPitch),numPitches);
+    pitches=fliplr(pitches);
+    filteredSACFParams.lags=1./pitches;     % autocorrelation lags vector
+    filteredSACFParams.acfTau=	.003;       % time constant of running ACF
+    filteredSACFParams.lambda=	0.12;       % slower filter to smooth ACF
+    filteredSACFParams.lambda=	0.01;       % slower filter to smooth ACF
+    
+    filteredSACFParams.plotACFs=0;          % special plot (see code)
+    filteredSACFParams.plotFilteredSACF=0;  % 0 plots unfiltered ACFs
+    filteredSACFParams.plotMoviePauses=.3;          % special plot (see code)
+    
+    filteredSACFParams.usePressnitzer=0; % attenuates ACF at  long lags
+    filteredSACFParams.lagsProcedure=  'useAllLags';
+    % filteredSACFParams.lagsProcedure=  'useBernsteinLagWeights';
+    % filteredSACFParams.lagsProcedure=  'omitShortLags';
+    filteredSACFParams.criterionForOmittingLags=3;
+    filteredSACFParams.plotACFsInterval=200;
+    
+    if filteredSACFParams.plotACFs
+        % plot original waveform on ACF plot
+        figure(13), clf
+        subplot(4,1,1)
+        t=dt*(1:length(savedInputSignal));
+        plot(t,savedInputSignal)
+        xlim([0 t(end)])
+        title(['stimulus: ' num2str(signalRMSdb, '%4.0f') ' dB SPL']);
+    end
+    
+    % plot original waveform on summary/smoothed ACF plot
+    figure(97), clf
+    subplot(2,1,1)
+    t=dt*(1:length(savedInputSignal));
+    plot(t,savedInputSignal)
+    xlim([0 t(end)])
+    title(['stimulus: ' num2str(signalRMSdb, '%4.0f') ' dB SPL']);
+    
+    
+    % compute ACF
+    switch saveAN_spikesOrProbability
+        case 'probability'
+            inputToACF=ANprobRateOutput.^0.5;
+        otherwise
+            inputToACF=ANoutput;
+    end
+    
+    disp ('computing ACF...')
+    [P, BFlist, sacf, boundaryValue] = ...
+        filteredSACF(inputToACF, method, filteredSACFParams);
+    disp(' ACF done.')
+    
+    % SACF
+    subplot(2,1,2)
+    imagesc(P)
+    ylabel('periodicities (Hz)')
+    xlabel('time (s)')
+    title(['running smoothed (root) SACF. ' saveAN_spikesOrProbability ' input'])
+    pt=[1 get(gca,'ytick')]; % force top xtick to show
+    set(gca,'ytick',pt)
+    set(gca,'ytickLabel', round(pitches(pt)))
+    tt=get(gca,'xtick');
+    set(gca,'xtickLabel', round(100*t(tt))/100)
+end
+
+path(restorePath)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/testPrograms/test_MAP1_14.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,128 @@
+function test_MAP1_14
+
+% MAPdemo runs the MATLAB auditory periphery model (MAP1_14) as far as
+%  the AN (probabilities) or IC (spikes) with graphical output
+
+% Things you might want to change; #1 - #5
+
+%%  #1 parameter file name
+MAPparamsName='Normal';
+
+
+%% #2 probability (fast) or spikes (slow) representation
+AN_spikesOrProbability='spikes';
+% or
+AN_spikesOrProbability='probability';
+
+
+%% #3 pure tone, harmonic sequence or speech file input
+signalType= 'tones';
+duration=0.100;                 % seconds
+sampleRate= 100000;
+% toneFrequency= 250:250:8000;    % harmonic sequence (Hz)
+toneFrequency= 1000;            % or a pure tone (Hz8
+
+rampDuration=.005;              % seconds
+
+% or
+signalType= 'file';
+fileName='twister_44kHz';
+% fileName='new-da-44khz';
+
+
+%% #4 rms level
+% signal details
+leveldBSPL=70;                  % dB SPL
+
+
+%% #5 number of channels in the model
+%   21-channel model (log spacing)
+numChannels=21;
+lowestBF=250; 	highestBF= 8000; 
+BFlist=round(logspace(log10(lowestBF), log10(highestBF), numChannels));
+
+%   or specify your own channel BFs
+% BFlist=1000;
+
+
+%% #6 change model parameters
+paramChanges=[];
+
+% or
+% Parameter changes can be used to change one or more model parameters
+%  *after* the MAPparams file has been read
+% This example declares only one fiber type with a calcium clearance time
+% constant of 80e-6 s (HSR fiber) when the probability option is selected.
+switch AN_spikesOrProbability
+    case 'probability'
+        paramChanges={'IHCpreSynapseParams.tauCa=80e-6;'};
+    otherwise
+        paramChanges=[];
+end
+
+%% delare showMap options
+showMapOptions=[];  % use defaults
+
+% or (example: show everything including an smoothed SACF output
+    showMapOptions.showModelParameters=1;
+    showMapOptions.showModelOutput=1;
+    showMapOptions.printFiringRates=1;
+    showMapOptions.showACF=1;
+    showMapOptions.showEfferent=1;
+
+%% Generate stimuli
+
+dbstop if error
+restorePath=path;
+addpath (['..' filesep 'MAP'],    ['..' filesep 'wavFileStore'])
+switch signalType
+    case 'tones'
+        inputSignal=createMultiTone(sampleRate, toneFrequency, ...
+            leveldBSPL, duration, rampDuration);
+        
+    case 'file'
+        [inputSignal sampleRate]=wavread(fileName);       
+        inputSignal(:,1);
+        targetRMS=20e-6*10^(leveldBSPL/20);
+        rms=(mean(inputSignal.^2))^0.5;
+        amp=targetRMS/rms;
+        inputSignal=inputSignal*amp;
+end
+
+
+%% run the model
+tic
+
+MAP1_14(inputSignal, sampleRate, BFlist, ...
+    MAPparamsName, AN_spikesOrProbability, paramChanges);
+toc
+
+% the model run is now complete. Now display the results
+showMAP(showMapOptions)
+
+path(restorePath)
+
+
+function inputSignal=createMultiTone(sampleRate, toneFrequency, ...
+    leveldBSPL, duration, rampDuration)
+% Create pure tone stimulus
+dt=1/sampleRate; % seconds
+time=dt: dt: duration;
+inputSignal=sum(sin(2*pi*toneFrequency'*time), 1);
+amp=10^(leveldBSPL/20)*28e-6;   % converts to Pascals (peak)
+inputSignal=amp*inputSignal;
+
+% apply ramps
+% catch rampTime error
+if rampDuration>0.5*duration, rampDuration=duration/2; end
+rampTime=dt:dt:rampDuration;
+ramp=[0.5*(1+cos(2*pi*rampTime/(2*rampDuration)+pi)) ...
+    ones(1,length(time)-length(rampTime))];
+inputSignal=inputSignal.*ramp;
+ramp=fliplr(ramp);
+inputSignal=inputSignal.*ramp;
+
+% add 10 ms silence
+silence= zeros(1,round(0.03/dt));
+inputSignal= [silence inputSignal silence];
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utilities/UTIL_CV.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,35 @@
+function [cv, cvTimes, allTimeStamps, allISIs]=  UTIL_CV(earObject, dt, timeStep)
+% UTIL_CV computes coefficient of variation for multiple spike trains
+% earObject must be logical 0/1.  Each row is a separate run
+% CV is computed for successive time regions specified by timeStep
+
+if ~islogical(earObject),error('UTIL_CV: input is not logical/ spikes'), end
+
+[rows cols]=size(earObject);
+totalDuration=cols*dt;
+
+if nargin<3, timeStep=totalDuration/5; end
+
+% identify all intervals
+allISIs=[]; allTimeStamps=[];
+for i=1:rows
+    temp=find(earObject(i,:))*dt;    % find spikes
+    isi{i}=diff(temp);                      % find ISIs
+    timeStamps{i}=temp(2:end); % time of isi is time of second spike
+    allISIs=[allISIs isi{i}];
+    allTimeStamps=[allTimeStamps timeStamps{i}];
+end
+
+count=0;
+cvTimes=0: timeStep:totalDuration-timeStep; % bin edges
+for t= cvTimes
+    % sort ISIs according to when they happened
+    idx=find(allTimeStamps>t & allTimeStamps<=t+timeStep);
+    count=count+1;
+    if ~isempty(allISIs(idx))
+        cv(count)=std(allISIs(idx))/mean(allISIs(idx));
+    else
+        cv(count)=0;
+    end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utilities/UTIL_PSTHmaker.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,40 @@
+function [PSTH dt]=UTIL_PSTHmaker(inputData, dt, PSTHbinWidth)
+% UTIL_PSTHmaker accumulates values into bins.
+% No corrections are applied
+% usage:
+%	PSTH=UTIL_PSTHmaker(inputData, method)
+%
+% arguments
+%	inputData is a channel x time matrix
+%	PSTH is the reduced matrix, the sum of all elements in the bin
+%
+% mandatory fileds:
+%	method.dt
+% 	method.PSTHbinWidth
+[numChannels numDataPoints]= size(inputData);
+
+% Multiple fibers is the same as repeat trials
+% Consolidate data into a histogram 
+dataPointsPerBin=round(PSTHbinWidth/dt);
+if dataPointsPerBin<=1;
+% 	Too few data points
+	PSTH=inputData;
+	return
+end
+
+numBins=floor(numDataPoints/dataPointsPerBin);
+PSTH=zeros(numChannels,numBins);
+
+% take care that signal length is an integer multiple of bin size
+%  by dropping the last unuseable values
+useableDataLength=numBins*dataPointsPerBin;
+inputData=inputData(:,1:useableDataLength);
+
+for ch=1:numChannels
+	% Convert each channel into a matrix where each column represents 
+	% the content of a single PSTH bin
+	PSTH2D=reshape (inputData(ch,:), dataPointsPerBin, numBins );
+	% and sum within each bin (across the rows
+	PSTH(ch,:)=sum (PSTH2D,1);
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utilities/UTIL_makePSTH.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,38 @@
+function PSTH =UTIL_makePSTH(inputData, dt, PSTHbinWidth)
+% UTIL_PSTHmaker accumulates values into bins.
+% No corrections are applied
+% usage:
+%	PSTH=UTIL_makePSTH(inputData, dt, PSTHbinWidth)
+%
+% arguments
+%	inputData is a channel x time matrix
+%	PSTH is the reduced matrix, the sum of all elements in the bin
+%
+
+[numChannels numDataPoints]= size(inputData);
+
+% Multiple fibers is the same as repeat trials
+% Consolidate data into a histogram 
+dataPointsPerBin=round(PSTHbinWidth/dt);
+if dataPointsPerBin<=1;
+% 	Too few data points
+	PSTH=inputData;
+	return
+end
+
+numBins=floor(numDataPoints/dataPointsPerBin);
+PSTH=zeros(numChannels,numBins);
+
+% take care that signal length is an integer multiple of bin size
+%  by dropping the last unuseable values
+useableDataLength=numBins*dataPointsPerBin;
+inputData=inputData(:,1:useableDataLength);
+
+for ch=1:numChannels
+	% Convert each channel into a matrix where each column represents 
+	% the content of a single PSTH bin
+	PSTH2D=reshape (inputData(ch,:), dataPointsPerBin, numBins );
+	% and sum within each bin (across the rows
+	PSTH(ch,:)=sum (PSTH2D,1);
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utilities/UTIL_paramsList.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,40 @@
+function paramsFound=UTIL_paramsList(myWhos)
+% UTIL_paramsList looks for structures with names ending in Params.
+% nm=UTIL_paramsList(whos);
+% for i=1:length(nm), eval(['showStruct(' nm{i} ', ''' nm{i} ''')']),end
+
+% find structures ending with params
+paramsUsedCount=0;
+for i=1:length(myWhos)
+    var=myWhos(i).name;
+    if length(var)>5
+        tag=var(end-5:end);
+        if strcmp(tag,'Params')
+            paramsUsedCount=paramsUsedCount+1;
+            paramsUsed{paramsUsedCount}=var;
+        end
+    end
+end
+
+
+
+orderedList={'controlParams', 'globalStimParams', 'inputStimulusParams',...
+     'OMEParams', 'DRNLParams', ...
+    'IHC_cilia_RPParams', 'IHCpreSynapseParams', 'AN_IHCsynapseParams', ...
+    'MacGregorMultiParams', 'MacGregorParams'};
+
+
+% check that they belong to the approved list
+paramsFoundcount=0;
+for i=1:length(orderedList)
+    for j=1:length(paramsUsed)
+        usedName=paramsUsed{j};
+        if strcmp(orderedList{i},paramsUsed{j})
+            paramsFoundcount=paramsFoundcount+1;
+            paramsFound{paramsFoundcount}=usedName;
+        end
+    end
+end
+
+% return the list of names
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utilities/UTIL_periodHistogram.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,49 @@
+function [PH, binTimes]=UTIL_periodHistogram(A, dt, frequency)
+% UTIL_makePeriodHistogram converts a time sequence into a period histogram
+%*********************
+% The period is 1/frequency.
+%
+% usage:
+%	PH=UTIL_periodHistogram(A, dt, frequency)
+%
+% Input:
+% A is a channel x time matrix of spikes (or other stuff)
+% frequency determines the period of the histogram
+%
+% Output
+%  PH is a channel by periodhistogram matrix
+% bintimes is useful for plotting the output
+%
+
+periodInSeconds=1/frequency;
+[numChannels signalNpoints]=size(A);
+
+% retrict data array to a multiple of the period.
+pointsPerPeriod= round(periodInSeconds/dt);
+NcompletePeriods=floor(signalNpoints/pointsPerPeriod);
+totalPointsUsed=NcompletePeriods*pointsPerPeriod;
+
+% check that the period is a whole number of epochs
+aliasing=NcompletePeriods*(periodInSeconds/dt-pointsPerPeriod);
+
+if aliasing>.1
+    error('UTIL_periodHistogram: irregular period length')
+end
+
+if NcompletePeriods<1
+    error('UTIL_periodHistogram: too few datapoints')
+end
+
+% transpose data so that time is down a column
+A=A(:,1:totalPointsUsed)';
+
+% knock it into shape
+A=reshape(A,pointsPerPeriod, NcompletePeriods, numChannels);
+% each period is a separate column
+% imagesc(squeeze(A)) % should have horizontal stipe
+
+% channels are now the third dimension.
+PH=squeeze(sum(A,2))';
+% PH=PH/NcompletePeriods;
+
+binTimes=dt:dt:pointsPerPeriod*dt;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utilities/UTIL_plotMatrix.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,350 @@
+function UTIL_plotMatrix(toPlot, method)
+% UTIL_plotMatrix general purpose plotting utility for plotting the results
+%  of the MAP auditory model.
+% All plots are placed in subplots of a figure (default figure 1).
+% Input arguments:
+% 	'toPlot' is matrix (either numeric or logical)
+% 	'method' is a structure containing plot instructions
+%
+%   surface plots have log z-axis when all values are >1
+%
+% when calling this function, always increment the subPlotNo in method
+% 	method.subPlotNo=method.subPlotNo+1;
+% 	method.subPlotNo=method.subPlotNo;
+%
+% mandatory parameters:
+% 	method.displaydt			xValues spacing between data points
+% 	method.numPlots      total number of subPlots in the figure
+% 	method.subPlotNo     number of this plot
+%   method.yValues 		mandatory only for 3D plots
+%
+% optional
+% 	method.figureNo      normally figure(1)
+% 	method.zValuesRange 	[min max] value pair to define yaxis limits
+%   method.zValuesRange  [min max] CLIMS for 3-D plot
+% 	method.yLabel 		(string) y-axis label
+% 	method.xLabel		(string) x-axis label
+% 	method.title  		     (string) subplot title
+%   method.bar    		    =1,  to force bar histogram (single channel only)
+%   method.view			  3D plot 'view' settings e.g. [-6 40]
+%   method.axes           (handle) used for writing to GUIs (specifies panel)
+%   method.maxPixels     maximum number of pixels (used to speed plotting)
+%   method.blackOnWhite =1;  % NB inverts display for 2D plots
+%   method.forceLog      positive values are put on log z-scale
+%   method.rasterDotSize min value is 1
+%   method.defaultFontSize
+%   method.timeStart        default=dt
+%   method.defaultTextColor default ='w'
+%   method.defaultAxesColor default = 'w'
+%   method.nCols            default=1
+%   method.nRows            default=method.numPlots
+%
+% useful paste for calling program
+% 	method.numPlots=method.numPlots;
+%	method.subPlotNo=method.subPlotNo+1;
+% 	method.subPlotNo=method.subPlotNo;
+% 	dt=dt;
+% 	method.yValues=method.nonlinCF;	% for 3D plots only
+%
+% 	method.figureNo=1;
+% 	method.yLabel='useThisLabel';
+% 	method.xLabel='use this label';
+% 	method.title='myTitle';
+%
+%   UTIL_plotMatrix(toPlot, method)
+
+dt=method.displaydt;
+if ~isfield(method,'figureNo') || isempty(method.figureNo)
+    method.figureNo=99;
+end
+% if ~isfield(method,'zValuesRange') || isempty(method.zValuesRange)
+%     method.zValuesRange=[-inf inf];
+% end
+
+% set some defaults
+if ~isfield( method,'plotDivider') || isempty(method.plotDivider)
+    method.plotDivider=0; 
+end
+if ~isfield( method,'blackOnWhite') || isempty(method.blackOnWhite)
+    method.blackOnWhite=0; 
+end
+if ~isfield(method,'timeStart')|| isempty(method.timeStart)
+    method.timeStart=dt; 
+end
+if ~isfield(method,'objectDuration') || isempty(method.objectDuration)
+    [nRows nCols]=size(toPlot); method.objectDuration=dt*nCols;
+end
+if ~isfield(method,'defaultFontSize') || isempty(method.defaultFontSize)
+    method.defaultFontSize=12; 
+end
+if ~isfield(method,'defaultTextColor') || isempty(method.defaultTextColor)
+    method.defaultTextColor='k';
+    defaultTextColor=method.defaultTextColor;
+else
+    defaultTextColor='k';
+end
+if ~isfield( method,'defaultAxesColor') || isempty(method.defaultAxesColor)
+    method.defaultAxesColor=defaultTextColor; 
+end
+defaultAxesColor=method.defaultAxesColor;
+
+% arrangement of plots in rows and columns
+if ~isfield(method,'nCols') || isempty(method.nRows)
+    method.nCols=1;
+end
+if  ~isfield(method,'nRows') || isempty(method.nRows)
+    method.nRows= method.numPlots;
+end
+
+if ~isfield(method,'rasterDotSize') || isempty(method.rasterDotSize)
+    rasterDotSize=1;
+else
+    rasterDotSize=method.rasterDotSize;
+end
+
+% user can specify either an independent axis
+%   or a subplot of the current figure
+%   if both are specified, 'axes' takes priority
+figure(method.figureNo)
+if isfield(method,'axes') && ~isempty(method.axes)
+    % select an axis in some location other than 'figure'
+    h=axes(method.axes);
+else
+    % now using a regular figure
+    if method.subPlotNo>method.numPlots;
+        error('UTIL_plotMatrix: not enough subplots allocated in figure 1.  Check method.numPlots')
+    end
+    % choose subplot
+    subplot(method.nRows,method.nCols,method.subPlotNo),  % cla
+    
+    if isfield(method,'segmentNumber') && ~isempty(method.segmentNumber)...
+            && method.segmentNumber>1
+        % in multi-segment mode do not clear the image 
+        %  from the previous segment
+        hold on
+    else
+        % otherwise a fresh image will be plotted
+        hold off
+        cla
+    end
+end
+
+[numYvalues numXvalues]=size(toPlot);
+xValues=method.timeStart:dt:method.timeStart+dt*(numXvalues-1);
+
+if isfield(method,'yValues') && ~isempty(method.yValues)
+    % yValues is normally a vector specifying channel BF
+    yValues=method.yValues;
+else
+    yValues=1:numYvalues;
+end
+
+% Now start the plot.
+%  3D plotting for 4 or more channels
+%  otherwise special cases for fewer channels
+
+if ~islogical(toPlot)
+    % continuous variables
+    switch numYvalues
+        case 1                          % single vector (black)
+            if isfield(method,'bar') && ~isempty(method.bar)
+                % histogram
+                bar(xValues, toPlot,'k')
+                method.bar=[]; % avoid carry over between modules
+            else
+                % waveform
+                plot(xValues, toPlot,'k')
+            end
+            xlim([0 method.objectDuration])
+            if isfield(method,'zValuesRange') ...
+                    && ~isempty(method.zValuesRange)
+                ylim(method.zValuesRange)
+                method.zValuesRange=[]; % avoid carry over between modules
+            end
+            if isfield(method,'yLabel') && ~isempty(method.yLabel)
+                ylabel(method.yLabel, 'color', defaultTextColor)
+                method.yLabel=[]; % avoid carry over between modules
+            end
+            
+        case 2                          % 2 x N vector (black and red)
+            plot(xValues, toPlot(1,:),'k'), % hold on
+            plot(xValues, toPlot(2,:),'r'), % hold off
+            xlim([0 method.objectDuration])
+            if isfield(method,'zValuesRange') ...
+                    && ~isempty(method.zValuesRange)
+                ylim(method.zValuesRange)
+                method.zValuesRange=[]; % avoid carry over between modules
+            end
+            if isfield(method,'yLabel')&& ~isempty(method.yLabel)
+                ylabel(method.yLabel, 'color', defaultTextColor)
+                method.yLabel=[]; % avoid carry over between modules
+            end
+            
+        case 3                       % 3 x N vector (black red and green)
+            % this is used for 1 channel DRNL output
+            plot(xValues, toPlot(1,:),'k'), hold on
+            plot(xValues, toPlot(2,:),'r'),  hold on
+            plot(xValues, toPlot(3,:),'g'), hold off
+            xlim([0 method.objectDuration])
+            if isfield(method,'zValuesRange') ...
+                    && ~isempty(method.zValuesRange)
+                ylim(method.zValuesRange)
+            end
+            if isfield(method,'yLabel') &&  ~isempty(method.yLabel)
+                ylabel(method.yLabel, 'color', defaultTextColor)
+            end
+            
+        otherwise                       % >3 channels: surface plot
+            % add white line to separate HSR and LSR
+            if method.plotDivider && size(toPlot,1) > 2
+                [r c]=size(toPlot);
+%                 if isempty(method.zValuesRange), method.zValuesRange=0; end
+%                 mm=method.zValuesRange(2);
+                emptyLine=max(max(toPlot))*ones(2,c);
+                halfway=round(r/2);
+                toPlot=[toPlot(1:halfway,:); emptyLine; toPlot(halfway+1:end,:)];
+            end
+            
+            % invert data for black on white matrix plotting
+            if  method.blackOnWhite
+                toPlot=-toPlot;
+            end
+            
+            % matrix (analogue) plot
+            if isfield(method,'forceLog') && ~isempty(method.forceLog)
+                % positive values are put on log z-scale
+                toPlot=toPlot+min(min(toPlot))+1;
+                toPlot=log(toPlot);
+                if isfield(method,'title')
+                    method.title=[method.title '  (log scale)'];
+                else
+                    method.title= '(log scale)';
+                end
+            end
+            
+            %  zValuesRange
+            if isfield(method,'zValuesRange') ...
+                    && ~isempty(method.zValuesRange)
+                % zValuesRange gives the max and min values
+%                 a=method.zValuesRange(1);
+%                 b=method.zValuesRange(2);
+%                 toPlot=(toPlot-a)/(b-a);
+%                 clims=[0 1];
+                clims=(method.zValuesRange);
+                imagesc(xValues, yValues, toPlot, clims), axis xy; %NB assumes equally spaced y-values
+            else
+                % automatically scaled
+                imagesc(xValues, yValues, toPlot), axis xy; %NB assumes equally spaced y-values
+                
+                %                 if ~isfield(method,'zValuesRange')
+                %                     method.zValuesRange=[-inf inf];
+                %                 end
+                %
+                %                 if method.blackOnWhite
+                %                     % NB plotted values have negative sign for black on white
+                %                     caxis([-method.zValuesRange(2) -method.zValuesRange(1)])
+                %                 else
+                %                     caxis(method.zValuesRange)
+                %                 end
+                
+                if ~isfield(method,'zValuesRange')...
+                        || isempty(method.zValuesRange)
+                    method.zValuesRange=[-inf inf];
+                end
+                
+                if method.blackOnWhite
+                    % NB plotted values have negative sign for black on white
+                    caxis([-method.zValuesRange(2) -method.zValuesRange(1)])
+                else
+                    caxis(method.zValuesRange)
+                end
+            end
+            
+            % xaxis
+            % NB segmentation may shorten signal duration
+            [r c]=size(toPlot);
+            imageDuration=c*method.displaydt;
+            xlim([0 imageDuration])            
+%             xlim([0 method.objectDuration])
+
+            % yaxis
+            if isfield(method,'minyMaxy') && ~isempty(method.minyMaxy)
+                ylim(method.minyMaxy)
+            else
+                if max(yValues)>min(yValues)
+                    ylim([min(yValues) max(yValues)])
+                end
+            end
+            if min(yValues)>1  % put channel array on a log scale
+                tickValues=[min(yValues) max(yValues)];
+                set(gca,'ytick',tickValues)
+                set(gca,'ytickLabel', strvcat(num2str(tickValues')))
+                set(gca,'FontSize', method.defaultFontSize)
+            end
+            
+    end
+    
+else	% is logical 
+    
+    % logical implies spike array. Use raster plot
+    [y,x]=find(toPlot);	%locate all spikes: y is fiber number ie row
+    x=x*dt+method.timeStart;   % x is time
+    plot(x,y, 'o', 'MarkerSize', rasterDotSize, 'color', 'k')
+    if numYvalues>1
+        set(gca,'yScale','linear')
+        set(gca,'ytick', [1 numYvalues],'FontSize', method.defaultFontSize)
+        % show lowest and highest BF value only
+        set(gca,'ytickLabel', [min(yValues) max(yValues) ],'FontSize', method.defaultFontSize)
+        if method.plotDivider
+            % or use labels to identify fiber type
+            set(gca,'ytickLabel', {'LSR', 'HSR'},'FontSize', method.defaultFontSize)
+        end
+        ylim([0 numYvalues+1])
+    end
+    xlim([0 method.objectDuration])
+    if isfield(method,'yLabel') && ~isempty(method.yLabel)
+        ylabel(method.yLabel,'FontSize', method.defaultFontSize, 'color', defaultTextColor)
+    end
+    
+    % add  line to separate HSR and LSR
+    if method.plotDivider
+        [r c]=size(toPlot);
+        halfWayUp=round(r/2);
+        hold on
+        plot([0 c*method.displaydt],[halfWayUp halfWayUp], 'b')
+        hold off
+    end
+end
+
+set(gca, 'xcolor', defaultAxesColor)
+set(gca, 'ycolor', defaultAxesColor)
+
+% add title
+if isfield(method,'title') && ~isempty(method.title)
+    title(method.title, 'FontSize', method.defaultFontSize, 'color', defaultTextColor)
+end
+
+% label axes
+if ~isfield(method,'axes') || isempty(method.axes)
+    % annotate the x-axis only if it is the last plot on a figure created by this utility
+    set(gca,'xtick',[],'FontSize', method.defaultFontSize)
+    if method.subPlotNo==method.numPlots
+        if isfield(method,'xLabel') && ~isempty(method.xLabel)
+%               set(gca,'ActivePositionProperty','outerposition')
+            %  xlabel(method.xLabel)
+            xlabel(method.xLabel, 'FontSize', method.defaultFontSize, 'color', defaultTextColor)
+        end
+        set(gca,'xtickmode','auto') % add timescale to the lowest graph
+    end
+end
+
+% add user labels to the y-axis if requested
+if isfield(method,'yLabel') && ~isempty(method.yLabel)
+    ylabel(method.yLabel, 'color', defaultTextColor)
+end
+
+% define color
+if method.blackOnWhite, 	colormap bone, else 	colormap jet
+end
+
+% drawnow
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utilities/UTIL_printTabTable.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,30 @@
+function UTIL_printTabTable(M, headers, format)
+% printTabTable prints a matrix as a table with tabs
+%headers are optional
+%headers=strvcat('firstname', 'secondname')
+%  printTabTable([1 2; 3 4],strvcat('a1','a2'));
+
+if nargin<3
+    format='%g';
+end
+
+if nargin>1
+    [r c]=size(headers);
+    for no=1:r
+        fprintf('%s\t',headers(no,:))
+    end
+    fprintf('\n')
+end
+
+[r c]=size(M);
+
+for row=1:r
+    for col=1:c
+        fprintf('%s',num2str(M(row,col),format))
+        if col<c
+            fprintf('\t')
+        end
+    end
+    fprintf('\n')
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utilities/UTIL_showStruct.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,65 @@
+function UTIL_showStruct(structure, name, valuesOnly, terminator)
+% showStruct prints out the values in a single structure
+% using the format <name> '.' <fieled> ' = ' <value><terminator>
+% e.g. 
+% showStruct(params,'params')         % standard usage
+%showStruct(params,'params', 0, ';')  % adds final comma
+%showStruct(params,'params', 1)      % omits structure and field names
+
+if nargin<3, valuesOnly=0; end
+if nargin<4, terminator=[]; end
+
+fields=fieldnames(eval('structure'));
+for i=1:length(fields)
+    % y is the contents of this field
+    y=eval([ 'structure.' fields{i}]);
+    if ischar(y),
+        % strings
+        if valuesOnly
+            fprintf('\n%s', y)
+        else
+            fprintf('\n%s.%s=\t''%s%s''', name, fields{i},y,terminator)
+        end
+    elseif isnumeric(y)
+        % arrays
+        if length(y)>1
+            % matrices and vectors
+            [r c]=size(y);
+            if r>c, y=y'; end   % make row vector from column vector
+            [r c]=size(y);
+            
+            if r>10
+                % large matrix
+                fprintf('\n%s.%s=\t%g x %g matrix',name, fields{i}, r, c)
+                
+            elseif r>1
+                % small matrix
+                for row=1:r
+                    fprintf('\n%s.%s(%1.0f)=\t%s;', name, fields{i},row, num2str(y(row,:)))
+                end
+                
+            elseif c>20
+                % long row vector
+                fprintf('\n%s.%s=\t %g...   [%g element array]%s',name, fields{i}, y(1),c, terminator)
+                
+            else
+                fprintf('\n%s.%s=\t[%s]%s', name, fields{i},num2str(y),terminator)
+            end
+        else
+            % single valued arrays
+            if valuesOnly
+                fprintf('\n%s%s', num2str(y), terminator)
+            else
+                fprintf('\n%s.%s=\t%s%s', name, fields{i},num2str(y), terminator)
+            end
+
+        end % length (y)
+    elseif iscell(y)
+        fprintf('\n%s.%s=\t cell array', name, fields{i})
+            
+    elseif isstruct(y)
+        fprintf('\n%s.%s=\t structure', name, fields{i})
+    end     % isstr/ numeric
+
+end         % field
+fprintf('\n')
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utilities/UTIL_showStructureSummary.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,55 @@
+function UTIL_showStructureSummary(structure, name, maxNoArrayValues)
+% showStructureSummary prints out the values of a single structure
+% The header is the structure name and each row is a field
+% e.g. showStructureSummary(params,'params')
+% This not the same as 'UTIL_showstruct'
+
+
+if nargin<3
+	maxNoArrayValues=20;
+end
+
+fprintf('\n%s:', name)
+
+fields=fieldnames(eval('structure'));
+% for each field in the structure
+for i=1:length(fields)
+	y=eval([ 'structure.' fields{i}]);
+	if isstr(y),
+		% strings
+		fprintf('\n%s=\t''%s''',  fields{i},y)
+	elseif isnumeric(y)
+		% arrays
+		if length(y)>1
+			% vectors
+			[r c]=size(y);
+			if r>c, y=y'; end
+
+			[r c]=size(y);
+			if r>1
+				%                 fprintf('\n%s.%s=\t%g x %g matrix',name, fields{i}, r, c)
+				fprintf('\n%s=\t%g x %g matrix',fields{i}, r, c)
+
+			elseif c<maxNoArrayValues
+				%                     fprintf('\n%s=\t[%s]',  fields{i},num2str(y))
+				fprintf('\n%s=',  fields{i})
+				fprintf('\t%g',y)
+
+			else
+				fprintf('\n%s=\t %g...   [%g element array]', fields{i}, y(1),c)
+			end
+		else
+			% single valued arrays
+			%             fprintf('\n%s.%s=\t%s;', name, fields{i},num2str(y))
+			fprintf('\n%s=\t%s', fields{i},num2str(y))
+		end
+	elseif iscell(y)
+		fprintf('\n%s=\t cell array', fields{i})
+
+	elseif isstruct(y)
+		fprintf('\n%s=\t structure', fields{i})
+	end,
+
+end,
+fprintf('\n')
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utilities/UTIL_vectorStrength.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,29 @@
+function VS=UTIL_vectorStrength(PH)
+% UTIL_vectorStrength converts a period histogram to a vector strength measure.
+% **************
+% using the Johnson(1980) formula.
+% usage:
+% 	VS=UTIL_vectorStrength(PH);
+%
+% Input arguments:
+% 	PH is channels x  period histogram matrix
+%
+% Output argumkents:
+% VS is a column of vector strengths, one per channel
+[numChannels K]=size(PH);
+
+% a=cos(2*pi*(1/K:1/K:1));
+% b=sin(2*pi*(1/K:1/K:1));
+% VS=(sum(PH.*repmat(a,numChannels,1),2).^2 + sum(PH.*repmat(b,numChannels,1),2).^2).^0.5;
+% warning off MATLAB:divideByZero
+% VS=VS./sum(PH,2);
+% warning on MATLAB:divideByZeroa=cos(2*pi*(1/K:1/K:1));
+
+
+a=cos(2*pi*(1/K:1/K:1));
+b=sin(2*pi*(1/K:1/K:1));
+N=sum(PH,2);
+warning off MATLAB:divideByZero
+VS=((sum(PH.*repmat(a,numChannels,1),2)./N).^2 ...
+    + (sum(PH.*repmat(b,numChannels,1),2)./N).^2).^0.5;
+warning on MATLAB:divideByZero
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utilities/stimulusCreate.m	Fri May 27 13:19:21 2011 +0100
@@ -0,0 +1,1767 @@
+function [audio, msg, time]=stimulusCreate(globalStimParams,...
+    stimComponents, doPlot)
+% updated June 2007
+% the only authorised version of stimulus create is the version to be found
+% in MAP1_6.  Other versions are copies!!
+%
+% for a simple tone you need
+%
+% % Mandatory structure fields
+%  globalStimParams.FS=100000;
+%  globalStimParams.overallDuration=.1;  % s
+% doPlot=1;
+%
+% stim.type='tone';
+% stim.phases='sin';
+% stim.toneDuration=.05;;
+% stim.frequencies=500;
+% stim.amplitudesdB=50;
+% stim.beginSilence=.01;
+% stim.endSilence=-1;
+% stim.rampOnDur=.002;
+% stim.rampOffDur=-1;
+% [audio, msg]=stimulusCreate(globalStimParams, stim, doPlot);
+%
+% % or for multi-component stimuli
+% % Mandatory structure fields
+%  globalStimParams.FS=100000;
+%  globalStimParams.overallDuration=.1;  % s
+% ear=1;
+% componentNo=1;
+%
+% stimComponents(ear, componentNo).type='tone';
+% stimComponents(ear, componentNo).phases='sin';
+% stimComponents(ear, componentNo).toneDuration=.05;;
+% stimComponents(ear, componentNo).frequencies=500;
+% stimComponents(ear, componentNo).amplitudesdB=50;
+% stimComponents(ear, componentNo).beginSilence=.01;
+% stimComponents(ear, componentNo).endSilence=-1;
+% stimComponents(ear, componentNo).rampOnDur=.002;
+% stimComponents(ear, componentNo).rampOffDur=-1;
+%
+% % All components are forced to have the same overall duration and sample rate
+%
+%
+% [audio, msg]=stimulusCreate(globalStimParams, stimComponents);
+%
+%  Optional fields
+%  .ears overides ear setting by component
+%  globalStimParams.ears='monoticL'; % 'monoticL', 'monoticR', 'diotic', 'dichotic'
+%
+%  globalStimParams.filter = [leftfl leftfu rightfl right fu]
+%    filter is applied separately to left and right combined sounds
+%
+%  correction factor is applied to all signals to compensate for differences in output devices.
+% audioOutCorrection is a scalar
+%  globalStimParams.audioOutCorrection=2;
+%
+%  globalStimParams.FFT= 1; % {0, 1}
+%  globalStimParams.doPlot=1; % {0, 1}
+%  globalStimParams.doPlay=1; % {0, 1}
+%
+%  stimComponents(ear, componentNo).filter=[100 10000 2] % [lower, upper, order] applies to an
+% individual component
+%
+% Output arguments:
+%  audio is a stereo signal, a 2-column vector
+%
+%
+% stim.type='noise';    % {'IRN', 'irn', 'noise', 'pinkNoise'}
+% stim.toneDuration=.05;;
+% stim.amplitudesdB=50;
+% stim.beginSilence=.01;
+% stim.endSilence=-1;
+% stim.rampOnDur=.002;
+% stim.rampOffDur=-1;
+% [audio, msg]=stimulusCreate(globalStimParams, stim);
+%
+% % for IRN only
+% stim.type='IRN';
+% stim.toneDuration=.05;;
+% stim.amplitudesdB=50;
+% stim.beginSilence=.01;
+% stim.endSilence=-1;
+% stim.rampOnDur=.002;
+% stim.rampOffDur=-1;
+% stim.niterations = 8;   %0 for white noise
+% stim.delay = 1/150;
+% stim.irnGain = 1;
+% [audio, msg]=stimulusCreate(globalStimParams, stim);stimComponents.clickWidth;
+%
+% stim.type='clicks';    % uses frequencies for duty cycle
+% stim.toneDuration=.05;;
+% stim.frequencies=500;
+% stim.amplitudesdB=50;
+% stim.beginSilence=.01;
+% stim.endSilence=-1;
+% stim.rampOnDur=.002;
+% stim.rampOffDur=-1;
+% [audio, msg]=stimulusCreate(globalStimParams, stim);
+% stimComponents.clickWidth=.0001;    % default= dt
+% stimComponents.clickHeight= 20e-6;  % default= 28e-6 * 10^(stimComponents.amplitudesdB/20);
+% stim.clickTimes=[.4 .6];            % times in cylce when clicks occur, default = 1
+%
+%
+
+msg=''; %error messages; no message is a good message
+
+% plotting can be set as a separate argument or as a globalstimParams
+% variable. this is for backwards compatibility only
+if nargin>2,
+    globalStimParams.doPlot=doPlot;
+end
+
+% stimComponents(1,1).endSilence=-1;  % end silence is always computed
+
+% perform checks and set defaults
+[globalStimParams, stimComponents]=checkDescriptors(globalStimParams, stimComponents);
+
+
+% create empty stereo audio of appropriate length
+audio=zeros(globalStimParams.nSignalPoints, 2);
+% signal=zeros(globalStimParams.nSignalPoints, 1);
+dt=globalStimParams.dt;
+
+[Nears nComponentSounds]=size(stimComponents);
+for ear=1:Nears % left/ right
+    % combinedSignal is the sum of all sounds in one ear
+    % it is a column vector
+    combinedSignal=zeros(globalStimParams.nSignalPoints,1);
+
+    % find valid components
+    % if a component is empty, it is not a validComponent and is ignored
+    validStimComponents=[];
+    for i=1:nComponentSounds
+        if ~isempty(stimComponents(ear,i).type)
+            validStimComponents=[validStimComponents i];
+        end
+    end
+
+    for componentNo=validStimComponents
+        % compute individual components before adding
+        stim=stimComponents(ear,componentNo);
+        switch stim.type
+            case 'tone'
+                stimulus=maketone(globalStimParams, stim);
+
+            case 'fmTone'
+                stimulus=makeFMtone(globalStimParams, stim);
+
+            case 'OHIO'
+                stim.beginSilence=0;
+                stimulus=makeOHIOtones(globalStimParams, stim);
+
+            case 'transposedStimulus'
+                stim.beginSilence=0;    % necessary because of recursion
+                stimulus=makeTransposedStimulus(globalStimParams, stim);
+
+            case { 'noise', 'pinkNoise'}
+                stimulus=makeNoise(globalStimParams, stim);
+
+            case { 'whiteNoise'}
+                stimulus=makeWhiteNoise(globalStimParams, stim);
+
+            case {'IRN', 'irn'}
+                stimulus=makeIRN(globalStimParams, stim);
+
+            case {'RPN'}
+                stimulus=makeRPN(globalStimParams, stim);
+
+            case 'clicks'
+                stimulus=makeClicks(globalStimParams, stim);
+
+            case 'PressnitzerClicks'
+                % kxx clicks
+                % k is 1/clickRepeatFrequency
+                stimulus=makePressnitzerClicks(globalStimParams, stimComponents);
+
+            case 'PressnitzerABxClicks'
+                % kxx clicks
+                % k is 1/clickRepeatFrequency
+                stimulus=makePressnitzerABxClicks(globalStimParams, stimComponents);
+
+            case 'ABxClicks'
+                % A=rand*k,  B=k-A, x=rand*k.
+                stimulus=makeABxClicks(globalStimParams, stimComponents);
+
+            case 'YostClicks'
+                % kxx clicks
+                % k is 1/clickRepeatFrequency
+                stimulus=makeYostClicks(globalStimParams, stimComponents);
+
+            case 'kxxClicks'
+                % kxx clicks
+                % k is 1/clickRepeatFrequency
+                stimulus=makeKxxClicks(globalStimParams, stimComponents);
+
+
+%             case 'babble'
+%                 % NB random start in a long file
+%                 [stimulus sampleRate]= wavread('babble');
+%                 nPoints=round(sampleRate*...
+%                     stimComponents(ear,componentNo).toneDuration);
+%                 start=round(rand(1,1)*(length(stimulus)-nPoints));
+%                 stimulus=stimulus(start:start+nPoints-1);
+%                 rms= 20*log10((mean(stimulus.^2).^0.5)/20e-6);
+%                 dBSPLrms=stimComponents(ear,componentNo).amplitudesdB;
+%                 gain=10.^((dBSPLrms-rms)/20);
+%                 stimulus=stimulus'*gain;
+
+            case 'speech'
+                [stimulus sampleRate]= wavread('speech');
+                stimulus=stimulus';
+                nPoints=sampleRate*stimComponents(ear,componentNo).toneDuration;
+                if nPoints > length(stimulus)
+                    initialSilence=zeros(1,nPoints-length(stimulus));
+                else
+                    initialSilence=[];
+                    start=round(rand(1,1)*(length(stimulus)-nPoints));
+                    stimulus=stimulus(start:start+nPoints-1);
+                end
+                rms= 20*log10((mean(stimulus.^2).^0.5)/20e-6);
+                dBSPLrms=stimComponents(ear,componentNo).amplitudesdB;
+                gain=10.^((dBSPLrms-rms)/20);
+                stimulus=stimulus*gain;
+                stimulus=[stimulus initialSilence ];
+
+
+            case 'file'
+                % component already read from file and stored in stimulus. Insert it here
+                % additional code for establishing signal rms level
+                % NB signal is always mono at this stage
+
+                stimulus=stim.stimulus;
+                dBSPL=stim.amplitudesdB;
+
+                nPoints=round(stim.toneDuration/dt);
+                [r c]=size(stimulus);
+                if r>c, stimulus=stimulus'; end    % secure horizontal vector
+                stimulus=stimulus(1,1:nPoints); % only mono taken from file
+
+                try
+                    % dB rms
+                    rms= 20*log10((mean(stimulus.^2).^0.5)/20e-6);
+                    % special request to set fixed rms for stimulus
+                    dBSPLrms=stimComponents(ear,componentNo).amplitudesdBrms;
+                    if ~(dBSPLrms==-1)
+                        gain=10.^((dBSPLrms-rms)/20);
+                        stimulus=stimulus*gain;
+                    end
+                catch
+                    % If no request for rms level is made
+                    % set dB as peak amp
+                    [stimulus gain]= normalize(stimulus);
+                    dBSPL=stimComponents(ear,componentNo).amplitudesdB;
+                    if ~(dBSPL==-1)
+                        amplitude=28e-6*10.^(dBSPL/20);
+                        stimulus=stimulus*amplitude;
+                    end
+                end
+
+            case 'none'
+                % no stimulus
+                stimulus=zeros(1,round(stim.toneDuration/dt));
+
+            case 'digitStrings'
+                % select a digit string at random anduse as target
+                files=dir(['..' filesep '..' filesep 'multithresholdResources\digitStrings']);
+                files=files(3:end);
+                nFiles=length(files);
+                fileNo=ceil(nFiles*rand);
+                fileData=files(fileNo);
+                fileName=['..\..\multithresholdResources\digitStrings\' fileData.name];
+                [stimulus sampleRate]=wavread(fileName);
+                stimulus=stimulus(:,1)';  % make into a row vector
+                % estimate the extend of endsilence padding
+                nPoints=sampleRate*...
+                    stimComponents(ear,componentNo).toneDuration;
+                if nPoints > length(stimulus)
+                    endSilence=zeros(1,nPoints-length(stimulus));
+                else
+                    % or truncate the file
+                    endSilence=[];
+                    stimulus=stimulus(1:nPoints);
+                end
+                % compute rms before adding silence
+                rms= 20*log10((mean(stimulus.^2).^0.5)/20e-6);
+                dBSPLrms=stimComponents(ear,componentNo).amplitudesdB;
+                gain=10.^((dBSPLrms-rms)/20);
+                stimulus=stimulus*gain;
+                stimulus=[stimulus endSilence];
+                global stimulusParameters
+                stimulusParameters.digitString=fileName(end-7:end-5);
+
+            otherwise
+                switch stim.type(end-5:end)
+                    % any file name with 'Babble' at the end is a
+                    % multiThreshold file
+                    case 'Babble'
+                        % one of the many babbles is selected.
+                        % NB random start in a long file
+                        %  stim.type should contain the name of the babble file
+                        fileName=['..' filesep '..' filesep ...
+                            'multithresholdResources' filesep ...
+                            'backgrounds and maskers'...
+                             filesep stim.type];
+                        
+                        [stimulus sampleRate]= wavread(fileName);
+                        if ~isequal(sampleRate, globalStimParams.FS)
+                            % NB the file will read but will disagree with
+                            % tone stimuli or other files read
+                            msg= ['error: file sample rate disagrees ' ...
+                                'with sample rate requested in paradigm'...
+                                ' file (' ...
+                            num2str(globalStimParams.FS) ').'];
+                            error(msg);                            
+                        end
+                        nPoints=round(sampleRate*...
+                            stimComponents(ear,componentNo).toneDuration);
+                        start=round(rand(1,1)*(length(stimulus)-nPoints));
+                        stimulus=stimulus(start:start+nPoints-1);
+                        rms= 20*log10((mean(stimulus.^2).^0.5)/20e-6);
+                        dBSPLrms=stimComponents(ear,componentNo).amplitudesdB;
+                        gain=10.^((dBSPLrms-rms)/20);
+                        stimulus=stimulus'*gain;
+                        
+                    otherwise
+                        % stim.type may be the name of a file to be read
+                        % play from beginning for stimulus duration
+                        try
+                            [stimulus sampleRate]= wavread([stim.type '.wav']);
+                        catch
+                            error(['stimulusCreate: unrecognised stimulus type -> '...
+                                stim.type])
+                        end
+                        if ~isequal(sampleRate, globalStimParams.FS)
+                            % NB the file will read but will disagree with
+                            % tone stimuli or other files read
+                            msg= ['error: file sample rate disagrees ' ...
+                                'with sample rate requested in paradigm'...
+                                ' file (' ...
+                            num2str(globalStimParams.FS) ').'];
+                            error(msg);
+                        end
+                        stimulus=stimulus';  % make into a row vector
+                        % estimate the extend of endsilence padding
+                        nPoints=sampleRate*...
+                            stimComponents(ear,componentNo).toneDuration;
+                        if nPoints > length(stimulus)
+                            endSilence=zeros(1,nPoints-length(stimulus));
+                        else
+                            % or truncate the file
+                            endSilence=[];
+                            stimulus=stimulus(1:nPoints);
+                        end
+                        % compute rms before adding silence
+                        rms= 20*log10((mean(stimulus.^2).^0.5)/20e-6);
+                        dBSPLrms=stimComponents(ear,componentNo).amplitudesdB;
+                        gain=10.^((dBSPLrms-rms)/20);
+                        stimulus=stimulus*gain;
+                        stimulus=[stimulus endSilence];
+                end
+        end
+
+        % NB stimulus is a row vector now!
+        % audio and combinedSignal were column vectors
+        % signal will be a row vector
+
+        % filter stimulus
+        try
+            % if filter field is present, [lower upper order]
+            if stim.filter(1)>0	% 0 means don't filter
+                stimulus=Butterworth (stimulus, dt, stim.filter(1), ...
+                    stim.filter(2), stim.filter(3));
+
+            end
+        catch
+        end
+
+
+        % apply amplitude modulation
+        if isfield(stim,'AMfrequency') & isfield(stim,'AMdepth')
+            if stim.AMfrequency>0 & stim.AMdepth>0
+                time=dt:dt:dt*length(stimulus);
+                modulator=sin(2*pi*stim.AMfrequency*time);
+                modulator=modulator*stim.AMdepth/100 + 1; % depth is percent
+                stimulus=stimulus.*modulator/2;
+            end
+        end
+
+        % Basic stimulus is now created.
+        % Add trappings, ramps, silences to main stimulus
+        rampOnTime=0;		 %ramp starts at the beginning of the stimulus
+        rampOffTime=stim.toneDuration-stim.rampOffDur;
+        if stim.rampOnDur>0.0001
+            stimulus=applyRampOn(stimulus, stim.rampOnDur, rampOnTime, 1/dt);
+            stimulus=applyRampOff(stimulus, stim.rampOffDur, rampOffTime, 1/dt);
+        end
+        if stim.rampOnDur<-0.0001   % apply Gaussian ramp
+            stimulus=applyGaussianRamps(stimulus, -stim.rampOnDur, 1/dt);
+        end
+
+        % Initial silence
+        % start with a signal of the right length consisting of zeros
+        signal=zeros(1, globalStimParams.nSignalPoints);
+        % identify start of stimulus
+        insertStimulusAt=round(stim.beginSilence/dt)+1;
+        % add stimulus
+        endOfStimulus=insertStimulusAt+length(stimulus)-1;
+        if endOfStimulus<=globalStimParams.nSignalPoints
+            signal(1, insertStimulusAt: endOfStimulus)=stimulus;
+        else
+            error('stimulusCreate: tone too long to fit into the overall duration')
+        end
+
+        % time signature
+        time=dt:dt:dt*length(signal);
+        %     figure(22), plot(signal), title([num2str(ear) ' - ' num2str(componentNo)]),pause (1)
+
+        try
+            % create a column vector and trap if no signal has been created
+            signal=signal';
+            % also traps if signals are not the same length
+            combinedSignal=combinedSignal+signal;
+            %             figure(21), plot(combinedSignal), title([num2str(ear) ' - ' num2str(componentNo)]),pause (1)
+        catch
+            % dump everything because there is a problem
+            globalStimParams
+            [ear  componentNo]
+            stim
+            size(combinedSignal)
+            size(signal)
+            [   size(initialSilence)            size(signal)            size(endSilence)]
+            [ ear  componentNo...
+                round(globalStimParams.overallDuration*globalStimParams.FS)...
+                round(stim.beginSilence*globalStimParams.FS)...
+                round(stim.toneDuration*globalStimParams.FS) ...
+                round(stim.endSilence*globalStimParams.FS)...
+                (                       round(globalStimParams.overallDuration*globalStimParams.FS)...
+                -round(stim.beginSilence*globalStimParams.FS)...
+                -round(stim.toneDuration*globalStimParams.FS) ...
+                -round(stim.endSilence*globalStimParams.FS))...
+                ]
+            error(' trouble in stimulusCreate: signals are the wrong length ')
+        end
+
+    end % component no
+
+    audio(:,ear)= combinedSignal;
+
+    % FFT
+    try
+        if globalStimParams.FFT
+            showFFT (audio, dt)
+        end
+    catch
+    end
+
+
+end % ear
+
+switch globalStimParams.ears
+    % normally the signals are created in appropriate ears but .ears can
+    % overide this to produce a mono signal.
+    case 'monoticL';
+        % combine left and right ears to make a mono signal in the left ear
+        audio(:,1)=audio(:,1)+audio(:,2);
+        audio(:,2)=zeros(globalStimParams.nSignalPoints, 1);
+
+    case 'monoticR';
+        % combine left and right ears to make a mono signal in the right ear
+        audio(:,2)=audio(:,1)+audio(:,2);
+        audio(:,1)=zeros(globalStimParams.nSignalPoints, 1);
+
+    case 'diotic';
+        % combine left and right ears to make a mono signal in both ears
+        bothEarsCombined=audio(:,1)+audio(:,2);
+        audio(:,2)=bothEarsCombined;
+        audio(:,1)=bothEarsCombined;
+
+    otherwise
+        % Any other denomination produces no effect here
+end
+
+% Plotting as required
+if globalStimParams.doPlot
+    figure(9), clf
+    plot(time,audio(:,1)'), hold on,
+    if Nears>1
+        offSet=(max(audio(:,1))+max(audio(:,2)))/10;
+        offSet=2*offSet+max(audio(:,1))+max(audio(:,2));
+        plot(time,audio(:,2)'+offSet,'r'), hold off
+    end
+    ylabel('left                             right')
+end
+
+% Calibration
+% all signals are divided by this correction factor
+% peakAmp=globalStimParams.audioOutCorrection; % microPascals = 100 dB SPL
+
+audio=audio/globalStimParams.audioOutCorrection;
+
+if globalStimParams.doPlay
+    wavplay(audio,globalStimParams.FS)
+end
+% all Done
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
+%---------------------------------------------------- maketone
+function tone=maketone(globalStimParams, stimComponents)
+% maketone generates a stimComponents tone
+% tone=maketone(dt, frequencies, toneDuration, dBSPL, phases)
+% tone is returned in Pascals
+% frequencies is a list of frequencies
+% phase is list of phases or 'sin', 'cos', 'alt'
+%
+% defaults:
+%  phase = sin
+%  dBSPL=56 dB SPL
+
+dt=globalStimParams.dt;
+frequencies=stimComponents.frequencies;
+toneDuration=stimComponents.toneDuration;
+dBSPL=stimComponents.amplitudesdB;
+phases=stimComponents.phases;
+
+if ischar(phases)
+    switch phases
+        case 'sin'
+            phases= zeros(1,length(frequencies));
+        case 'cos'
+            phases= pi/2*ones(1,length(frequencies));
+        case 'alt'
+            phases= repmat([0 pi/2], 1, floor(length(frequencies)/2));
+            if length(phases)<length(frequencies)
+                phases=[phases 0];
+            end
+        case {'ran', 'rand'}
+            phases= 2*pi*rand(1,length(frequencies));
+    end
+end
+
+if length(phases)==1, phases=repmat(phases(1), 1, length(frequencies)); end
+if length(phases)<length(frequencies)
+    error('makeTone:phase specification must have the same length as frequencies')
+end
+
+if length(dBSPL)==1, dBSPL=repmat(dBSPL(1), 1, length(frequencies)); end
+if length(dBSPL)<length(dBSPL)
+    error('makeTone:dBSPL specification must have the same length as frequencies')
+end
+
+time=dt:dt:toneDuration;
+amplitudes=28e-6* 10.^(dBSPL/20);
+
+tone=zeros(size(time));
+for i=1:length(frequencies)
+    frequency=frequencies(i);
+    phase=phases(i);
+    tone=tone+amplitudes(i)*sin(2*pi*frequency*time+phase);
+end
+
+% figure(1), plot(time, signal)
+
+
+%---------------------------------------------------- makeOHIOtones
+function stimulus=makeOHIOtones(globalStimParams, stimComponents)
+
+% Generates a stimulus consisting of one or more 10-ms tones
+% Tones are presented at 10-ms intervals
+% Each tone has its own amplitude and its own ramp.
+
+frequencies=stimComponents.frequencies;
+amplitudesdB=stimComponents.amplitudesdB;
+nFrequencies=length(frequencies);
+
+dt=globalStimParams.dt;
+toneDuration=.010;
+time=dt:dt:toneDuration;
+
+rampDuration=stimComponents.rampOnDur;
+rampTime=dt:dt:rampDuration;
+ramp=[0.5*(1+cos(2*pi*rampTime/(2*rampDuration)+pi)) ones(1,length(time)-length(rampTime))];
+ramp=ramp.*fliplr(ramp);
+
+stimulus= zeros(1,round((toneDuration+globalStimParams.beginSilences(end))/dt)+1);
+
+for i=1:nFrequencies
+    toneBeginPTR=round(globalStimParams.beginSilences(i)/dt)+1;
+
+    frequency=frequencies(i);
+    dBSPL=amplitudesdB(i);
+    amplitude=28e-6* 10.^(dBSPL/20);
+    tone=amplitude*sin(2*pi*frequency*time);
+    tone=tone.*ramp;
+    stimulus(toneBeginPTR:toneBeginPTR+length(tone)-1)=stimulus(toneBeginPTR:toneBeginPTR+length(tone)-1)+tone;
+end
+% figure(2), plot( stimulus')
+
+
+%---------------------------------------------------- makeFMtone
+function tone=makeFMtone(globalStimParams, stimComponents)
+% maketone generates a stimComponents tone
+% tone=maketone(dt, frequencies, toneDuration, dBSPL, phases)
+% tone is returned in Pascals
+% frequencies is a list of frequencies
+% phase is list of phases or 'sin', 'cos', 'alt'
+%
+% defaults:
+%  phase = sin
+%  dBSPL=56 dB SPL
+
+dt=globalStimParams.dt;
+frequencies=stimComponents.frequencies;
+toneDuration=stimComponents.toneDuration;
+dBSPL=stimComponents.amplitudesdB;
+phases=stimComponents.phases;
+fmDepth=stimComponents.fmDepth;
+fmFrequency=stimComponents.fmFrequency;
+
+if ischar(phases)
+    switch phases
+        case 'sin'
+            phases= zeros(1,length(frequencies));
+        case 'cos'
+            phases= pi/2*ones(1,length(frequencies));
+        case 'alt'
+            phases= repmat([0 pi/2], 1, floor(length(frequencies)/2));
+            if length(phases)<length(frequencies)
+                phases=[phases 0];
+            end
+    end
+end
+
+if length(phases)==1, phases=repmat(phases(1), 1, length(frequencies)); end
+if length(phases)<length(frequencies)
+    error('makeTone:phase specification must have the same length as frequencies')
+end
+
+if length(dBSPL)==1, dBSPL=repmat(dBSPL(1), 1, length(frequencies)); end
+if length(dBSPL)<length(dBSPL)
+    error('makeTone:dBSPL specification must have the same length as frequencies')
+end
+
+time=dt:dt:toneDuration;
+amplitudes=28e-6* 10.^(dBSPL/20);
+
+tone=zeros(size(time));
+for i=1:length(frequencies)
+    frequency=frequencies(i);
+    phase=phases(i);
+    tone=tone+amplitudes(i)*sin(2*pi*frequency*time+phase + fmDepth*sin(2*pi*fmFrequency*time));
+end
+
+% figure(1), plot(time, signal)
+
+%----------------------------------------------------makeTransposedStimulus
+function [transposedStimulus]=makeTransposedStimulus(globalStimParams, stim)
+% globalStimParams.FS=100000;
+% globalStimParams.overallDuration=.1;  % s
+% globalStimParams.doPlot=1;
+%
+% stim.type='transposedStimulus';
+% stim.phases='sin';
+% stim.toneDuration=.05;;
+% stim.frequencies=500;
+% stim.amplitudesdB=50;
+% stim.beginSilence=.01;
+% stim.endSilence=-1;
+% stim.rampOnDur=.002;
+% stim.rampOffDur=-1;
+%
+% stim.transCarrierFreq=4000;
+% stim.transModFreq=100;
+
+transposedStimulus=[];
+% make envelope of transposed tone
+for i=1:length(stim.transModFreq)
+    stim.type='tone';
+    stim.frequencies=stim.transModFreq(i);
+    stim.endsilence=-1;     stim.beginSilence=0;
+    [envelope, msg]=stimulusCreate(globalStimParams, stim);    % NB recursive
+    envelope=envelope(:,1);   % mono
+    % HW rectify
+    envelope(find(envelope<0))=0;
+    % LP filter
+    maxEnvelope=max(envelope);
+    envelope=UTIL_Butterworth (envelope, globalStimParams.dt, 10, .2*stim.transModFreq(i), 2);
+    envelope=envelope*maxEnvelope/max(envelope);
+
+    % make the carrier
+    stim.frequencies=stim.transCarrierFreq(i);
+    stim.endsilence=-1;    stim.beginSilence=0;
+    [audio, msg]=stimulusCreate(globalStimParams, stim);
+    carrier=audio(:,1);
+    x= (carrier.*envelope)';
+    % base amplitude on peak of unmodulated carrier
+    x=x/max(carrier);
+    transposedStimulus=[transposedStimulus; x];
+end
+transposedStimulus=sum(transposedStimulus,1);
+% clf,plot(transposedStimulus)
+
+%--------------------------------------------------------------------makeClicks
+function clickTrain=makeClicks(globalStimParams, stimComponents)
+% makeClicks(F0, clickTimes, duration, FS);
+% F0 specifies the repetition rate of the click sequence
+% If F0=-1, a single click is generated at the start of the duration of the signal
+%
+% clickTimes a are fractions of the period
+%  and specify when the click appears in the period
+% A click time of 1 is reset to zero.
+% if the clicktime plus the click width is greater than the period, no click is generated
+% clicks are treated as 20 microPascal high before amplification
+%  unless otherwise specified in stimComponents.clickHeight
+% click width is dt unless specified in stimComponents.clickWidth
+%
+% for regular pulse train set clicktimes=1 or zero;
+% FS is the sampling interval;
+% CarlyonClickTrain(100, [.4 1], 40, 441000);
+
+FS=globalStimParams.FS; % sample rate
+dt=1/FS;
+
+try,clickWidth=stimComponents.clickWidth;catch, clickWidth=dt; end
+try,clickHeight=stimComponents.clickHeight; catch, clickHeight=28e-6 * 10^(stimComponents.amplitudesdB/20); end
+try, clickTimes=stimComponents.clickTimes; catch, clickTimes=1; end
+
+% clickTimes are the times in a cycle that the click
+% occurs
+checkClickTimes=clickTimes-1;
+if max(checkClickTimes)>1
+    msg= 'click times must be <= than 1 (period)';
+    return
+end
+
+if clickWidth>=1/stimComponents.clickRepeatFrequency
+    msg= 'click width is too great for frequency';
+    return
+end
+
+duration=stimComponents.toneDuration;
+totalLength=round(stimComponents.toneDuration/dt);
+F0=stimComponents.clickRepeatFrequency;
+F0=round(F0/dt)*dt;
+if F0==-1 % single click required
+    F0=1/duration;
+    repetitions=1;
+    clickStartTimes=1; %clicktimes are fractions of a period
+else
+    repetitions=round(F0*duration)-1;
+    duration=repetitions/F0;
+    clickStartTimes=clickTimes;
+end
+% if a clickTime=1 (end of duty period) set it to the beginning
+clickStartTimes(clickStartTimes==1)=0;
+
+period=1/F0;
+time=dt:dt:period;
+nPoints=length(time);
+signal=zeros(1,nPoints);
+dBSPL=stimComponents.amplitudesdB;
+
+% compute click train for a single cycle
+clickWidthNpoints=round(clickWidth*FS);
+for i=1:length(clickStartTimes)
+    %     if clickStartTimes(i)<clickWidth
+    %         clickStartTimes(i)=dt;
+    %     end
+    clickTime=round(period*clickStartTimes(i)/dt -dt);
+    % clicks are treated as 20 microPascal high
+    if clickTime+clickWidthNpoints<length(signal)
+        signal(clickTime+1:clickTime+clickWidthNpoints)=clickHeight;
+    end
+end
+
+clickTrain=repmat(signal, 1, repetitions);
+
+if length(clickTrain)>totalLength
+    clickTrain=clickTrain(1:totalLength);
+elseif length(clickTrain)<totalLength
+    timeToAdd=zeros(1,round((totalLength-length(clickTrain))));
+    clickTrain=[clickTrain timeToAdd];
+    % figure (1), plot(clickTrain)
+end
+
+%----------------------------------------------------------------makePressnitzerClicks
+function signal=makePressnitzerClicks(globalStimParams, stimComponents)
+% PressnitzerClicks(k,duration,dt)
+% Generates a sequence of clicks with intervals kxx
+%  where x= rand*k/2
+% This is not the same as Kaernbach and Demany clicks
+
+FS=globalStimParams.FS; % sample rate
+dt=1/FS;
+
+% obligatory parameter
+try
+    k=stimComponents.k;
+catch
+    error('PressnitzerClicks: field ''k'' is missing from stimcomponent')
+end
+
+% optional parameters
+if isfield(stimComponents,'clickWidth')
+    clickWidth=stimComponents.clickWidth;
+else
+    clickWidth=dt;
+end
+clickWidthNpoints=round(clickWidth*FS);
+
+if isfield(stimComponents,'clickHeight')
+    clickHeight=stimComponents.clickHeight;
+else
+    clickHeight=28e-6 * 10^(stimComponents.amplitudesdB/20);
+end
+
+duration=stimComponents.toneDuration;
+
+signalLength=round(duration/dt);
+signal=zeros(1,signalLength);
+kInterval=round(k/dt);
+halfk=k/2;
+signal(1)=clickHeight;
+timeIdx=0;
+while timeIdx<signalLength
+    % first interval = k
+    clickTime=timeIdx+kInterval;
+    signal(clickTime:clickTime+clickWidthNpoints)=clickHeight;
+    timeIdx=timeIdx+kInterval;
+
+    % second interval = 0 : k/2
+    intervalx1=round(rand*halfk/dt);
+    clickTime=timeIdx+intervalx1;
+    signal(clickTime:clickTime+clickWidthNpoints)=clickHeight;
+    timeIdx=timeIdx+intervalx1;
+
+    % third interval = 0 : k/2
+    intervalx1=round(rand*halfk/dt);
+    clickTime=timeIdx+intervalx1;
+    signal(clickTime:clickTime+clickWidthNpoints)=clickHeight;
+    timeIdx=timeIdx+intervalx1;
+end
+
+signal=signal(1:signalLength);
+% figure(1),	plot(dt:dt:duration,signal)
+
+%----------------------------------------------------------------makePressnitzerABXClicks
+function signal=makePressnitzerABxClicks(globalStimParams, stimComponents)
+% Generates a sequence of clicks with intervals ABx
+% AB interval is 2*k
+% where A= rand* k
+%       B= k-A
+%       x= k/2
+% These are second order clicks
+
+FS=globalStimParams.FS; % sample rate
+dt=1/FS;
+
+% obligatory parameter
+try
+    k=stimComponents.k;
+catch
+    error('PressnitzerClicks: field ''k'' is missing from stimcomponent')
+end
+
+% optional parameters
+if isfield(stimComponents,'clickWidth')
+    clickWidth=stimComponents.clickWidth;
+else
+    clickWidth=dt;
+end
+clickWidthNpoints=round(clickWidth*FS);
+
+if isfield(stimComponents,'clickHeight')
+    clickHeight=stimComponents.clickHeight;
+else
+    clickHeight=28e-6 * 10^(stimComponents.amplitudesdB/20);
+end
+
+duration=stimComponents.toneDuration;
+
+signalLength=round(duration/dt);
+signal=zeros(1,2*signalLength); % allow for overrun
+ABinterval=k/dt;                % i.e. the number of dt steps
+randomInterval=ABinterval/2;
+signal(1)=clickHeight;
+time=0;
+while time<signalLength
+    % first interval = A
+    intervalA=rand*ABinterval;
+    clickTime=round(time+intervalA)+1;   % +1 avoids zero index
+    signal(clickTime:clickTime+clickWidthNpoints)=clickHeight;
+    time=time+intervalA;
+
+    % second interval = B
+    intervalB=ABinterval-intervalA;
+    clickTime=round(time+intervalB)+1;
+    signal(clickTime:clickTime+clickWidthNpoints-1)=clickHeight;
+    time=time+intervalB;
+
+    % third interval = 0 : k/2
+    intervalx1=rand*randomInterval;    % mean random interval=k
+    clickTime=round(time+intervalx1)+1;
+    signal(clickTime:clickTime+clickWidthNpoints-1)=clickHeight;
+    time=time+intervalx1;
+end
+
+signal=signal(1:signalLength);
+% figure(1),	plot(dt:dt:duration,signal)
+
+%-----------------------------------------------------makeABxClicks
+function signal=makeABxClicks(globalStimParams, stimComponents)
+% Generates a sequence of clicks with intervals ABx
+% AB interval is 2*k
+% where A= rand* k
+%       B= k-A
+%       x= rand*2*k
+% These are second order clicks
+
+FS=globalStimParams.FS; % sample rate
+dt=1/FS;
+
+% obligatory parameter
+try
+    k=stimComponents.k;
+catch
+    error('PressnitzerClicks: field ''k'' is missing from stimcomponent')
+end
+
+% optional parameters
+if isfield(stimComponents,'clickWidth')
+    clickWidth=stimComponents.clickWidth;
+else
+    clickWidth=dt;
+end
+clickWidthNpoints=round(clickWidth*FS);
+
+if isfield(stimComponents,'clickHeight')
+    clickHeight=stimComponents.clickHeight;
+else
+    clickHeight=28e-6 * 10^(stimComponents.amplitudesdB/20);
+end
+
+duration=stimComponents.toneDuration;
+
+signalLength=round(duration/dt);
+signal=zeros(1,2*signalLength); % allow for overrun
+ABinterval=2*k/dt;
+randomInterval=ABinterval;
+signal(1)=clickHeight;
+timeIdx=0;
+while timeIdx<signalLength
+    % first interval = A
+    intervalA=round(rand*ABinterval);
+    clickTime=timeIdx+intervalA+1;
+    signal(clickTime:clickTime+clickWidthNpoints-1)=clickHeight;
+    timeIdx=timeIdx+intervalA;
+
+    % second interval = B
+    intervalB=round(ABinterval-intervalA);
+    clickTime=timeIdx+intervalB;
+    signal(clickTime:clickTime+clickWidthNpoints-1)=clickHeight;
+    timeIdx=timeIdx+intervalB;
+
+    % third interval = 0 : k
+    intervalx1=round(rand*randomInterval);    % mean random interval=k
+    clickTime=timeIdx+intervalx1;
+    signal(clickTime:clickTime+clickWidthNpoints-1)=clickHeight;
+    timeIdx=timeIdx+intervalx1;
+end
+
+signal=signal(1:signalLength);
+% figure(1),	plot(dt:dt:duration,signal)
+
+%----------------------------------------------------------------makeYostClicks
+function signal=makeYostClicks(globalStimParams, stimComponents)
+% Generates a shuffled sequence of clicks with intervals kxxxx
+%  where max(x)= 2*k
+%  and there are n occurrences of x
+% this section requires:
+%  stimComponents.k
+%  stimComponents.nXs
+%  stimComponents.toneDuration
+% optional:
+%  stimComponents.clickWidth	%useful because width depends on dt
+%  stimComponents.clickHeight	%best left to amplitude rescaling later
+
+FS=globalStimParams.FS; % sample rate
+dt=1/FS;
+
+% obligatory parameters
+try
+    k=stimComponents.k;
+catch
+    error('makeYostClicks: field ''k'' is missing from stimComponents')
+end
+
+try
+    nXs=stimComponents.nXs;
+catch
+    error('makeYostClicks: field ''nXs'' is missing from stimComponents')
+end
+
+try
+    shuffled=stimComponents.shuffled;
+catch
+    error('makeYostClicks: field ''shuffled'' is missing from stimComponents')
+end
+
+try
+    duration=stimComponents.toneDuration;
+catch
+    error('makeYostClicks: field ''toneDuration'' is missing from stimComponents')
+end
+
+% optional parameters
+if isfield(stimComponents,'clickWidth')
+    clickWidth=stimComponents.clickWidth;
+else
+    clickWidth=dt;
+end
+clickWidthNpoints=round(clickWidth*FS);
+
+if isfield(stimComponents,'clickHeight')
+    clickHeight=stimComponents.clickHeight;
+else
+    clickHeight=28e-6 * 10^(stimComponents.amplitudesdB/20);
+end
+
+kInterval=round(k/dt);
+twoK=k*2;				% max width of x interval
+
+signalLength=round(duration/dt);
+signal=zeros(1,signalLength);
+
+timeIdx=0;
+intervalCount=0;
+while timeIdx<signalLength
+    timeIdx=timeIdx+kInterval;
+    if timeIdx>signalLength, break,end
+    intervalCount=intervalCount+1;
+    intervals(intervalCount)=kInterval;
+
+    % repeat x intervals as required
+    if nXs>0
+        for nX=1:nXs
+            xInterval=round(rand*twoK/dt);
+            timeIdx=timeIdx+xInterval;
+            if timeIdx>signalLength, break,end
+            intervalCount=intervalCount+1;
+            intervals(intervalCount)=xInterval;
+        end
+    end
+    if timeIdx>signalLength, break,end
+end
+
+% shuffle intervals
+if shuffled
+    randomNumbers=rand(1,length(intervals));
+    [randomNumbers idx]=sort(randomNumbers);
+    intervals=intervals(idx);
+    idx=intervals>0;
+    intervals=intervals(idx);
+end
+
+intervalCount=length(intervals);
+signal(1)=clickHeight;
+clickTime=0;
+for i=1:intervalCount
+    clickTime=clickTime+intervals(i);
+    signal(clickTime:clickTime+clickWidthNpoints)=clickHeight;
+end
+signal=signal(1:signalLength);
+%  figure(1),	plot(dt:dt:duration,signal)
+
+%--------------------------------------------------------------------makeKxxClicks
+function signal=makeKxxClicks(globalStimParams, stimComponents)
+% Click train consists of kkxxx.. sequences
+% k is the duration of a fixed interval (seconds)
+% random intervals are distributed 0 : 2* k (NB not like Pressnitzer clicks)
+% nKs is the number of successive 'k' intervals
+% nXs is the number of random intervals between k sequences
+% sequences of 3 x intervals > k are replaced with new sequences
+% shuffled causes all intervals to be reordered randomly
+% NB 1/k is the mean click rate
+
+FS=globalStimParams.FS; % sample rate
+dt=1/FS;
+
+try
+    k=stimComponents.k;		% duration (s) of fixed intervals
+catch
+    error('makeYostClicks: field ''k'' is missing from stimComponents')
+end
+
+try
+    duration=stimComponents.toneDuration;
+catch
+    error('makeYostClicks: field ''duration'' is missing from stimComponents')
+end
+
+if isfield(stimComponents,'clickWidth')
+    clickWidth=stimComponents.clickWidth;
+else
+    clickWidth=dt;
+end
+
+if isfield(stimComponents,'clickHeight')
+    clickHeight=stimComponents.clickHeight;
+else
+    clickHeight=28e-6 * 10^(stimComponents.amplitudesdB/20);
+end
+
+
+if isfield(stimComponents,'order')
+    order=stimComponents.order;
+else
+    order=1;
+end
+
+if isfield(stimComponents,'nKs')
+    nKs=stimComponents.nKs;
+else
+    nKs=1;
+end
+
+if isfield(stimComponents,'nXs')
+    nXs=stimComponents.nXs;
+else
+    nXs=1;
+end
+
+if isfield(stimComponents,'shuffled')
+    shuffled=stimComponents.shuffled;
+else
+    shuffled=1;
+end
+
+kLength=round(k/dt);    % fixed interval
+xLength=2*kLength;      % maximum random interval
+requiredSignalLength=round(duration/dt);
+intervalsPerCycle=(nKs+nXs);
+cycleLength=nKs*kLength+nXs*xLength;
+% more cycles to allow for uncertainty
+nCycles=5*round(requiredSignalLength/cycleLength);
+nIntervals=nCycles*intervalsPerCycle;
+
+% random intervals
+if nXs>0
+    xIntervals=floor(rand(1,nIntervals)*2*kLength);
+    % weed out triple intervals > 2*k
+    rogues=1;
+    while sum(rogues)
+        y=(xIntervals>kLength);
+        rogues=(sum([y(1:end-2)' y(2:end-1)' y(3:end)'],2)>2);
+        xIntervals(rogues)=floor(rand*2*kLength);
+    end
+    xIntervals=reshape(xIntervals,nCycles,intervalsPerCycle);
+else
+    xIntervals=[];
+end
+
+% insert constrained (k) intervals
+if nKs>0
+    switch order
+        case 1
+            kIntervals=floor(ones(nCycles,nKs)*kLength);
+        case 2
+            nKs=1; % force this
+            kIntervals=floor(rand(nCycles,1)*kLength);
+            kIntervals=[kIntervals kLength-kIntervals];
+    end
+else
+    kIntervals=[];
+end
+
+% combine fixed and random
+intervals=[kIntervals xIntervals(:,nKs+1:end)];
+% make a single array;
+[r c]=size(intervals);
+intervals=reshape(intervals',1,r*c);
+
+% shuffle intervals
+if shuffled
+    randomNumbers=rand(1,length(intervals));
+    [randomNumbers idx]=sort(randomNumbers);
+    intervals=intervals(idx);
+    idx=intervals>0;
+    intervals=intervals(idx);
+end
+
+% convert intervals to clicks
+clickTimes=cumsum(intervals);
+signal(clickTimes)=clickHeight;
+signal=signal(1:requiredSignalLength);
+% figure(1), clf, plot(signal)
+
+
+
+%--------------------------------------------------------------------makeNoise
+function noise=makeNoise(globalStimParams, stimComponents)
+% FS in Hz, noiseDuration in s, delay in s;
+% noise is returned with overall level dB(rms) = amplitudesdB
+%
+% % You need
+%
+% stim.type='noise'; % or 'IRN', or 'pinkNoise'
+% stim.toneDuration=.05;
+% stim.amplitudesdB=50;
+% stim.beginSilence=.01;
+% stim.endSilence=-1;
+% stim.rampOnDur=.002;
+% stim.rampOffDur=-1;
+%
+% % Mandatory structure fields
+% globalStimParams.FS=100000;
+% globalStimParams.overallDuration=.1;  % s
+% globalStimParams.doPlot=1;
+% globalStimParams.doPlay=1;
+%
+% [audio, msg]=stimulusCreate(globalStimParams, stim, );
+%
+% % local
+% stim.type='noise'; % or 'IRN'
+%
+FS=globalStimParams.FS;
+noiseDuration= stimComponents.toneDuration;
+npts=round(noiseDuration*FS);
+noise=randn(1,npts);    % NB randn (normally distributed)
+
+switch stimComponents.type
+    case  'pinkNoise'
+        %         noise=UTIL_lowpassFilterFreq(noise, 100, 1/FS);
+        noise=UTIL_bandPassFilter(noise, 1, 100, 200, 1/FS,[]);
+end
+
+rms=(mean(noise.^2)^.5);  %should be 20 microPascals for 0 dB SPL
+adjust=20e-6/rms;
+noise=noise*adjust;
+rms=(mean(noise.^2)^.5);
+amplitude=10.^(stimComponents.amplitudesdB/20);
+noise=amplitude*noise;
+% rms=(mean(noise.^2)^.5);
+% dBnoise=20*log10(rms/20e-6)
+
+
+%--------------------------------------------------------------------makeWhiteNoise
+function noise=makeWhiteNoise(globalStimParams, stimComponents)
+% FS in Hz, noiseDuration in s, delay in s;
+% noise is bandpass filtered between 100 and 10000 Hz
+% spectrum level (dB/Hz) is 40 dB below nominal level.
+% noise is returned with dB(rms) = amplitudesdB
+%
+% % You need
+%
+% stim.type='noise'; % or 'IRN', or 'pinkNoise'
+% stim.toneDuration=.05;
+% stim.amplitudesdB=50;
+% stim.beginSilence=.01;
+% stim.endSilence=-1;
+% stim.rampOnDur=.002;
+% stim.rampOffDur=-1;
+%
+% % Mandatory structure fields
+% globalStimParams.FS=100000;
+% globalStimParams.overallDuration=.1;  % s
+% globalStimParams.doPlot=1;
+% globalStimParams.doPlay=1;
+%
+% [audio, msg]=stimulusCreate(globalStimParams, stim, );
+%
+% % local
+% stim.type='noise'; % or 'IRN'
+%
+FS=globalStimParams.FS;
+noiseDuration= stimComponents.toneDuration;
+npts=round(noiseDuration*FS);
+noise=randn(1,npts);
+
+noise=UTIL_bandPassFilter (noise, 6, 100, 10000, 1/FS, []);
+
+rms=(mean(noise.^2)^.5);  %should be 20 microPascals for 0 dB SPL
+adjust=20e-6/rms;
+noise=noise*adjust;
+rms=(mean(noise.^2)^.5);
+amplitude=10.^(stimComponents.amplitudesdB/20);
+noise=amplitude*noise;
+% rms=(mean(noise.^2)^.5);
+% dBnoise=20*log10(rms/20e-6)
+
+
+%-----------------------------------------------------------------makeIRN
+function noise=makeIRN(globalStimParams, stimComponents)
+% FS in Hz, noiseDuration in s, delay in s;
+% noise is returned with dB(rms) = amplitudesdB
+%
+% % You need
+%
+% stim.type='noise'; % or 'IRN', or 'pinkNoise'
+% stim.toneDuration=.05;
+% stim.amplitudesdB=50;
+% stim.beginSilence=.01;
+% stim.endSilence=-1;
+% stim.rampOnDur=.002;
+% stim.rampOffDur=-1;
+%
+% % Mandatory structure fields
+% globalStimParams.FS=100000;
+% globalStimParams.overallDuration=.1;  % s
+% globalStimParams.doPlot=1;
+% globalStimParams.doPlay=1;
+%
+% [audio, msg]=stimulusCreate(globalStimParams, stim, );
+%
+% % local
+% stim.type='noise'; % or 'IRN'
+% % for IRN only
+% stim.niterations = 8;   %0 for white noise
+% stim.delay = 1/150;
+% stim.irnGain = 1;
+%
+FS=globalStimParams.FS;
+noiseDuration= stimComponents.toneDuration;
+
+nIterations=stimComponents.niterations;
+if nIterations==0
+    % white noise is specified as nIterations=1
+    nIterations=1;
+    IRNgain=0;
+    delay=0.01; % dummy
+else
+    % IRN
+    delay=stimComponents.delay;
+    IRNgain=stimComponents.irnGain;
+end
+
+npts=round(noiseDuration*FS);
+dels=round(delay*FS);
+noise=randn(1,npts);
+
+%fringe=nIterations*dels;
+%npts=npts+fringe;
+
+for i=1:nIterations,
+    dnoise=[noise(dels+1:npts) noise(1:dels)];
+    dnoise=dnoise.*IRNgain;
+    noise=noise+dnoise;
+end;
+
+switch stimComponents.type
+    case  'pinkNoise'
+        noise=UTIL_lowpassFilterFreq(noise, 10000, 1/FS);
+end
+
+rms=(mean(noise.^2)^.5);  %should be 20 microPascals for 0 dB SPL
+adjust=20e-6/rms;
+noise=noise*adjust;
+rms=(mean(noise.^2)^.5);
+amplitude=10.^(stimComponents.amplitudesdB/20);
+noise=amplitude*noise;
+% rms=(mean(noise.^2)^.5);
+% dBnoise=20*log10(rms/20e-6)
+
+%------------------------------------------------------------------ makeRPN
+function RPN=makeRPN(globalStimParams, stim)
+% 'period' is a collection of samples - AAABCD
+% you need
+%
+% stim.type='RPN';
+% stim.toneDuration=.2;
+% stim.amplitudesdB=50;
+% stim.beginSilence=.01;
+% stim.rampOnDur=.002;
+% stim.rampOffDur=-1;
+%
+% stim.sampleDuration=.005;  %200 Hz pitch
+% stim.nSimilarSamples=5;   % pitch strength
+% stim.nIndependentSamples=1% dilutes strength
+%
+% % Mandatory structure fields
+%  globalStimParams.FS=44100;
+%  globalStimParams.overallDuration=.21;  % s
+%
+% globalStimParams.doPlot=1;
+% globalStimParams.doPlay=1;
+% [audio, msg]=stimulusCreate(globalStimParams, stim);
+
+FS=globalStimParams.FS;
+ptsPerSample=floor(stim.sampleDuration*FS);
+
+samplesPerPeriod=stim.nSimilarSamples+stim.nIndependentSamples;
+periodDuration=samplesPerPeriod*stim.sampleDuration;
+
+totalNumPeriods=2*floor(stim.toneDuration/periodDuration);  % longer than necessary
+if totalNumPeriods<1
+    error('stimulusCreate: RPN, stimulus duration needs to be longer')
+end
+
+RPN=[];
+for j=1:totalNumPeriods
+    noise=randn(1,ptsPerSample);
+    for i=1:stim.nSimilarSamples
+        RPN=[RPN noise];
+    end
+
+    for i=1:stim.nIndependentSamples
+        noise=randn(1,ptsPerSample);
+        RPN=[RPN noise];
+    end
+end
+
+targetStimulusLength=round(stim.toneDuration/FS);
+RPN=RPN(1:floor(stim.toneDuration*FS));     % take enough for stimulus
+
+rms=(mean(RPN.^2)^.5);  %should be 20 microPascals for 0 dB SPL
+adjust=20e-6/rms;
+RPN=RPN*adjust;
+rms=(mean(RPN.^2)^.5);
+amplitude=10.^(stim.amplitudesdB/20);
+RPN=amplitude*RPN;
+% rms=(mean(noise.^2)^.5);
+% dBnoise=20*log10(rms/20e-6)
+
+%--------------------------------------------------------------------applyRampOn
+function signal=applyRampOn(signal, rampDur, rampOnTime, sampleRate)
+%applyRampOn applies raised cosine ramp
+%rampOntime is the time at which the ramp begins
+%At all other times the mask has a value of 1
+%signal=applyRampOn(signal, rampDur, rampOnTime, sampleRate)
+
+rampDurPoints=round(rampDur*sampleRate);
+rampOn= (1+cos(pi:pi/(rampDurPoints-1): 2*pi))/2';
+
+sigDurPoints=length(signal);
+mask(1:sigDurPoints)=1;
+rampOnStartIndex=round(rampOnTime*sampleRate+1);
+mask(rampOnStartIndex: rampOnStartIndex+ rampDurPoints-1)=rampOn;
+signal=signal.*mask;
+%plot(mask)
+
+%--------------------------------------------------------------------applyRampOff
+function signal=applyRampOff(signal, rampDur, rampOffTime, sampleRate)
+%applyRampOn applies raised cosine squared ramp
+%rampOffTime is the time at which the ramp begins
+%At all other times the mask has a value of 1
+% signal=applyRampOff(signal, rampDur, rampOffTime, sampleRate)
+
+rampDurPoints=round(rampDur*sampleRate);
+rampOff= (1+cos(0:pi/(rampDurPoints-1): pi))/2';
+
+sigDurPoints=length(signal);
+mask=ones(1,sigDurPoints);
+rampOffStartIndex=round(rampOffTime*sampleRate+1);
+mask(rampOffStartIndex: round(rampOffStartIndex+ rampDurPoints-1))=rampOff;
+if length(mask)>sigDurPoints, mask=mask(1:sigDurPoints); end
+signal=signal.*mask;
+%plot(mask)
+
+function signal=applyGaussianRamps(signal, sigma, sampleRate)
+dt=1/sampleRate;
+time=dt:dt:dt*length(signal);
+ramp=1-exp(-time.^2/(2*sigma^2));
+% apply onset ramp
+signal=signal.*ramp;
+% apply offset ramp
+ramp=fliplr(ramp);
+signal=signal.*ramp;
+
+
+
+%--------------------------------------------------------------------checkDescriptors
+function [globalStimParams, stimComponents]=checkDescriptors(globalStimParams, stimComponents);
+
+try
+    % if FS exists, it takes priority
+    globalStimParams.dt=1/globalStimParams.FS;
+catch
+    % otherwise set FS using dt
+    globalStimParams.FS=1/globalStimParams.dt;
+end
+
+globalStimParams.nSignalPoints=round(globalStimParams.overallDuration/globalStimParams.dt);
+
+% optional field (ears)
+try
+    globalStimParams.ears;
+catch
+    % default: dichotic.
+    globalStimParams.ears='dichotic';
+end
+
+% audioOutCorrection is optional
+% audioOutCorrection is a scalar for reducing the sound
+try
+    globalStimParams.audioOutCorrection;
+catch
+    %      set to 1 if omitted
+    globalStimParams.audioOutCorrection=1;
+end
+
+try
+    globalStimParams.doPlay;
+catch
+    % default plays sound only if explicitly requested
+    globalStimParams.doPlay=0;
+end
+
+try
+    globalStimParams.doPlot;
+catch
+    % no plotting unless explicitly requested
+    globalStimParams.doPlot=0;
+end
+
+
+
+[ears nComponentSounds]=size(stimComponents);
+
+for ear=1:2 % 1=left/ 2=right
+
+    % create a list of components whose type is specified
+    % if no type is specified assume that it is an empty specification
+    % this is allowed
+    validStimComponents=[];
+    for i=1:nComponentSounds
+        try
+            if ~isempty(stimComponents(ear,i).type)
+                validStimComponents=[validStimComponents i];
+            end
+        catch
+        end
+    end
+
+    for componentNo=validStimComponents
+        % If no AM filed is present, create it for completeness
+        if ~isfield(stimComponents(ear,componentNo),'AMfrequency') |...
+                ~isfield(stimComponents(ear,componentNo),'AMdepth')
+            stimComponents(ear,componentNo).AMfrequency=0;
+            stimComponents(ear,componentNo).AMdepth=0;
+        end
+
+        % all signals must have durations, amplitudes and ramps
+        if ...
+                isempty(stimComponents(ear,componentNo).type) |...
+                isempty(stimComponents(ear,componentNo).toneDuration) |...
+                isempty(stimComponents(ear,componentNo).amplitudesdB) |...
+                isempty(stimComponents(ear,componentNo).rampOnDur)
+            descriptorError( 'missing stimComponent descriptor', stimComponents, ear, componentNo)
+        end
+
+        try, stimComponents(ear,componentNo).endSilence; catch, stimComponents(ear,componentNo).endSilence=-1; end
+
+        % ramp checks do not apply to file input
+        if ~strcmp(stimComponents(ear,componentNo).type, 'file')
+            % match offset ramp to onset if not explicitly specified
+            if stimComponents(ear,componentNo).rampOffDur==-1,
+                stimComponents(ear,componentNo).rampOffDur=stimComponents(ear,componentNo).rampOnDur;
+            end
+            % ramps must be shorter than the stimulus
+            if stimComponents(ear,componentNo).rampOffDur> stimComponents(ear,componentNo).toneDuration | ...
+                    stimComponents(ear,componentNo).rampOnDur> stimComponents(ear,componentNo).toneDuration
+                descriptorError( 'ramp longer than sound component', stimComponents, ear, componentNo)
+            end
+        end
+
+        % end silence is measured to fit into the global duration
+        if stimComponents(ear,componentNo).endSilence==-1,
+            endSilenceNpoints=...
+                globalStimParams.nSignalPoints ...
+                -round(stimComponents(ear,componentNo).beginSilence*globalStimParams.FS)...
+                -round(stimComponents(ear,componentNo).toneDuration*globalStimParams.FS);
+            stimComponents(ear,componentNo).endSilence=endSilenceNpoints/globalStimParams.FS;
+            % if endSilence < 0, we have a problem
+            if stimComponents(ear,componentNo).endSilence<0
+                globalStimParams
+                descriptorError( 'component durations greater than overallDuration', stimComponents, ear, componentNo)
+            end
+        end
+
+        % check overall duration of this component against global duration
+        totalDuration= ...
+            stimComponents(ear,componentNo).beginSilence+...
+            stimComponents(ear,componentNo).toneDuration+...
+            stimComponents(ear,componentNo).endSilence;
+
+        % avoid annoying error message for single stimulus component
+        if ears==1 && nComponentSounds==1
+            globalStimParams.overallDuration= totalDuration;
+        end
+
+
+        if round(totalDuration*globalStimParams.FS)>round(globalStimParams.overallDuration*globalStimParams.FS)
+            globalStimParams
+            descriptorError( 'Component durations greater than overallDuration', stimComponents, ear, componentNo)
+        end
+
+        % check total duration
+        totalSignalPoints= round((stimComponents(ear,componentNo).beginSilence+ stimComponents(ear,componentNo).toneDuration+...
+            stimComponents(ear,componentNo).endSilence)/globalStimParams.dt);
+        if totalSignalPoints  >globalStimParams.nSignalPoints
+            descriptorError( 'Signal component duration does not match overall duration ', stimComponents, ear, componentNo)
+        end
+
+        % no ramps for clicks please!
+        %         if strcmp(stimComponents(ear,componentNo).type, 'clicks') & stimComponents(ear,componentNo).clickRepeatFrequency==-1
+        %         if strcmp(stimComponents(ear,componentNo).type, 'clicks')
+        %             stimComponents(ear,componentNo).rampOnDur=0;
+        %             stimComponents(ear,componentNo).rampOffDur=0;
+        %         end
+
+        if isfield(stimComponents(ear,componentNo), 'filter')
+            if ~isequal(length(stimComponents(ear,componentNo).filter), 3)
+                descriptorError( 'Filter parameter must have three elements ', stimComponents, ear, componentNo)
+            end
+        end
+    end % component
+    % ??
+    if strcmp(globalStimParams.ears,'monoticL') | strcmp(globalStimParams.ears, 'monoticR'), break, end
+end		% ear
+
+
+%-------------------------------------------------------------------- descriptorError
+function descriptorError( msg, stimComponents, ear, componentNo)
+stimComponents(ear, componentNo)
+
+disp(' *********** **************** ************')
+disp([ '...Error in stimComponents description: '])
+disp([msg ])
+disp(['Ear = ' num2str(ear) ' component No ' num2str(componentNo)])
+disp(' *********** **************** ************')
+error('myError ')
+
+
+%-------------------------------------------------------------------- normalize
+function [normalizedSignal, gain]= normalize(signal)
+% normalize (signal)
+maxSignal=max(max(signal));
+minSignal=min(min(signal));
+if -minSignal>maxSignal, normalizingFactor=-minSignal; else normalizingFactor=maxSignal; end
+normalizingFactor=1.01*normalizingFactor;
+gain= 20*log10(normalizingFactor);
+normalizedSignal=signal/normalizingFactor;
+
+
+%--------------------------------------------------------------------Butterworth
+function y=Butterworth (x, dt, fl, fu, order)
+% Butterworth (x, dt, fu, fl, order)
+% Taken from Yuel and beauchamp page 261
+% NB error in their table for K (see their text)
+% x is original signal
+% fu, fl upper and lower cutoff
+% order is the number of times the filter is applied
+
+q=(pi*dt*(fu-fl));
+J=1/(1+ cot(q));
+K= (2*cos(pi*dt*(fu+fl)))/(1+tan(q)*cos(q));
+L= (tan(q)-1)/(tan(q)+1);
+b=[J -J];
+a=[1 -K  -L];
+for i=1:order
+    y=filter(b, a, x);
+    x=y;
+end
+
+
+% -------------------------------------------------------- UTIL_amp2dB
+function [y] = UTIL_amp2dB (x, ref)
+% Calculates a dB (ref. ref) value 'y' from a peak amplitude number 'x'.
+% if ref omitted treat as dB
+% Check the number of arguments that are passed in.
+if (nargin < 2)
+    ref=1;
+end
+if (nargin > 2)
+    error ('Too many arguments');
+end
+
+% Check arguments.
+if x < 0.0
+    error ('Can not calculate the log10 of a negative number');
+elseif x == 0.0
+    warning ('log10 of zero.  The result is set to -1000.0');
+    y = -1000.0;
+else
+    % Do calculations.
+    y = 20.0 * log10(x/(sqrt(2)*ref));
+
+end
+
+%-------------------------------------------------------------------- FFT
+function showFFT (getFFTsignal, dt)
+color='r';
+figure(2), clf,
+hold off
+
+% trim initial silence
+idx=find(getFFTsignal>0);
+if ~isempty(idx)
+    getFFTsignal=getFFTsignal(idx(1):end);
+end
+%trim final silence
+getFFTsignal=getFFTsignal(end:-1:1);
+idx=find(getFFTsignal>0);
+if ~isempty(idx)
+    getFFTsignal=getFFTsignal(idx(1):end);
+    getFFTsignal=getFFTsignal(end:-1:1);
+end
+
+% Analyse make stimComponents length a power of 2
+x=length(getFFTsignal);
+squareLength=2;
+while squareLength<=x
+    squareLength=squareLength*2;
+end
+squareLength=round(squareLength/2);
+getFFTsignal=getFFTsignal(1:squareLength);
+n=length(getFFTsignal);
+
+minf=100; maxf=20000;
+
+fft_result = fft(getFFTsignal, n);				% Compute FFT of the input signal.
+fft_power = fft_result .* conj(fft_result);% / n;	% Compute power spectrum.  Dividing by 'n' we get the power spectral density.
+fft_phase = angle(fft_result);			% Compute the phase spectrum.
+
+frequencies = (1/dt)*(1:n/2)/n;
+fft_power=fft_power(1:length(fft_power)/2); % remove mirror frequencies
+fft_phase=fft_phase(1:length(fft_phase)/2); % remove mirror frequencies
+fft_powerdB = UTIL_amp2dB (fft_power, max(fft_power)); % convert to dB
+%     jags=find(diff(fft_phase)>0); % unwrap phase
+%     for i=jags, fft_phase(i+1:end)=fft_phase(i+1:end)-2*pi; end
+
+xlim([minf maxf])
+semilogx(frequencies, fft_powerdB-max(fft_powerdB), color)
+ylim([ -20 5])
+
+
+
+function y=UTIL_lowpassFilterFreq(x, cutOffFrequency, dt)
+% UTIL_lowpassFilterFreq multi-channel filter
+%
+% Usage:
+% output=UTIL_lowpassFilterFreq(input, cutOffFrequency, dt)
+%
+% cutoff should be around 100 Hz for audio work
+% dt should be <1/50000 s for audio work
+%
+% Attenuation 	       is - 6 dB per octave above cutoff.
+
+
+sampleRate=1/dt;
+
+if 4*cutOffFrequency>sampleRate
+    warning(['UTIL_lowpassFilterFreq: sample rate ' num2str(1/dt) ' is too low for this BF.  Sampling rate should be >' num2str(4*cutOffFrequency) 'or cutoff (' num2str(4*cutOffFrequency) ') should be lower' ])
+    cutOffFrequency=sampleRate/4;
+end
+
+tau=1/(2*pi*cutOffFrequency);
+
+y=zeros(size(x));
+[numChannels numPoints]=size(x);
+for i=1:numChannels
+    y(i,:)=filter([dt/tau], [1 -(1-dt/tau)], x(i,:));
+end
+
+
Binary file wavFileStore/new-ba-44khz.wav has changed
Binary file wavFileStore/new-da-44khz.wav has changed
Binary file wavFileStore/new-da-44khz_olde.wav has changed
Binary file wavFileStore/twister_44kHz.wav has changed
Binary file ~$P1_14 quick reference.doc has changed