def getStandardPriors(data, options): """sets the standard Priors function priors = getStandardPriors(data,options) The priors set here are the ones used if the user does supply own priors. Thus this functions constitutes a way to change the priors permanently note here that the priors here are not normalized. Psignifit takes care of the normalization implicitly. """ priors = [] """ threshold """ xspread = options['stimulusRange'][1]-options['stimulusRange'][0] ''' we assume the threshold is in the range of the data, for larger or smaller values we tapre down to 0 with a raised cosine across half the dataspread ''' priors.append(lambda x: prior1(x,xspread,options['stimulusRange'])) """width""" # minimum = minimal difference of two stimulus levels widthmin = options['widthmin'] widthmax = xspread ''' We use the same prior as we previously used... e.g. we use the factor by which they differ for the cumulative normal function''' Cfactor = (my_norminv(.95,0,1) - my_norminv(.05,0,1))/( my_norminv(1-options['widthalpha'],0,1) - my_norminv(options['widthalpha'],0,1)) priors.append(lambda x: prior2(x,Cfactor, widthmin, widthmax)) """ asymptotes set asymptote prior to the 1, 10 beta prior, which corresponds to the knowledge obtained from 9 correct trials at infinite stimulus level """ priors.append(lambda x: my_betapdf(x,1,10)) priors.append(lambda x: my_betapdf(x,1,10)) """ sigma """ be = options['betaPrior'] priors.append(lambda x: my_betapdf(x,1,be)) return priors def __call__(self): import sys return getStandardPriors(sys.argv[1], sys.argv[2])
def getStandardPriors(data, options): """sets the standard Priors function priors = getStandardPriors(data,options) The priors set here are the ones used if the user does supply own priors. Thus this functions constitutes a way to change the priors permanently note here that the priors here are not normalized. Psignifit takes care of the normalization implicitly. """ priors = [] """ threshold """ xspread = options['stimulusRange'][1] - options['stimulusRange'][0] ''' we assume the threshold is in the range of the data, for larger or smaller values we tapre down to 0 with a raised cosine across half the dataspread ''' priors.append(lambda x: prior1(x, xspread, options['stimulusRange'])) """width""" # minimum = minimal difference of two stimulus levels widthmin = options['widthmin'] widthmax = xspread ''' We use the same prior as we previously used... e.g. we use the factor by which they differ for the cumulative normal function''' Cfactor = (my_norminv(.95, 0, 1) - my_norminv(.05, 0, 1)) / ( my_norminv(1 - options['widthalpha'], 0, 1) - my_norminv(options['widthalpha'], 0, 1)) priors.append(lambda x: prior2(x, Cfactor, widthmin, widthmax)) """ asymptotes set asymptote prior to the 1, 10 beta prior, which corresponds to the knowledge obtained from 9 correct trials at infinite stimulus level """ priors.append(lambda x: my_betapdf(x, 1, 10)) priors.append(lambda x: my_betapdf(x, 1, 10)) """ sigma """ be = options['betaPrior'] priors.append(lambda x: my_betapdf(x, 1, be)) return priors def __call__(self): import sys return getStandardPriors(sys.argv[1], sys.argv[2])
def setBorders(data,options): """ automatically set borders on the parameters based on were you sampled. function Borders=setBorders(data,options) this function sets borders on the parameter values of a given function automaically It sets: -the threshold to be within the range of the data +/- 50% -the width to half the distance of two datapoints up to 10 times the range of the data -the lapse rate to 0 to .5 -the lower asymptote to 0 to .5 or fix to 1/n for nAFC -the varscale to the full range from almost 0 to almost 1 """ widthmin = options['widthmin'] # lapse fix to 0 - .5 lapseB = np.array([0,.5]) if options['expType'] == 'nAFC': gammaB = np.array([1/options['expN'], 1/options['expN']]) elif options['expType'] == 'YesNo': gammaB = np.array([0, .5]) elif options['expType'] == 'equalAsymptote': gammaB = np.array([np.nan, np.nan]) # varscale from 0 to 1, 1 excluded! varscaleB = np.array([0, 1-np.exp(-20)]) # if range was not given take from data '''if options['stimulusRange'].size <= 1 : options['stimulusRange'] = np.array([min(data[:,0]), max(data[:,0])]) stimRangeSet = False else: stimRangeSet= True if options['logspace']: options['stimulusRange'] = np.log(options['stimulusRange']) ''' ''' We then assume it is one of the reparameterized functions with alpha=threshold and beta= width The threshold is assumed to be within the range of the data +/- .5 times it's spread ''' dataspread = np.diff(options['stimulusRange']) alphaB = np.array([options['stimulusRange'][0] - .5*dataspread, options['stimulusRange'][1] +.5*dataspread]).squeeze() ''' the width we assume to be between half the minimal distance of two points and 5 times the spread of the data if len(np.unique(data[:,0])) > 1 and not(stimRangeSet): widthmin = np.min(np.diff(np.sort(np.unique(data[:,0])))) else : widthmin = 100*np.spacing(options['stimulusRange'][1]) ''' ''' We use the same prior as we previously used... e.g. we use the factor by which they differ for the cumulative normal function ''' Cfactor = (my_norminv(.95,0,1) - my_norminv(.05, 0,1))/(my_norminv(1- options['widthalpha'], 0,1) - my_norminv(options['widthalpha'], 0,1)) betaB = np.array([widthmin, 3/Cfactor*dataspread]) borders =[[alphaB], [betaB], [lapseB], [gammaB], [varscaleB]] borders = np.array(borders).squeeze() return borders
def plotPrior(result, lineWidth = 2, lineColor = np.array([0,105,170])/255, markerSize = 30): """ This function creates the plot illustrating the priors on the different parameters """ data = result['data'] if np.size(result['options']['stimulusRange']) <= 1: result['options']['stimulusRange'] = np.array([min(data[:,0]), max(data[:,0])]) stimRangeSet = False else: stimRangeSet = True stimRange = result['options']['stimulusRange'] r = stimRange[1] - stimRange[0] # get borders for width # minimum = minimal difference of two stimulus levels if len(np.unique(data[:,0])) > 1 and not(stimRangeSet): widthmin = min(np.diff(np.sort(np.unique(data[:,0])))) else: widthmin = 100*np.spacing(stimRange[1]) # maximum = spread of the data # We use the same prior as we previously used... e.g. we use the factor by # which they differ for the cumulative normal function Cfactor = (my_norminv(.95,0,1) - my_norminv(.05,0,1))/ \ (my_norminv(1-result['options']['widthalpha'], 0,1) - \ my_norminv(result['options']['widthalpha'], 0,1)) widthmax = r steps = 10000 theta = np.empty(5) for itheta in range(0,5): if itheta == 0: x = np.linspace(stimRange[0]-.5*r, stimRange[1]+.5*r, steps) elif itheta == 1: x = np.linspace(min(result['X1D'][itheta]), max(result['X1D'][1],),steps) elif itheta == 2: x = np.linspace(0,.5,steps) elif itheta == 3: x = np.linspace(0,.5,steps) elif itheta == 4: x = np.linspace(0,1,steps) y = result['options']['priors'][itheta](x) theta[itheta] = np.sum(x*y)/np.sum(y) if result['options']['expType'] == 'equalAsymptote': theta[3] = theta[2] if result['options']['expType'] == 'nAFC': theta[3] = 1/result['options']['expN'] # get limits for the psychometric function plots xLimit = [stimRange[0] - .5*r , stimRange[1] +.5*r] """ threshold """ xthresh = np.linspace(xLimit[0], xLimit[1], steps ) ythresh = result['options']['priors'][0](xthresh) wthresh = convn(np.diff(xthresh), .5*np.array([1,1])) cthresh = np.cumsum(ythresh*wthresh) plt.subplot(2,3,1) plt.plot(xthresh,ythresh, lw = lineWidth, c= lineColor) plt.hold(True) plt.xlim(xLimit) plt.title('Threshold', fontsize = 18) plt.ylabel('Density', fontsize = 18) plt.subplot(2,3,4) plt.plot(data[:,0], np.zeros(data[:,0].shape), 'k.', ms = markerSize*.75 ) plt.hold(True) plt.ylabel('Percent Correct', fontsize = 18) plt.xlim(xLimit) for idot in range(0,5): if idot == 0: xcurrent = theta[0] color = 'k' elif idot == 1: xcurrent = min(xthresh) color = [1,200/255,0] elif idot == 2: tix = cthresh[cthresh >=.25].size xcurrent = xthresh[-tix] color = 'r' elif idot == 3: tix = cthresh[cthresh >= .75].size xcurrent = xthresh[-tix] color = 'b' elif idot == 4: xcurrent = max(xthresh) color = 'g' y = 100*(theta[3]+(1-theta[2])-theta[3])*result['options']['sigmoidHandle'](x,xcurrent, theta[1]) plt.subplot(2,3,4) plt.plot(x,y, '-', lw=lineWidth,c=color ) plt.subplot(2,3,1) plt.plot(xcurrent, result['options']['priors'][0](xcurrent), '.',c=color, ms = markerSize) """ width""" xwidth = np.linspace(widthmin, 3/Cfactor*widthmax, steps) ywidth = result['options']['priors'][1](xwidth) wwidth = convn(np.diff(xwidth), .5*np.array([1,1])) cwidth = np.cumsum(ywidth*wwidth) plt.subplot(2,3,2) plt.plot(xwidth,ywidth,lw=lineWidth,c=lineColor) plt.hold(True) plt.xlim([widthmin,3/Cfactor*widthmax]) plt.title('Width',fontsize=18) plt.subplot(2,3,5) plt.plot(data[:,0],np.zeros(data[:,0].size),'k.',ms =markerSize*.75) plt.hold(True) plt.xlim(xLimit) plt.xlabel('Stimulus Level',fontsize=18) x = np.linspace(xLimit[0],xLimit[1],steps) for idot in range(0,5): if idot == 0: xcurrent = theta[1] color = 'k' elif idot == 1: xcurrent = min(xwidth) color = [1,200/255,0] elif idot == 2: wix = cwidth[cwidth >= .25].size xcurrent = xwidth[-wix] color = 'r' elif idot == 3: wix = cwidth[cwidth >= .75].size xcurrent = xwidth[-wix] color = 'b' elif idot ==4: xcurrent = max(xwidth) color = 'g' y = 100*(theta[3]+ (1-theta[2] -theta[3])* result['options']['sigmoidHandle'](x,theta[0],xcurrent)) plt.subplot(2,3,5) plt.plot(x,y,'-',lw = lineWidth, c= color) plt.subplot(2,3,2) plt.plot(xcurrent,result['options']['priors'][1](xcurrent),'.',c = color,ms=markerSize) """ lapse """ xlapse = np.linspace(0,.5,steps) ylapse = result['options']['priors'][2](xlapse) wlapse = convn(np.diff(xlapse),.5*np.array([1,1])) clapse = np.cumsum(ylapse*wlapse) plt.subplot(2,3,3) plt.plot(xlapse,ylapse,lw=lineWidth,c=lineColor) plt.hold(True) plt.xlim([0,.5]) plt.title('\lambda',fontsize=18) plt.subplot(2,3,6) plt.plot(data[:,0],np.zeros(data[:,0].size),'k.',ms=markerSize*.75) plt.hold(True) plt.xlim(xLimit) x = np.linspace(xLimit[0],xLimit[1],steps) for idot in range(0,5): if idot == 0: xcurrent = theta[2] color = 'k' elif idot == 1: xcurrent = 0 color = [1,200/255,0] elif idot == 2: lix = clapse[clapse >= .25].size xcurrent = xlapse[-lix] color = 'r' elif idot == 3: lix = clapse[clapse >= .75].size xcurrent = xlapse[-lix] color = 'b' elif idot ==4: xcurrent = .5 color = 'g' y = 100*(theta[3]+ (1-xcurrent-theta[3])*result['options']['sigmoidHandle'](x,theta[0],theta[1])) plt.subplot(2,3,6) plt.plot(x,y,'-',lw=lineWidth,c=color) plt.subplot(2,3,3) plt.plot(xcurrent,result['options']['priors'][2](xcurrent),'.',c=color,ms=markerSize) a_handle = plt.gca() a_handle.set_position([200,300,1000,600]) fig, ax = plt.subplots() for item in [fig, ax]: item.patch.set_visible(False)
if __name__ == "__main__": result = {} result['Fit'] = np.array([.004651, .004658, 1.7125E-7, .5, 1.0632E-4]) options = {} options['expType'] = 'nAFC' options['expN'] = 2 options['logspace'] = False options['threshPC'] = .5 from utils import my_normcdf alpha = .05 C = my_norminv(1-alpha,0,1)-my_norminv(alpha,0,1) options['sigmoidHandle'] = lambda X,m,width: my_normcdf(X, (m-my_norminv(.5,0,width/C)), width/C) tmp1 = np.array([10,15,20,25,30,35,40,45,50,60,70,80,100], dtype=float)/10000 tmp2 = np.array([45,50,44,44,52,53,62,64,76,79,88,90,90], dtype=float) tmp3 = np.array([90 for i in range(len(tmp1))], dtype=float) data = np.array([tmp1,tmp2,tmp3]).T result['data'] = data options['stimulusRange'] = 0 options['widthalpha'] = .05 options['betaPrior'] = 10 options['priors'] = [lambda x: [74.074074196287796 for i in range(len(x))]] result['options'] = options CIs = np.zeros((5,2,3))
def plotPrior(result, lineWidth=2, lineColor=np.array([0, 105, 170]) / 255, markerSize=30, showImediate=True): """ This function creates the plot illustrating the priors on the different parameters """ data = result['data'] if np.size(result['options']['stimulusRange']) <= 1: result['options']['stimulusRange'] = np.array( [min(data[:, 0]), max(data[:, 0])]) stimRangeSet = False else: stimRangeSet = True stimRange = result['options']['stimulusRange'] r = stimRange[1] - stimRange[0] # get borders for width # minimum = minimal difference of two stimulus levels if len(np.unique(data[:, 0])) > 1 and not (stimRangeSet): widthmin = min(np.diff(np.sort(np.unique(data[:, 0])))) else: widthmin = 100 * np.spacing(stimRange[1]) # maximum = spread of the data # We use the same prior as we previously used... e.g. we use the factor by # which they differ for the cumulative normal function Cfactor = (_utils.my_norminv(.95,0,1) - _utils.my_norminv(.05,0,1))/ \ (_utils.my_norminv(1-result['options']['widthalpha'], 0,1) - \ _utils.my_norminv(result['options']['widthalpha'], 0,1)) widthmax = r steps = 10000 theta = np.empty(5) for itheta in range(0, 5): if itheta == 0: x = np.linspace(stimRange[0] - .5 * r, stimRange[1] + .5 * r, steps) elif itheta == 1: x = np.linspace(min(result['X1D'][itheta]), max(result['X1D'][1], ), steps) elif itheta == 2: x = np.linspace(0, .5, steps) elif itheta == 3: x = np.linspace(0, .5, steps) elif itheta == 4: x = np.linspace(0, 1, steps) y = result['options']['priors'][itheta](x) theta[itheta] = np.sum(x * y) / np.sum(y) if result['options']['expType'] == 'equalAsymptote': theta[3] = theta[2] if result['options']['expType'] == 'nAFC': theta[3] = 1 / result['options']['expN'] # get limits for the psychometric function plots xLimit = [stimRange[0] - .5 * r, stimRange[1] + .5 * r] """ threshold """ xthresh = np.linspace(xLimit[0], xLimit[1], steps) ythresh = result['options']['priors'][0](xthresh) wthresh = _convn(np.diff(xthresh), .5 * np.array([1, 1])) cthresh = np.cumsum(ythresh * wthresh) plt.subplot(2, 3, 1) plt.plot(xthresh, ythresh, lw=lineWidth, c=lineColor) plt.hold(True) plt.xlim(xLimit) plt.title('Threshold', fontsize=18) plt.ylabel('Density', fontsize=18) plt.subplot(2, 3, 4) plt.plot(data[:, 0], np.zeros(data[:, 0].shape), 'k.', ms=markerSize * .75) plt.hold(True) plt.ylabel('Percent Correct', fontsize=18) plt.xlim(xLimit) x = np.linspace(xLimit[0], xLimit[1], steps) for idot in range(0, 5): if idot == 0: xcurrent = theta[0] color = 'k' elif idot == 1: xcurrent = min(xthresh) color = [1, 200 / 255, 0] elif idot == 2: tix = cthresh[cthresh >= .25].size xcurrent = xthresh[-tix] color = 'r' elif idot == 3: tix = cthresh[cthresh >= .75].size xcurrent = xthresh[-tix] color = 'b' elif idot == 4: xcurrent = max(xthresh) color = 'g' y = 100 * (theta[3] + ((1 - theta[2]) - theta[3]) * result['options']['sigmoidHandle'](x, xcurrent, theta[1])) plt.subplot(2, 3, 4) plt.plot(x, y, '-', lw=lineWidth, c=color) plt.subplot(2, 3, 1) plt.plot(xcurrent, result['options']['priors'][0](xcurrent), '.', c=color, ms=markerSize) """ width""" xwidth = np.linspace(widthmin, 3 / Cfactor * widthmax, steps) ywidth = result['options']['priors'][1](xwidth) wwidth = _convn(np.diff(xwidth), .5 * np.array([1, 1])) cwidth = np.cumsum(ywidth * wwidth) plt.subplot(2, 3, 2) plt.plot(xwidth, ywidth, lw=lineWidth, c=lineColor) plt.hold(True) plt.xlim([widthmin, 3 / Cfactor * widthmax]) plt.title('Width', fontsize=18) plt.subplot(2, 3, 5) plt.plot(data[:, 0], np.zeros(data[:, 0].size), 'k.', ms=markerSize * .75) plt.hold(True) plt.xlim(xLimit) plt.xlabel('Stimulus Level', fontsize=18) x = np.linspace(xLimit[0], xLimit[1], steps) for idot in range(0, 5): if idot == 0: xcurrent = theta[1] color = 'k' elif idot == 1: xcurrent = min(xwidth) color = [1, 200 / 255, 0] elif idot == 2: wix = cwidth[cwidth >= .25].size xcurrent = xwidth[-wix] color = 'r' elif idot == 3: wix = cwidth[cwidth >= .75].size xcurrent = xwidth[-wix] color = 'b' elif idot == 4: xcurrent = max(xwidth) color = 'g' y = 100 * (theta[3] + (1 - theta[2] - theta[3]) * result['options']['sigmoidHandle'](x, theta[0], xcurrent)) plt.subplot(2, 3, 5) plt.plot(x, y, '-', lw=lineWidth, c=color) plt.subplot(2, 3, 2) plt.plot(xcurrent, result['options']['priors'][1](xcurrent), '.', c=color, ms=markerSize) """ lapse """ xlapse = np.linspace(0, .5, steps) ylapse = result['options']['priors'][2](xlapse) wlapse = _convn(np.diff(xlapse), .5 * np.array([1, 1])) clapse = np.cumsum(ylapse * wlapse) plt.subplot(2, 3, 3) plt.plot(xlapse, ylapse, lw=lineWidth, c=lineColor) plt.hold(True) plt.xlim([0, .5]) plt.title('\lambda', fontsize=18) plt.subplot(2, 3, 6) plt.plot(data[:, 0], np.zeros(data[:, 0].size), 'k.', ms=markerSize * .75) plt.hold(True) plt.xlim(xLimit) x = np.linspace(xLimit[0], xLimit[1], steps) for idot in range(0, 5): if idot == 0: xcurrent = theta[2] color = 'k' elif idot == 1: xcurrent = 0 color = [1, 200 / 255, 0] elif idot == 2: lix = clapse[clapse >= .25].size xcurrent = xlapse[-lix] color = 'r' elif idot == 3: lix = clapse[clapse >= .75].size xcurrent = xlapse[-lix] color = 'b' elif idot == 4: xcurrent = .5 color = 'g' y = 100 * (theta[3] + (1 - xcurrent - theta[3]) * result['options']['sigmoidHandle'](x, theta[0], theta[1])) plt.subplot(2, 3, 6) plt.plot(x, y, '-', lw=lineWidth, c=color) plt.subplot(2, 3, 3) plt.plot(np.array(xcurrent), result['options']['priors'][2](np.array(xcurrent)), '.', c=color, ms=markerSize) if (showImediate): plt.show()