def psyCurve(fname, choice): ''' Generates psychometric curve with preset parameters for each .csv file using psignifit package for duration data ''' data = [] with open(fname, 'r+', newline='') as csvfile: filereader = csv.reader(csvfile, delimiter=',') next(filereader) for row in filereader: if choice == 'yep': if row[2] == 'match': data.append([ float(row[1]), int(row[3]), int(row[3]) + int(row[4]) ]) if choice == 'nope': if row[2] == 'mismatch': data.append([ float(row[1]), int(row[3]), int(row[3]) + int(row[4]) ]) newData = np.array(data) options = dict() options['sigmoidName'] = 'norm' result = ps.psignifit(newData, options) print(result['conf_Intervals']) if choice == 'yep': ps.psigniplot.plotPsych(result, dataColor=[0, 0, 0], lineColor=[0, 0, 0], xLabel='NUMEROSITY RATIO', yLabel='PROPORTION CHOSE 1 MORE', fontName='Consolas', dataSize=0.5) elif choice == 'nope': ps.psigniplot.plotPsych(result, dataColor=[227 / 255, 66 / 255, 52 / 255], lineColor=[227 / 255, 66 / 255, 52 / 255], xLabel='NUMEROSITY RATIO', yLabel='PROPORTION CHOSE 1 MORE', fontName='Consolas', dataSize=0.5)
def fit_curve(df): import psignifit as psf print(df.index) if (df["Hit Rate"] > 0.5).any() and (df["Hit Rate"] < 0.5).any(): df = df.drop(columns="Hit Rate") data = df.to_numpy() options = { "sigmoidName": "norm", "expType": "YesNo", "confP": [0.95], "nblocks": 1000, } # # def priorGamma(x): # # return norm.pdf(x, FArate, 0.1) # # options["priors"] = [None, None, None, priorGamma, None] result = psf.psignifit(data, options) results_df = pd.DataFrame( [{ "Threshold": result["Fit"][0], "width": result["Fit"][1], "lambda": result["Fit"][2], "gamma": result["Fit"][3], "beta": result["Fit"][4], "location_CI_95": result["conf_Intervals"][0][0][0], "width_CI_95": result["conf_Intervals"][1][0][0], "lambda_CI_95": result["conf_Intervals"][2][0][0], "gamma_CI_95": result["conf_Intervals"][3][0][0], "beta_CI_95": result["conf_Intervals"][4][0][0], "location_CI_5": result["conf_Intervals"][0][1][0], "width_CI_5": result["conf_Intervals"][1][1][0], "lambda_CI_5": result["conf_Intervals"][2][1][0], "gamma_CI_5": result["conf_Intervals"][3][1][0], "beta_CI_5": result["conf_Intervals"][4][1][0], }], index=pd.MultiIndex.from_tuples([df.index.tolist()[0]], names=df.index.names), ) return results_df else: return pd.DataFrame()
[0.0025, 44.0000, 90.0000], [0.0030, 52.0000, 90.0000], [0.0035, 53.0000, 90.0000], [0.0040, 62.0000, 90.0000], [0.0045, 64.0000, 90.0000], [0.0050, 76.0000, 90.0000], [0.0060, 79.0000, 90.0000], [0.0070, 88.0000, 90.0000], [0.0080, 90.0000, 90.0000], [0.0100, 90.0000, 90.0000]]) options = dict() options['expType'] = '2AFC' options['sigmoidName'] = 'norm' res = ps.psignifit(data, options) ps.psigniplot.plotPrior(res) ''' You should check that the assumptions we make for the heuristic to work are actually true in the case of your data. e.g. check, whether one of the following statements holds: (1) You understand what our priors mean exactly and judge them to be appropriate. (2) You are sure you recorded a trial well above and a trial well below threshold. (3) Your posterior concentrates on an area for which the prior was constant. '''
We will need some fitted function for illustration. Thus we first fit our standard data from DEMO_001 again: ''' data = np.array([[0.0010, 45.0000, 90.0000], [0.0015, 50.0000, 90.0000], [0.0020, 44.0000, 90.0000], [0.0025, 44.0000, 90.0000], [0.0030, 52.0000, 90.0000], [0.0035, 53.0000, 90.0000], [0.0040, 62.0000, 90.0000], [0.0045, 64.0000, 90.0000], [0.0050, 76.0000, 90.0000], [0.0060, 79.0000, 90.0000], [0.0070, 88.0000, 90.0000], [0.0080, 90.0000, 90.0000], [0.0100, 90.0000, 90.0000]]) options = dict() options['sigmoidName'] = 'norm' options['expType'] = '2AFC' res = ps.psignifit(data, options) """ obtaining threshold values """ ''' For comparison to other estimation techniques we provide functions to calculate thresholds at any given percent correct. The first function is getThreshold(result, pCorrect, unscaled). It calculates the threshold of the function fit in result with pCorrect proportion correct. Unscaled toggles, whether you refer to the pCorrect obtained in the experiment (default), or to the percent correct on the original function unscaled by guessing and lapse rate. For example: This call will find the value at which our function reaches 90% correct: ''' ps.getThreshold(res, 0.9)
x_1 = np.arange(SNRs_1[-1], SNRs_1[0], .1) psy_curve_1 = GaussCDF(x_1, param_1[0], param_1[1], param_1[2]) plt.figure() plt.plot(SNRs_0, acc_0) plt.plot(SNRs_1, acc_1) plt.plot(x_0, psy_curve_0, '--') plt.plot(x_1, psy_curve_1, '--') #%% Do fit with psignifit data_0ps = np.concatenate( (SNRs_0[:, np.newaxis], acc_0[:, np.newaxis] * ntrials, 20 * np.ones([7, 1])), axis=1) data_1ps = np.concatenate( (SNRs_1[:, np.newaxis], acc_1[:, np.newaxis] * ntrials, 20 * np.ones([acc_1.size, 1])), axis=1) options = dict({'sigmoidName': 'norm', 'expType': '3AFC'}) result_0ps = ps.psignifit(data_0ps, options) result_1ps = ps.psignifit(data_1ps, options) plt.figure() ps.psigniplot.plotPsych(result_0ps) ps.psigniplot.plotPsych(result_1ps, dataColor='tab:orange', lineColor='tab:orange')
'logn' a cumulative lognormal distribution 'Weibull' a Weibull function There are many other options you can set in the options-file. You find them in demo_002 --- NOW RUN PSIGNIFIT --- Now we are ready to run the main function, which fits the function to the data. You obtain a struct, which contains all the information about the fitted function and can be passed to the many other functions in this toolbox, to further process the results. """ res = ps.psignifit(data, options) """ --- VISUALIZE THE RESULTS --- For example you can use the result dict res to plot your psychometric function with the data: """ ps.psigniplot.plotPsych(res) plt.show() """ --- REMARK FOR INSUFFICIENT MEMORY ISSUES ---
# %% plt.show() # %% fdsf YesNo = np.array(total.loc[::-1]) YesNo = YesNo.T[0] Stimulus = np.array(axisx[0][0])+0.65 Target = np.ones(7) Datas = np.array([Stimulus, YesNo*100, Target*100]).T YesNo = np.array(totalc3.loc[::-1]) YesNo = YesNo.T[0] Datas2 = np.array([Stimulus, YesNo*100, Target*100]).T options = dict() options['sigmoidName'] = 'norm' options['expType'] = 'YesNo' result = ps.psignifit(Datas,options); result2 = ps.psignifit(Datas2,options); result['Fit'] result['conf_Intervals'] ps.psigniplot.plotPsych(result) ps.psigniplot.plotPsych(result2) if __name__ == "__main__": pass
subData2IFC = big_df.loc[big_df['expName'] == "2IFC"] #print (big_df) ##big_df.to_csv('BigData.csv', index=False) ###subData.to_csv('DataYesNo.csv', index=False) #creating a subdata set with only "yes-No Task ## 2IFC + Suggestion start dataOne = evaluationAndPlot(create_subdataset_for_participant(nameVpn)) dataTwo = calc2AFCSuggestion(create_subdataset_for_participant(nameVpn)) dataThree = evaluationAndPlot2IFC( create_subdataset_for_participant2IFC(nameVpn)) options = dict() options['expType'] = 'nAFC' # choose 2-AFC as the experiment type options['expN'] = 2 resultOne = ps.psignifit(dataOne, options) result = dict() resultTwo = ps.psignifit(dataTwo, options) ps.psigniplot.plotPsych(resultOne, dataColor=[1, 0, 0.5], lineColor=[1, 0, 0.5]) ps.psigniplot.plotPsych(resultTwo, dataColor=[0.5, 1, 0.5], lineColor=[0.5, 1, 0.5]) resultThree = ps.psignifit(dataThree, options) ps.psigniplot.plotPsych(resultThree, dataColor=[0.5, 0, 1], lineColor=[0.5, 0, 1]) # 2IFC + Suggestion end #RelativeProbabilityYesNo(create_subdataset_for_participant (nameVpn))
'''to illustrate this we plot the priors from our original example from demo_001: ''' data = np.array([[0.0010, 45.0000, 90.0000], [0.0015, 50.0000, 90.0000], [0.0020, 44.0000, 90.0000], [0.0025, 44.0000, 90.0000], [0.0030, 52.0000, 90.0000], [0.0035, 53.0000, 90.0000], [0.0040, 62.0000, 90.0000], [0.0045, 64.0000, 90.0000], [0.0050, 76.0000, 90.0000], [0.0060, 79.0000, 90.0000], [0.0070, 88.0000, 90.0000], [0.0080, 90.0000, 90.0000], [0.0100, 90.0000, 90.0000]]) options = dict() options['expType'] = '2AFC' options['sigmoidName'] = 'norm' res = ps.psignifit(data, options) ps.psigniplot.plotPrior(res) ''' You should check that the assumptions we make for the heuristic to work are actually true in the case of your data. e.g. check, whether one of the following statements holds: (1) You understand what our priors mean exactly and judge them to be appropriate. (2) You are sure you recorded a trial well above and a trial well below threshold. (3) Your posterior concentrates on an area for which the prior was constant. ''' """ adjusting the realistic range
def __init__(self, data, options): self.res = ps.psignifit(data, options)
keys = ['sigmoidName', 'expType','expN','estimateType','stepN','mbStepN','confP', 'CImethod', 'betaPrior', 'useGPU','nblocks','poolMaxGap','poolMaxLength', 'poolxTol', 'instantPlot', 'borders', 'setBordersType', 'maxBorderValue', 'moveBorders', 'dynamicGrid', 'GridSetEval', 'UniformWeight', 'widthalpha', 'logspace'] for i in range(n): data = testsMat['data'][i][0] # parse options struct to proper dict tmpOptions = testsMat['options'][i][0][0,0] for key in keys: try: if 'str' in tmpOptions[key].dtype.name: options[key] = tmpOptions[key][0] else: options[key] = tmpOptions[key] except: print(key + ' does not exist') # run fitting results = psignifit(data,options) # calculate differences to matlab results (max difference for the latter ones) for param in ['logPmax','integral']: differences[param][i] = testsMat[param][i][0][0][0][0] - results[param] for param in ['X1D','marginals','marginalsX','marginalsW','Fit']: tmp = testsMat[param][i][0][0] for j in range(5): differences[param][i,j] = max(tmp[j] - results[param])
def psyCurve(fname): ''' Generates psychometric curve with preset parameters for each .csv file using psignifit package for duration data ''' allData = {} with open(fname, 'r+', newline='') as csvfile: filereader = csv.reader(csvfile, delimiter=',') next(filereader) for row in filereader: dur = float(row[1]) press = int(row[5]) if dur not in allData: allData[dur] = [dur, 0, 0] allData[dur][2] += 1 if press == 76: allData[dur][1] += 1 data = np.array([values for values in allData.values()]) options = dict() options['sigmoidName'] = 'norm' result = ps.psignifit(data, options) print(result['conf_Intervals']) if fname == 'Exp1Oddball/oddData.csv' or fname == 'Exp21Oddball/oddData2.csv' or fname == 'Exp3Oddball/oddData4.csv': ps.psigniplot.plotPsych(result, dataColor=[0, 0, 0], lineColor=[0, 0, 0], xLabel='STIMULUS DURATION (msec)', yLabel='PROPORTION CORRECT', fontName='Consolas') elif fname == 'Exp1Oddball/redData.csv' or fname == 'Exp21Oddball/redData2.csv' or fname == 'Exp3Oddball/redData4.csv': ps.psigniplot.plotPsych(result, lineColor=[227 / 255, 66 / 255, 52 / 255], dataColor=[227 / 255, 66 / 255, 52 / 255], xLabel='STIMULUS DURATION (msec)', yLabel='PROPORTION CORRECT', fontName='Consolas') elif fname == 'Exp1Oddball/loomingData.csv': ps.psigniplot.plotPsych(result, lineColor=[135 / 255, 200 / 255, 48 / 255], dataColor=[135 / 255, 200 / 255, 48 / 255], xLabel='STIMULUS DURATION (msec)', yLabel='PROPORTION CORRECT', fontName='Consolas') elif fname == 'Exp21Oddball/polychromaticData.csv' or fname == 'Exp22Oddball/polychromaticData2.csv' or fname == 'Exp3Oddball/polychromaticData3.csv': ps.psigniplot.plotPsych(result, lineColor=[252 / 255, 89 / 255, 163 / 255], dataColor=[252 / 255, 89 / 255, 163 / 255], xLabel='STIMULUS DURATION (msec)', yLabel='PROPORTION CORRECT', fontName='Consolas') elif fname == 'Exp1Oddball/spikeyData.csv': ps.psigniplot.plotPsych(result, lineColor=[27 / 255, 161 / 255, 226 / 255], dataColor=[27 / 255, 161 / 255, 226 / 255], xLabel='STIMULUS DURATION (msec)', yLabel='PROPORTION CORRECT', fontName='Consolas') elif fname == 'Exp21Oddball/spikeyData2.csv' or fname == 'Exp3Oddball/spikeyData4.csv': ps.psigniplot.plotPsych(result, lineColor=[48 / 255, 84 / 255, 138 / 255], dataColor=[48 / 255, 84 / 255, 138 / 255], xLabel='STIMULUS DURATION (msec)', yLabel='PROPORTION CORRECT', fontName='Consolas')
def vPsyCurve(fname): ''' Generates psychometric curve with preset parameters for each .csv file using psignifit package for velocity data ''' allData = {} with open(fname, 'r+', newline='') as csvfile: filereader = csv.reader(csvfile, delimiter=',') next(filereader) for row in filereader: press = int(row[5]) velo = float(row[9]) if velo not in allData: allData[velo] = [velo, 0, 0] allData[velo][2] += 1 if press == 76 and velo > 1: allData[velo][1] += 0 elif press == 83 and velo <= 1: allData[velo][1] += 0 else: allData[velo][1] += 1 data = np.array([values for values in allData.values()]) print(data) options = dict() options['sigmoidName'] = 'norm' result = ps.psignifit(data, options) if fname == 'Exp3Oddball/oddData4.csv': ps.psigniplot.plotPsych( result, dataColor=[0, 0, 0], lineColor=[0, 0, 0], xLabel='ODDBALL : STD SPEED RATIO', yLabel='ODDBALL DURATION > STD DURATION \n PROBABILITY', fontName='Consolas', ) elif fname == 'Exp3Oddball/redData4.csv': ps.psigniplot.plotPsych( result, lineColor=[227 / 255, 66 / 255, 52 / 255], dataColor=[227 / 255, 66 / 255, 52 / 255], xLabel='ODDBALL : STD SPEED RATIO', yLabel='ODDBALL DURATION > STD DURATION \n PROBABILITY', fontName='Consolas') elif fname == 'Exp3Oddball/polychromaticData3.csv': ps.psigniplot.plotPsych( result, lineColor=[252 / 255, 89 / 255, 163 / 255], dataColor=[252 / 255, 89 / 255, 163 / 255], xLabel='ODDBALL : STD SPEED RATIO', yLabel='ODDBALL DURATION > STD DURATION \n PROBABILITY', fontName='Consolas') elif fname == 'Exp3Oddball/spikeyData4.csv': ps.psigniplot.plotPsych( result, lineColor=[27 / 255, 161 / 255, 226 / 255], dataColor=[27 / 255, 161 / 255, 226 / 255], xLabel='ODDBALL : STD SPEED RATIO', yLabel='ODDBALL DURATION > STD DURATION \n PROBABILITY', fontName='Consolas')
options = dict({'sigmoidName': 'norm', 'expType': 'nAFC', 'expN': 6}) result_ps = [] thresh_70 = np.zeros(len(subjects)) lapse = np.zeros(len(subjects)) psCurves = [] plt.figure() for sub in range(len(subjects)): data_sub = np.concatenate( (SNRs[:, np.newaxis], accuracy[:, sub][:, np.newaxis] * cond_trials[:, np.newaxis], cond_trials[:, np.newaxis]), axis=1) result_sub = ps.psignifit(data_sub, options) thresh_70[sub] = ps.getThreshold(result_sub, 0.70)[0] lapse[sub] = result_sub['Fit'][2] result_ps.append(result_sub) ps.psigniplot.plotPsych(result_sub) #%% Store curves to look at a verage x_vals = np.linspace(-13, 13, num=1000) fit = result_sub['Fit'] data = result_sub['data'] options = result_sub['options'] fitValues = (1 - fit[2] - fit[3]) * options['sigmoidHandle']( x_vals, fit[0], fit[1]) + fit[3]