def enterSubjInfo(expName,optionList): """ Brings up a GUI in which to enter all the subject info.""" def inputsOK(optionList,expInfo): for curOption in sorted(optionList.items()): if curOption[1]['options'] != 'any' and expInfo[curOption[1]['name']] not in curOption[1]['options']: return [False,"The option you entered for " + curOption[1]['name'] + " is not in the allowable list of options: " + str(curOption[1]['options'])] print "inputsOK passed" return [True,''] try: expInfo = misc.fromFile(expName+'_lastParams.pickle') except: expInfo={} #make the kind of dictionary that this gui can understand for curOption in sorted(optionList.items()): expInfo[curOption[1]['name']]=curOption[1]['default'] #load the tips tips={} for curOption in sorted(optionList.items()): tips[curOption[1]['name']]=curOption[1]['prompt'] expInfo['dateStr']= data.getDateStr() expInfo['expName']= expName dlg = gui.DlgFromDict(expInfo, title=expName, fixed=['dateStr','expName'],order=[optionName[1]['name'] for optionName in sorted(optionList.items())],tip=tips) if dlg.OK: misc.toFile(expName+'_lastParams.pickle', expInfo) [success,error] = inputsOK(optionList,expInfo) if success: return [True,expInfo] else: return [False,error] else: core.quit()
def getRunTimeVars(varsToGet, order, expName): """Get run time variables, see http://www.psychopy.org/api/gui.html for explanation""" order.append('expName') varsToGet['expName'] = expName try: previousRunTime = misc.fromFile(expName + '_lastParams.pickle') for curVar in previousRunTime.keys(): if isinstance(varsToGet[curVar], list) or curVar == "room" or curVar == "date_time": pass #don't load it in else: varsToGet[curVar] = previousRunTime[curVar] except: pass if varsToGet.has_key('room') and varsToGet.has_key('date_time'): infoDlg = gui.DlgFromDict(dictionary=varsToGet, title=expName, fixed=['room', 'date_time'], order=order) else: infoDlg = gui.DlgFromDict(dictionary=varsToGet, title=expName, fixed=[expName], order=order) misc.toFile(expName + '_lastParams.pickle', varsToGet) if infoDlg.OK: return varsToGet else: print 'User Cancelled'
def testReadWriteData(self): dat = misc.fromFile(os.path.join(thisDir, 'data.psydat')) dat.saveAsExcel(name, stimOut=[ 'text', 'congruent', 'corrAns', 'letterColor', ], dataOut=['n', 'all_mean', 'all_std', 'all_raw']) # Make sure the file is there assert os.path.isfile(fullName) expBook = load_workbook(os.path.join(thisDir, 'data.xlsx')) actBook = load_workbook(fullName) for wsN, expWS in enumerate(expBook.worksheets): actWS = actBook.worksheets[wsN] for key, expVal in expWS._cells.items(): actVal = actWS._cells[key] try: # convert to float if possible and compare with a reasonable # (default) precision expVal.value = float(expVal.value) nose.tools.assert_almost_equals(expVal.value, float(actVal.value)) except: # otherwise do precise comparison nose.tools.assert_equal(expVal.value, actVal.value)
def testReadWriteData(self): dat = misc.fromFile(os.path.join(thisDir, 'data.psydat')) dat.saveAsExcel(name, stimOut=[ 'text', 'congruent', 'corrAns', 'letterColor', ], dataOut=['n', 'all_mean', 'all_std', 'all_raw']) # Make sure the file is there assert os.path.isfile(fullName) expBook = load_workbook(os.path.join(thisDir, 'data.xlsx')) actBook = load_workbook(fullName) for wsN, expWS in enumerate(expBook.worksheets): actWS = actBook.worksheets[wsN] for key, expVal in expWS._cells.items(): actVal = actWS._cells[key] try: #convert to float if possible (to get around 2.15E-2 probs) expVal.value = float(expVal.value) except: pass nose.tools.eq_(expVal.value, actVal.value, msg="expected %s but got %s" % (expVal.value, actVal.value))
def get_subj_info(gui_yaml, data_file_fmt): """Create a psychopy.gui from a yaml config file. The first time the experiment is run, a pickle of that subject's settings is saved. On subsequent runs, the experiment tries to prepopulate the settings with those of the previous subject. Args: gui_yaml (str): Path to config file in yaml format. data_file_fmt (str): Formatted string to determine location of data file. e.g., 'data/{subj_id}.csv'. If a file exists at that location, a popup error is raised. Returns: dict of subject info An example yaml config file looks like this: --- # subj_info.yaml 1: name: subj_id prompt: Subject identifier. default: SUBJ1 2: name: condition prompt: Between subjects condition. options: [a, b, c] 3: name: order prompt: Between subjects order. type: int options: [1, 2, 3] """ with open(gui_yaml, 'r') as f: gui_info = yaml.load(f) ordered_fields = [field for _, field in sorted(gui_info.items())] # Determine order, tips, and validation ordered_names = [field['name'] for field in ordered_fields] field_tips = {field['name']: field['prompt'] for field in ordered_fields} # Load the last participant's options or use the defaults last_subj_info = gui_yaml + '.pickle' try: gui_data = misc.fromFile(last_subj_info) for yaml_name in ordered_names: if yaml_name not in gui_data: # Invalid pickle raise AssertionError except IOError, AssertionError: gui_data = { field['name']: field['default'] for field in ordered_fields }
def test_multiKeyResponses(self): dat = misc.fromFile(os.path.join(fixturesPath,'multiKeypressTrialhandler.psydat')) #test csv output dat.saveAsText(pjoin(self.temp_dir, 'testMultiKeyTrials.csv'), appendFile=False) utils.compareTextFiles(pjoin(self.temp_dir, 'testMultiKeyTrials.csv'), pjoin(fixturesPath,'corrMultiKeyTrials.csv')) #test xlsx output dat.saveAsExcel(pjoin(self.temp_dir, 'testMultiKeyTrials.xlsx'), appendFile=False) utils.compareXlsxFiles(pjoin(self.temp_dir, 'testMultiKeyTrials.xlsx'), pjoin(fixturesPath,'corrMultiKeyTrials.xlsx'))
def checkPsychoDone(subject, node): tab = int(lib.get_node(node,'id')[0]) expName = os.path.splitext(os.path.basename(node['file']))[0] filename = expName + getTimestamp(node, -2) + 'trials.psydat' doneFile = os.path.abspath(os.path.join(lib.SUBJS, subject, "session%d"%tab, 'ltTaskData', expName, filename)) print "Psychopy complete? Checking", doneFile if os.path.exists(doneFile): datFile = fromFile(doneFile) print "Found .psydat file. Collected",datFile.thisN, "trials, so finished is",datFile.finished return datFile.finished else: return False
def get_subject_info(): try: expInfo = fromFile('../data/lastParams.pickle') # check existence of previous parameter file except: expInfo = {'pseudo':'pseudo'} expInfo['date']= data.getDateStr() #add current time #present a dialog box to get user info dlg = gui.DlgFromDict(expInfo, title='Experiment', fixed=['date']) if dlg.OK: toFile('../data/lastParams.pickle', expInfo)#save params to file for next time else: core.quit()#cancel -> exit return expInfo
def test_multiKeyResponses(self): dat = misc.fromFile( os.path.join(fixturesPath, 'multiKeypressTrialhandler.psydat')) #test csv output dat.saveAsText(pjoin(self.temp_dir, 'testMultiKeyTrials.csv'), appendFile=False) utils.compareTextFiles(pjoin(self.temp_dir, 'testMultiKeyTrials.csv'), pjoin(fixturesPath, 'corrMultiKeyTrials.csv')) #test xlsx output dat.saveAsExcel(pjoin(self.temp_dir, 'testMultiKeyTrials.xlsx'), appendFile=False) utils.compareXlsxFiles(pjoin(self.temp_dir, 'testMultiKeyTrials.xlsx'), pjoin(fixturesPath, 'corrMultiKeyTrials.xlsx'))
def enterSubInfo(expName): """Brings up a GUI in which to enter all the subject info.""" try: expInfo = misc.fromFile(expName+'_lastParams.pickle') except: expInfo = {'ExpTitle':expName,'Subject':'s01', 'Subject Initials':'abc','Start at trial':0,'Experimenter Initials':'KV'} expInfo['dateStr']= data.getDateStr() dlg = gui.DlgFromDict(expInfo, title=expName+' Exp', fixed=['dateStr']) if dlg.OK: misc.toFile(expName+'_lastParams.pickle', expInfo) else: core.quit() return expInfo
def get_subj_info(self): requirements = [ 'subj_info_options', 'participant_yaml', 'sona_experiment_code', 'data_dir' ] assert all([req in self for req in requirements]) subj_info = self['subj_info_options'] fields = [info for _, info in sorted(subj_info.items())] # Determine order and tips ordered_names = [info['name'] for info in fields] dlg_tips = {info['name']: info['prompt'] for info in fields} # Load the last participant's options or use the defaults last_dlg_data = self['participant_yaml'] + '.pickle' try: dlg_data = misc.fromFile(last_dlg_data) except IOError: dlg_data = {info['name']: info['default'] for info in fields} # Set fixed fields dlg_data['date'] = data.getDateStr() dlg_data['sona_experiment_code'] = self['sona_experiment_code'] fixed_fields = ['date', 'sona_experiment_code'] while True: # Bring up the dialogue dlg = gui.DlgFromDict(dlg_data, order=ordered_names, fixed=fixed_fields, tip=dlg_tips) if not dlg.OK: core.quit() subj_info = dict(dlg_data) data_filename = unipath.Path(self['data_dir'], subj_info['subj_id'] + '.csv') if data_filename.exists(): print 'that data file already exists' else: misc.toFile(last_dlg_data, dlg_data) break open(data_filename, 'w') subj_info['data_filename'] = data_filename self.update(subj_info)
def get_subj_info(gui_yaml, check_exists, save_order=True): """ Create a psychopy.gui from a yaml config file. The first time the experiment is run, a pickle of that subject's settings is saved. On subsequent runs, the experiment tries to prepopulate the settings with those of the previous subject. Parameters ---------- gui_yaml: str, Path to config file in yaml format. check_exists: function, Computes a data file path from the gui data, and checks for its existence. If the file exists, an error is displayed. save_order: bool, Should the key order be saved in "_order"? Defaults to True. Returns ------- dict, with key order saved in "_order", if specified. """ with open(gui_yaml, 'r') as f: gui_info = yaml.load(f) ordered_fields = [field for _, field in sorted(gui_info.items())] # Determine order and tips ordered_names = [field['name'] for field in ordered_fields] field_tips = {field['name']: field['prompt'] for field in ordered_fields} # Load the last participant's options or use the defaults last_subj_info = gui_yaml + '.pickle' try: gui_data = misc.fromFile(last_subj_info) for yaml_name in ordered_names: if yaml_name not in gui_data: # Invalid pickle raise AssertionError except IOError, AssertionError: gui_data = { field['name']: field['default'] for field in ordered_fields }
def testReadWriteData(self): dat = misc.fromFile(os.path.join(thisDir, 'data.psydat')) dat.saveAsExcel(name, stimOut=['text', 'congruent', 'corrAns', 'letterColor', ], dataOut=['n','all_mean','all_std', 'all_raw']) # Make sure the file is there assert os.path.isfile(fullName) expBook = load_workbook(os.path.join(thisDir,'data.xlsx')) actBook = load_workbook(fullName) for wsN, expWS in enumerate(expBook.worksheets): actWS = actBook.worksheets[wsN] for key, expVal in expWS._cells.items(): actVal = actWS._cells[key] try:#convert to float if possible (to get around 2.15E-2 probs) expVal.value = float(expVal.value) except: pass nose.tools.eq_(expVal.value, actVal.value, msg="expected %s but got %s" %(expVal.value, actVal.value))
def get_subj_info(gui_yaml, check_exists, save_order=True): """ Create a psychopy.gui from a yaml config file. The first time the experiment is run, a pickle of that subject's settings is saved. On subsequent runs, the experiment tries to prepopulate the settings with those of the previous subject. Parameters ---------- gui_yaml: str, Path to config file in yaml format. check_exists: function, Computes a data file path from the gui data, and checks for its existence. If the file exists, an error is displayed. save_order: bool, Should the key order be saved in "_order"? Defaults to True. Returns ------- dict, with key order saved in "_order", if specified. """ with open(gui_yaml, 'r') as f: gui_info = yaml.load(f) ordered_fields = [field for _, field in sorted(gui_info.items())] # Determine order and tips ordered_names = [field['name'] for field in ordered_fields] field_tips = {field['name']: field['prompt'] for field in ordered_fields} # Load the last participant's options or use the defaults last_subj_info = gui_yaml + '.pickle' try: gui_data = misc.fromFile(last_subj_info) for yaml_name in ordered_names: if yaml_name not in gui_data: # Invalid pickle raise AssertionError except IOError, AssertionError: gui_data = {field['name']: field['default'] for field in ordered_fields}
def testReadWriteData(self): dat = misc.fromFile(os.path.join(thisDir, 'data.psydat')) dat.saveAsExcel(name, stimOut=['text', 'congruent', 'corrAns', 'letterColor', ], dataOut=['n','all_mean','all_std', 'all_raw']) # Make sure the file is there assert os.path.isfile(fullName) expBook = load_workbook(os.path.join(thisDir,'data.xlsx')) actBook = load_workbook(fullName) for wsN, expWS in enumerate(expBook.worksheets): actWS = actBook.worksheets[wsN] for key, expVal in expWS._cells.items(): actVal = actWS._cells[key] try: # convert to float if possible and compare with a reasonable # (default) precision expVal.value = float(expVal.value) nose.tools.assert_almost_equals(expVal.value, float(actVal.value)) except: # otherwise do precise comparison nose.tools.assert_equal(expVal.value, actVal.value)
@author: orduek Corsi Block Expreiment in Psychopy. This experiment is spatial memory experiment as in the WMS """ from psychopy import core, visual, gui, data, misc, event, sound import time, os # now turn to right folder directory=os.getcwd() # get folder os.chdir(directory) # use it #folder='/home/ord/Experiments_BP_Clinic/PCT/' #specify the folder of result files to be saved in # savine last experiment data try:#try to get a previous parameters file expInfo = misc.fromFile('corsi.pickle') except:#if not there then use a default set expInfo = {'subject no':''} expInfo['dateStr']= data.getDateStr() #add the current time # dialouge box for name of subject and file dlg = gui.DlgFromDict(expInfo, title='Corsi Task', fixed=['dateStr']) if dlg.OK: misc.toFile('corsi.pickle', expInfo)#save params to file for next time else: core.quit()#the user hit cancel so exit # check if folder exist and if not, create it if not os.path.exists('results'): os.makedirs('results') fileName = expInfo['subject no'] + expInfo['dateStr']
def enter_subj_info(exp_name, options, unique=True, exp_dir='./', data_dir='./'): """ Brings up a GUI in which to enter all the subject info. author: Gary Lupyan, Pierce Edmiston Parameters ---------- exp_name: str, Name to appear in psychopy.gui header. options: dict. unique: bool, Defaults to True, which checks for data file uniqueness. exp_dir: relative path, where to store the _last_params.pickle. data_dir: relative path, where to look for the data files. """ info_accepted = False if not Path(exp_dir).exists(): Path(exp_dir).mkdir() if not Path(data_dir).exists(): Path(data_dir).mkdir() def inputsOK(options, expInfo): for curOption in sorted(options.items()): if curOption[1]['options'] != 'any' and expInfo[ curOption[1]['name']] not in curOption[1]['options']: return [ False, "The option you entered for " + curOption[1]['name'] + " is not in the allowable list of options: " + str(curOption[1]['options']) ] return [True, ''] while not info_accepted: version_pth = os.path.join(exp_dir, exp_name + '_last_params.pickle') try: expInfo = misc.fromFile(version_pth) except: expInfo = { } #make the kind of dictionary that this gui can understand for curOption in sorted(options.items()): expInfo[curOption[1]['name']] = curOption[1]['default'] #load the tips tips = {} for curOption in sorted(options.items()): tips[curOption[1]['name']] = curOption[1]['prompt'] expInfo['date'] = data.getDateStr() expInfo['exp_name'] = exp_name dlg = gui.DlgFromDict(expInfo, title=exp_name, fixed=['date', 'exp_name'], order=[ optionName[1]['name'] for optionName in sorted(options.items()) ], tip=tips) if dlg.OK: misc.toFile(version_pth, expInfo) [success, error] = inputsOK(options, expInfo) else: core.quit() data_file = os.path.join( data_dir, '{subj_id}.tsv'.format(subj_id=expInfo['subj_id'])) if not success: popup_error(error) elif os.path.isfile(data_file): popup_error('A data file with that name already exists.') else: info_accepted = True data_handle = open(data_file, 'w') expInfo['computer'] = socket.gethostname() return expInfo, data_handle
"""This is not a particularly useful example of saving out csv files from a set of psydat files """ from os import path from psychopy import misc, gui #select some files to use filenames = gui.fileOpenDlg(allowed="*.psydat") #loop through the files for thisFilename in filenames: #get a new name fileNoExt, fileExt = path.splitext(thisFilename) newName = fileNoExt+"NEW.csv" #load and save dat = misc.fromFile(thisFilename) dat.saveAsWideText(newName) print 'saved', newName
def plotDataAndPsychometricCurve(df, dataFileName): """ Plot data, and fit and plot psychometric curve If df is not None then get data from dataFileName """ if df is None: if type(dataFileName) is not str: print 'dataFileName = ', dataFileName raise Exception("No df supplied and no string dataFileName supplied") if dataFileName.endswith('.pickle'): df = fromFile(dataFileName) elif dataFileName.endswith('.txt'): df = pd.read_csv(dataFileName, delimiter='\t') elif dataFileName.endswith('.psydat'): trialHandler = fromFile(dataFileName) raise Exception('Cant handle .psydat file, because first Alex has to write a toDataFrame function for experimentHandler, so that its data can be analyzed.') #or would have to save to save trialHandler saveAsWideText to dummy file, and use returned dataframe #dat = tools.filetools.fromFile(dataFileName) #<class 'psychopy.data.DataHandler'> if not isinstance(df, pd.core.frame.DataFrame): raise Exception("Don't have viable DataFrame still") if np.all(df.dtypes==object): raise Exception("I thought you'd give me some numbers to work with, but everything in this dataframe is an object") #Need to convert_ #add overcorrect to cases where tilt==0 tilt = df.loc[:,'tilt'] neutralStimIdxs = (tilt==0) #print('neutralStimIdxs=\n',neutralStimIdxs) if len(neutralStimIdxs)>1: if neutralStimIdxs.any(): #Calculate over/under-correction, which is only interpretable when tilt=0 forCalculatn = df.loc[neutralStimIdxs, ['tilt','startLeft','upDown','respLeftRight']] overCorrected = calcOverCorrected( forCalculatn ) df['overCorrected']= np.nan df.loc[neutralStimIdxs, 'overCorrected'] = overCorrected #test plotting of data usePsychopy_ext = False if usePsychopy_ext: #have to use psychopy_ext to aggregate ag = psychopy_ext.stats.aggregate(df, values="respLeftRight", cols="tilt") #, values=None, subplots=None, yerr=None, aggfunc='mean', order='natural') print "ag = \n", ag plt = psychopy_ext.plot.Plot() plt.plot(ag, kind='line') print "Showing plot with psychopy_ext.stats.aggregate" plt.show() #dataframe aggregate grouped = df.groupby(['startLeft','tilt']) dirTilt = grouped.mean() #this is a dataframe, not a DataFrameGroupBy print "mean at each dir, tilt =\n", dirTilt #print "dirTilt.index = ", dirTilt.index #there is no column called 'tilt', instead it's the actual index, kinda like row names # MultiIndex [(False, -0.4), (False, 0.0), (False, 0.4), (True, -0.4), (True, 0.0), (True, 0.4)] #dirTilt.groups no groups, maybe because dataframe? dirTilt = dirTilt.reset_index() #flatten MultiIndex back into columns with rows (simple dataframe) leftwardM = dirTilt[ dirTilt['startLeft']==False ] rightwardM = dirTilt[ dirTilt['startLeft']==True ] ax1 = pylab.subplot(121) pylab.scatter(leftwardM['tilt'], leftwardM['respLeftRight'], edgecolors=(1,0,0), facecolor=(1,0,0), label='leftward saccade') pylab.scatter(rightwardM['tilt'], rightwardM['respLeftRight'], edgecolors=(0,1,0), facecolor=(0,1,0), label='rightward saccade') pylab.legend() print str( round( 100*df['overCorrected'].mean(), 2) ) msg = 'proportn overCorrected at 0 tilt = ' + str( round( 100*df['overCorrected'].mean(), 2) ) + \ '% of ' + str( df['overCorrected'].count() ) + ' trials' msg2= ' 95% Agresti-Coull CI = ' + \ str( np.round( agrestiCoull95CI(df['overCorrected'].sum(), df['overCorrected'].count()), 2) ) pylab.text(0.52, 0.85, msg, horizontalalignment='left', fontsize=12) pylab.text(0.52,0.75, msg2, horizontalalignment='left', fontsize=12) #pylab.ylim([-0.01,1.01]) pylab.xlabel("tilt") pylab.ylabel("proportion respond 'right'") #psychometric curve basics tiltMin = min( df['tilt'] ) tiltMax = max( df['tilt'] ) x = np.linspace(tiltMin, tiltMax, 50) #test function fitting #fit curve def logistic(x, x0, k): y = 1 / (1 + np.exp(-k*(x-x0))) return y def inverseLogistic(y, x0, k): linear = np.log ( y / (1-y) ) #linear = -k*(x-x0) #x-x0 = linear/-k #x= linear/-k + x0 x = linear/-k + x0 return x #scipy.stats.logistic.fit paramsLeft = None; paramsRight = None try: paramsLeft, pcov = scipy.optimize.curve_fit(logistic, leftwardM['tilt'], leftwardM['respLeftRight'], p0 = [0, 6]) except Exception as e: print 'leftward fit failed ', e try: paramsRight, pcov = scipy.optimize.curve_fit(logistic, rightwardM['tilt'], rightwardM['respLeftRight'], p0 = [0, 6]) except Exception as e: print 'rightward fit failed ', e threshVal = 0.5 pylab.plot([tiltMin, tiltMax],[threshVal,threshVal],'k--') #horizontal dashed line overCorrectAmts = list() if paramsLeft is not None: pylab.plot(x, logistic(x, *paramsLeft) , 'r-') threshL = inverseLogistic(threshVal, paramsLeft[0], paramsLeft[1]) print 'threshL = ', np.round(threshL, 2) overCorrectAmts.append(threshL) pylab.plot([threshL, threshL],[0,threshVal],'g--') #vertical dashed line if paramsRight is not None: pylab.plot(x, logistic(x, *paramsRight) , 'g-') threshR = inverseLogistic(threshVal, paramsRight[0], paramsRight[1]) print 'threshR = ', np.round(threshR, 2) overCorrectAmts.append(-1*threshR) pylab.plot([threshR, threshR],[0,threshVal],'g--') #vertical dashed line pylab.title('threshold (%.2f) = %0.3f' %(threshVal, threshR)) if (paramsLeft is not None) and (paramsRight is not None): pylab.title('PSE (%.2f) = %0.3f & %0.3f' %(threshVal, threshL, threshR)) if len(overCorrectAmts)==0: msg3= 'Failed both fits so cant tell you average over/under correction amount' else: msg3= 'Average tilt needed to compensate overcorrection\n (negative indicates undercorrection)\n = ' + str( np.round( np.mean(overCorrectAmts), 2) ) pylab.text(0.52,0.45, msg3, horizontalalignment='left', fontsize=12, linespacing=2.0) #pylab.savefig('figures/Alex.png') #, bbox_inches='tight') return pylab.gcf() #return current figure
#from a GUI. It then plots the staircases on top of each other on #the left and a combined psychometric function from the same data #on the right from psychopy import data, gui, misc, core import pylab #Open a dialog box to select files from files = gui.fileOpenDlg('.') if not files: core.quit() #get the data from all the files allIntensities, allResponses = [], [] for thisFileName in files: thisDat = misc.fromFile(thisFileName) allIntensities.append(thisDat.intensities) allResponses.append(thisDat.data) #plot each staircase pylab.subplot(121) colors = 'brgkcmbrgkcm' lines, names = [], [] for fileN, thisStair in enumerate(allIntensities): #lines.extend(pylab.plot(thisStair)) #names = files[fileN] pylab.plot(thisStair, label=files[fileN]) #pylab.legend() #get combined data combinedInten, combinedResp, combinedN = \
#Stairs to find the detection threshold of small Lum, LM and S based edges - June 2012 from psychopy import visual, event, misc, core, data, gui, monitors, sound import numpy as np import os, time, copy, random from numpy.random import shuffle import colorFunctions #Create a dialog box for participant information try: info=misc.fromFile('smdetParams.pickle') except: info = {'participant' : 'RJS'} info['dateStr'] = time.strftime("%b%d_%H%M", time.localtime()) dlg = gui.DlgFromDict(info, title='Synth Edge Detection', fixed=['dateStr']) if dlg.OK: misc.toFile('smdetParams.pickle', info) else: core.quit() DEBUG = True #Create the basic parameters info['conditions'] = ['Lum', 'LM', 'S'] info['ISI'] = 0.5 info['displayT'] = 0.3 info['baseContrast'] = 0 info['Blur'] = 0.1 #Change to be equivalent to 0.1deg #Staircase Information info['nTrials'] = 2
keys = event.getKeys() for key in keys: if (key == self.key1 or key == self.key2): response = True elif (key == 'escape'): core.quit() if response: break self.win.flip() core.wait(self.isi) if __name__ == '__main__': # show dialog box for patricipant info try: exp_info = misc.fromFile('last_expinfo.pickle') except: exp_info = {'Nr':'01', 'Age (18-99)':22, 'Sex (m/f)':'m', 'Hand (r/l)':'r'} exp_info_gui = gui.DlgFromDict(exp_info) if exp_info_gui.OK: misc.toFile('last_expinfo.pickle', exp_info) else: core.quit() exp_info['Timestamp'] = time.strftime('%Y-%m-%d-%H%M%S') # create window win = visual.Window(SCREENSIZE, monitor='labscreen', units='cm', color=[-1,-1,-1], allowGUI=False) # create fixation cross fixation = visual.ShapeStim(win=win, pos=[0,0],
import seaborn as sns sns.set_style('whitegrid') sns.set_context('poster') sub_name = 'patxi' working_dir = '../results/' saving_dir = '../result_figures' if not os.path.exists(os.path.join(saving_dir,sub_name)): os.mkdir(os.path.join(saving_dir,sub_name)) psy_data = glob(os.path.join(working_dir,sub_name,'*.psydat')) working_data = glob(os.path.join(working_dir,sub_name,'*.csv')) dfs = {} for f,g in zip(working_data,psy_data): df_temp = pd.read_csv(f) temp = fromFile(g) language = temp.extraInfo['language'] dfs[language] = df_temp fig,axes = plt.subplots(figsize = (8,16), nrows = 3, sharey = True, ) for (language),ax in zip(['spanish','basque','mixed'],axes.flatten()[:2]): df = dfs[language] ax = sns.barplot(x = 'set_size', y = 'just_press.rt', data = df, ax = ax, seed = 12345,
from psychopy import data, gui, misc, core import matplotlib matplotlib.use('WXAgg') import pylab, scipy, numpy files = gui.fileOpenDlg('.') if not files: core.quit() #Get the individual data from the files indIntensities={} indResponses={} for thisFileName in files: thisIndDat = misc.fromFile(thisFileName) for imageName, array in thisIndDat.extraInfo.iteritems(): thisImageName = imageName indIntensities[thisImageName]=[] indResponses[thisImageName]=[] thisIntensity = thisIndDat.reversalIntensities[-10:] thisResponse = thisIndDat.data[-10:] indIntensities[thisImageName].extend(thisIntensity) indResponses[thisImageName].extend(thisResponse) #get individual data thisNewIntensity = indIntensities[thisImageName] thisNewResponse = indResponses[thisImageName]
# Gap is fraction of the overall stimulus i.e. a gap of 0.1 would be 10% of the stimulus or 1 degree # Blur width is also a fraction of the overall stimulus i.e. a blur of 0.1 would be 10% of the stimulus or 1 degree # Marker position - the output from the staircase - is between 0 and 10 and is in degrees # lumEdgePos - is a randomly generated number which positions the luminance edge, this is a fraction of the stim # i.e. lumEdgePos = 0.2 the luminance edge will be 2 degrees from the left # the LM edge is positioned relative to the luminance edge - i.e. lm edge position = lumEdgePos+Gap from psychopy import visual, event, filters, monitors, data, sound, gui, misc, core import numpy as np import random, time, os DEBUG = True # Create a dialog box for settings and participant information try: info = misc.fromFile("edgeParams.pickle") except: info = {"participant": "RJS", "Channel": "LM", "Blur": 0.1, "Gap": 0, "Noise Size": 0.1, "Noise Contrast": 0.2} info["dateStr"] = time.strftime("%b%d_%H%M", time.localtime()) dlg = gui.DlgFromDict(info, title="Synthetic Edge Experiment", fixed=["dateStr"]) if dlg.OK: misc.toFile("lastParams.pickle", info) else: core.quit() # Staircase Information info["nTrials"] = 50 info["nReversals"] = 1 info["stepSizes"] = [ 0.9888, 0.9888,
""" # build basic task (practice, 1-back, 2-back) # Decide to use animals for small children and other for adolecsents. # -*- coding: utf-8 -*- from psychopy import core, visual, gui, data, misc, event, sound import time, os, random # now turn to right folder directory=os.getcwd() # get folder os.chdir(directory) # use it #folder='/home/ord/Experiments_BP_Clinic/PCT/' #specify the folder of result files to be saved in # savine last experiment data try:#try to get a previous parameters file expInfo = misc.fromFile('nBack.pickle') except:#if not there then use a default set expInfo = {'subject no':''} expInfo['dateStr']= data.getDateStr() #add the current time # dialouge box for name of subject and file dlg = gui.DlgFromDict(expInfo, title='nBack Task', fixed=['dateStr']) if dlg.OK: misc.toFile('nBack.pickle', expInfo)#save params to file for next time else: core.quit()#the user hit cancel so exit # check if folder exist and if not, create it if not os.path.exists('results'): os.makedirs('results') fileName = expInfo['subject no'] + expInfo['dateStr']
#!/usr/bin/env python from psychopy import visual, core, event, gui, misc, monitors import random, time import numpy as np #LAST TR=135 #Hit Q to quit during the experiment #load last run of colorflash experiment try: #try to load previous info config = misc.fromFile('config.pickle') print 'config.pickle is picked!' #if loading fails use these values except: #if no file use some defaults config = {'SubjectID':'Empty','SessionNr':'Empty','RunNr':'Empty', 'stimSize':05.00, #degrees of visual angle 'stimPosX':08.50, #degrees of visual angle 'trialDur':12.00, #seconds 'restDur' :12.00, #seconds !!!unused for this experiment 'nrBlocks':2, #number of blocks 'nrBlockCycles':8, #how many times the blocks will repeat 'flickFreq':16.0, #hertz 'letterDur':0.200, #seconds 'letterSize':0.85, #degrees of visual angle 'offsetDur':10} #seconds print 'config.pickle is not picked! Using default configuration values.' #set some configuration parametres that don't change config['Date'] = time.strftime("%b_%d_%Y_%H:%M", time.localtime())
import time, numpy, random #import retinotopyScans #import math from array import * import os #import glob #import imp #from Tkinter import * #from tkFileDialog import askopenfilename #import psychopy.info screenNums = [0, 1] if os.path.isfile('lastrun.pickle') == True: #found a lastrun file--load scanDict from it scanDict = misc.fromFile('lastrun.pickle') #scanDict['animFreq']=2 #scanDict['pairWedge']=1 else: #define defaults scanDict = { #Tr (s) 'Tr': 5, #number of cycles (traveling wave cycle or stim-rest pairs) 'numCycles': 10, #period (s) of each cycle 'period': 24, #pre-scan duration (s) --rest before start OR traveling wave to show during throw-away time 'preScanRest': 12, #contrast for retinotopy, 0 to 1 'contrast': 1.0,
def run_session(self): path = os.path.join(self.res_dir, self.subject) if not os.path.exists(path): os.makedirs(path) # welcome msg = visual.TextStim(self.win, 'Welcome!' + '\n' + ' Press any key to start this session :)', color='black', units='deg', pos=(0, 0), height=0.8) msg.draw() self.win.mouseVisible = False self.win.flip() event.waitKeys() # read staircase parameters conditions = [ dict({'stimulus': key}, **value) for key, value in self.param.items() if key.startswith('stimulus') ] if conditions[0]['stairType'] == 'simple': stairs = data.MultiStairHandler(stairType='simple', conditions=conditions, nTrials=self.trial_nmb, method='sequential') elif conditions[0]['stairType'] == 'quest': stairs = [] for cond in conditions: if self.priors_file_path: prior_file = self.priors_file_path + cond[ 'label'] + '.psydat' print(prior_file) prior_handler = misc.fromFile(prior_file) else: prior_handler = None cur_handler = data.QuestHandler(cond['startVal'], cond['startValSd'], pThreshold=cond['pThreshold'], nTrials=self.trial_nmb, minVal=cond['min_val'], maxVal=cond['max_val'], staircase=prior_handler, extraInfo=cond) stairs.append(cur_handler) elif conditions[0]['stairType'] == 'psi': stairs = [] for cond in conditions: if self.priors_file_path: prior_file = self.priors_file_path + cond['label'] + '.npy' else: prior_file = None print(prior_file) cur_handler = data.PsiHandler(nTrials=self.trial_nmb, intensRange=[1, 10], alphaRange=[1, 10], betaRange=[0.01, 10], intensPrecision=0.1, alphaPrecision=0.1, betaPrecision=0.01, delta=0.01, extraInfo=cond, prior=prior_file, fromFile=(prior_file is not None)) stairs.append(cur_handler) # write configuration files xpp = config_tools.WriteXpp(self.subject, self.idx) xpp_file = xpp.head(self.cfg_file, self.par_file) config_tools.write_xrl(self.subject, cfg_file=self.cfg_file, par_file=self.par_file, xpp_file=xpp_file) xlsname = path + '/' + self.idx + self.param[ 'noise_condition'] + '.xlsx' """ running staircase """ if isinstance(stairs, data.MultiStairHandler): # start running the staircase using the MultiStairHandler for the up-down method count = 0 for rot, cond in stairs: count += 1 judge, thiskey, trial_time = self.run_trial(rot, cond, count) # check whether the theta is valid - if not, the rotation given by staircase should be corrected by # realizable values valid_theta = np.round(np.load(self.hue_list), decimals=1) disp_standard = self.take_closest( valid_theta, cond['standard']) # theta actually displayed stair_test = cond['standard'] + stairs._nextIntensity * (-1)**( cond['label'].endswith('m')) # theta for staircase if stair_test < 0: stair_test += 360 disp_test = self.take_closest(valid_theta, stair_test) disp_intensity = abs(disp_test - disp_standard) if disp_intensity > 300: disp_intensity = 360 - (disp_test + disp_standard) stairs.addResponse(judge, disp_intensity) xpp.task(count, cond, rot, float(disp_intensity), judge, trial_time) event.waitKeys(keyList=[ thiskey ]) # press the response key again to start the next trial config_tools.write_xrl(self.subject, xls_file=xlsname) stairs.saveAsExcel(xlsname) # save results psydat_file_path = os.path.join( path, "psydat", self.idx + self.param['condition'] + '.psydat') # save the handler into a psydat-file misc.toFile(psydat_file_path, stairs) elif isinstance(stairs, list): # start running the staircase using custom interleaving stairs for the quest and psi methods count = 0 rot_all = [] rot_all_disp = [] judge_all = [] estimates = {s.extraInfo['label']: [] for s in stairs} for trial_n in range(self.trial_nmb): for handler_idx, cur_handler in enumerate(stairs): count += 1 rot = next(cur_handler) if len(rot_all) <= handler_idx: rot_all.append([]) rot_all[handler_idx].append(rot) cond = cur_handler.extraInfo judge, thiskey, trial_time = self.run_trial( rot, cond, count) if len(judge_all) <= handler_idx: judge_all.append([]) judge_all[handler_idx].append(judge) # cur_handler.addResponse(judge) # to the next trial valid_theta = np.round(np.load(self.hue_list), decimals=1) disp_standard = self.take_closest( valid_theta, cond['standard']) # theta actually displayed stair_test = cond[ 'standard'] + cur_handler._nextIntensity * (-1)**( cond['label'].endswith('m')) # theta for staircase if stair_test < 0: stair_test += 360 disp_test = self.take_closest(valid_theta, stair_test) disp_intensity = abs(disp_test - disp_standard) if disp_intensity > 300: disp_intensity = 360 - (disp_test + disp_standard) cur_handler.addResponse(judge, disp_intensity) if len(rot_all_disp ) <= handler_idx: # add displayed intensities rot_all_disp.append([]) rot_all_disp[handler_idx].append(disp_intensity) print('stair test: ' + str(stair_test) + ', ' + 'disp_test:' + str(disp_test)) if isinstance(cur_handler, data.PsiHandler): estimates[cur_handler.extraInfo['label']].append([ cur_handler.estimateLambda()[0], # location cur_handler.estimateLambda768()[1], # slope cur_handler.estimateThreshold(0.75) ]) elif isinstance(cur_handler, data.QuestHandler): estimates[cur_handler.extraInfo['label']].append([ cur_handler.mean(), cur_handler.mode(), cur_handler.quantile(0.5) ]) xpp.task(count, cond, rot, disp_intensity, judge, trial_time) event.waitKeys(keyList=[ thiskey ]) # press the response key again to start the next trial config_tools.write_xrl(self.subject, xls_file=xlsname) # save results in xls-file workbook = xlsxwriter.Workbook(xlsname) for handler_idx, cur_handler in enumerate(stairs): worksheet = workbook.add_worksheet( cur_handler.extraInfo['label']) worksheet.write('A1', 'Reversal Intensities') worksheet.write('B1', 'Reversal Indices') worksheet.write('C1', 'All Intensities') worksheet.write('D1', 'All Responses') for i in range(len(rot_all[handler_idx])): # worksheet.write('C' + str(i + 2), rot_all[handler_idx][i]) worksheet.write('C' + str(i + 2), rot_all_disp[handler_idx][i]) worksheet.write('D' + str(i + 2), judge_all[handler_idx][i]) workbook.close() # print resulting parameters and estimates for each step res_file_path = os.path.join(path, self.idx + '_estimates.csv') res_writer = csv.writer(open(res_file_path, 'w')) for res_stim, res_vals in estimates.items(): for res_val_id, res_val in enumerate(res_vals): res_writer.writerow([ res_stim, res_val_id, res_val[0], res_val[1], res_val[2] ]) # save each handler into a psydat-file and save posterior into a numpy-file for cur_handler in stairs: file_name = os.path.join( path, self.idx + self.param['noise_condition'] + cur_handler.extraInfo['label']) misc.toFile(file_name + '.psydat', cur_handler) if isinstance(cur_handler, data.PsiHandler): cur_handler.savePosterior(file_name + '.npy')
import pylab if __name__ == "__main__": cond_colors = {"pre": "g", "stim": "r", "post": "b"} # Open a dialog box to select files from files = gui.fileOpenDlg(".") if not files: core.quit() coherence_resp = {} coherence_rt = {} # get the data from all the files allCoherenceLevels, allResponses, allRTs = {}, {}, {} for thisFileName in files: thisDat = fromFile(thisFileName) condition = thisDat.extraInfo["condition"].lower() if not condition in coherence_resp: coherence_resp[condition] = {} coherence_rt[condition] = {} allCoherenceLevels[condition] = [] allResponses[condition] = [] allRTs[condition] = [] trialList = thisDat.trialList for i in range(thisDat.data["response"].shape[0]): for j in range(thisDat.data["response"].shape[1]): trialIdx = thisDat.sequenceIndices[i, j]
#Blur width is also a fraction of the overall stimulus i.e. a blur of 0.1 would be 10% of the stimulus or 1 degree #Marker position - the output from the staircase - is between 0 and 10 and is in degrees #lumEdgePos - is a randomly generated number which positions the luminance edge, this is a fraction of the stim #i.e. lumEdgePos = 0.2 the luminance edge will be 2 degrees from the left #the LM edge is positioned relative to the luminance edge - i.e. lm edge position = lumEdgePos+Gap from psychopy import visual, event, filters, monitors, data, sound, gui, misc, core import numpy as np import random, time, os, cPickle from numpy.random import shuffle DEBUG=True #Create a dialog box for settings and participant information try: info=misc.fromFile('lastParams.pickle') except: info = {'participant' : 'RJS', 'Gap' : 0, 'Edge Contrast LM' : 0.1, 'Edge Contrast S' : 0.1, 'Edge Contrast Lum' : 0.1} info['dateStr']=time.strftime("%b%d_%H%M", time.localtime()) dlg = gui.DlgFromDict(info, title='Synthetic Edge Experiment', fixed=['dateStr']) if dlg.OK: misc.toFile('lastParams.pickle', info) else: core.quit() #Clocks and Sounds trialClock = core.Clock()
def main(argv): """ should not need to modify this """ try: expInfo = misc.fromFile('lastParams.pickle') except: expInfo = {'participant': '', 'session': ''} expInfo['dateStr'] = datetime.time(datetime.now()) # This function creates the dialog box at the beginning of the script that you # enter the subject's name and has the date automatically entered into it dlg = gui.DlgFromDict(expInfo, title='File Name', fixed=['dateStr']) if dlg.OK: misc.toFile('lastParams.pickle', expInfo) else: core.quit() ### initialize output5 # Stores the information in the dialog box to a variable to be used to create a file dataFile_All, tsvFile = initoutput(expInfo) print dataFile_All TrialTimes, randomizedArray, jitters = getstiminfo( str(os.path.join('stimuli', 'run_' + expInfo['session'] + '.csv'))) ### INITIALIZE DISPLAY ### # keep in mind monitor resolution mywin = visual.Window(RESOLUTION, monitor=MONITOR, units="deg", color=BLACK) mouse = event.Mouse(visible=False, win=mywin) mouse.setVisible(0) # Sets mouse to invisible # Initial instructions before scan starts welcome = visual.TextStim(mywin, pos=[0, 0], text=WELCOMETEXT, wrapWidth=20, alignHoriz='center', alignVert='center', color=WHITE) welcome.draw() # Displays the welcome stimulus mywin.update() # Updates the window to show the stimulus # Waits for the pulse senquence to send a 5. This is before the TRs to be deleted event.waitKeys(keyList=[MR_PULSE]) # Informs participant that the experiment is beginning sessionStart = visual.TextStim(mywin, pos=[0, 0], text=BEGINTEXT, wrapWidth=35, alignHoriz='center', alignVert='center', color=WHITE) #Creates a fixation cross stimulus to be used later fixation = visual.TextStim(mywin, pos=[0, 0], text="+", wrapWidth=25, alignHoriz='center', alignVert='center', color=WHITE) sessionStart.draw() # Displays the welcome stimulus mywin.update() # Updates the window to show the stimulus # Waits N TRs till global clock starts for i in xrange(WAIT_TRs): event.waitKeys(keyList=[MR_PULSE]) globalClock = core.Clock() # Sets the global clock to globalClock variable globalClock.reset() # Resets the global clock trialClock = core.Clock() # sets a trial clock to trialClock variable condClock = core.Clock( ) # initializes condition clock which resets every time try: fixation.draw() mywin.flip() core.wait(PRETRIAL) # just using ITI for now... ### actual experiment loop ### for trialID in randomizedArray: # randTrial = rarr[c] if event.getKeys(keyList=ESCKEY): raise KeyboardInterrupt singletrial(tt=TrialTimes, rt=trialID, dfa=dataFile_All, tsv=tsvFile, gc=globalClock, cc=condClock, j=jitters[trialID], fx=fixation, mw=mywin) core.wait(ITI) ### end of block, draw fixation and quit message ### core.wait(END_DUR) sessionEnd = visual.TextStim(mywin, pos=[0, 0], text="Q", wrapWidth=35, alignHoriz='center', alignVert='center', color=[1, 1, 1]) sessionEnd.draw() mywin.flip() event.waitKeys(keyList=["q"]) except KeyboardInterrupt: print "manually aborted" except: print "error" finally: fixation.draw() mywin.update() dataFile_All.close() tsvFile.close() mywin.close() core.quit()
#!/usr/bin/env python # stimuli for retinotopic mapping # original code by jwp # updated for PsychoPy3 by ab # can measure vf centre and coverage usin visualField.py import time, scipy, os from psychopy import visual, event, core, monitors, gui, misc from psychopy import hardware import numpy as num #last run of visual field try: #try to load previous info visField = misc.fromFile('visualFieldParams.pickle') except: #if no file use some defaults visField = {'centre_x': 0., 'centre_y': 0., 'size': 6.0} #last run of retinotopy try: #try to load previous info params = misc.fromFile('retinotopyParams.pickle') except: #if no file use some defaults params = { 'observer': 'jwp', 'direction': 'exp', 'cycleTime': 24, 'nCycles': 10,
fout.write(str(expInfo['Seed']) + ", " + str(num_marked_targets) + ", " + str(num_marked_distractors)) self.done = True # Immer alle Tracking Objekte malen for tracking_object in self.tracking_objects: tracking_object.draw() self.window.flip() if len(event.getKeys()) > 0: self.done = True if __name__ == "__main__": try: expInfo = misc.fromFile('last_expInfo.pickle') expInfo['Session'] += 1 except: expInfo = {'Versuchsleiter': 'Alisa', 'Versuchsperson': 'vp01', 'Session': 1, 'Seed': 1} starttime = time.strftime("%Y%m%d_%H%M%S", time.localtime()) expInfo['Datum'] = starttime expInfo['Seed'] = starttime # present a dialogue to change infos dlg = gui.DlgFromDict(expInfo, title='Motion Tracking Experiment', fixed=['Datum']) if dlg.OK: misc.toFile('last_expInfo.pickle', expInfo) # save params to file for next time else: core.quit()
import numpy as np np.set_printoptions(precision=3, suppress=True) import pylab import matplotlib.pyplot as plt import glob from psychopy import misc fig = plt.figure() ax = fig.add_subplot(111) for fn in glob.glob('results/*npy'): data = misc.fromFile(fn.replace('npy', 'pickle')) print data results = np.load(fn) print 'experiment ', fn, ', # trials=', results.shape[1] ax.scatter(results[2, :], results[0, :]) #_ = ax.axis([0., 1., -1.1, 1.1]) _ = ax.set_xlabel('shift') _ = ax.set_ylabel('perceived direction') plt.hist(results[2,:]) alpha = .3 fig = plt.figure(figsize=(12,5)) ax1 = fig.add_subplot(121) ax2 = fig.add_subplot(122) data = [] for fn in glob.glob('results/*npy'): results = np.load(fn) # phi motion ind_phi = results[1, :]==1 for i_fig, color in zip(range(1,4), ['r', 'g', 'b']):
from datetime import datetime from psychopy import core, visual, gui, data, misc, event, sound #Loads different libraries that will be used in this script import csv, random #This function creates the dialog box at the beginning of the script that you enter the subject's name and has the date automatically entered into it try: expInfo = misc.fromFile('lastParams.pickle') except: expInfo = {'participant': '', 'session': '001'} expInfo['dateStr'] = datetime.time(datetime.now()) dlg = gui.DlgFromDict(expInfo, title='File Name', fixed=['dateStr']) if dlg.OK: misc.toFile('lastParams.pickle', expInfo) else: core.quit() fileName = 'Output/' + expInfo['participant'] + '_' + expInfo[ 'session'] + '_' + expInfo[ 'dateStr'] #Stores the information in the dialog box to a variable to be used to create a file dataFile_All = open( fileName + '_All' + '.csv', 'w' ) #Creates a text file that stores the timing and other variables within the script dataFile_All.write( 'TrialTag,TrialStart,TrialDur,QStart,QDur,QResponse,QCorrResponse\n') print dataFile_All Col1 = "Sentence" Col2 = "OpacityS" Col3 = "Illustration" Col4 = "OpacityI" Col5 = "StimCat" Col6 = "Family"
from psychopy import gui, misc, core, misc, data import os, pylab import numpy as np from noiseStaircaseHelpers import toStaircase, printStaircase, outOfStaircase from pandas import DataFrame datFile = misc.fromFile(r'./fingerTransferTest/rawData/pilot_sarah_unadapted_data_2015-02-11_184932.psydat') #print datFile.otherData #print datFile.intensities #print datFile.data print datFile.quantile() #fit curve fit = None try: fit = data.FitLogistic(datFile.intensities, datFile.data, expectedMin=0, sems = 1.0/len(datFile.intensities)) print fit.params except: print('Fit failed.') def plotDataAndPsychometricCurve(staircase,fit,descendingPsycho,threshVal): #Expects staircase, which has intensities and responses in it #May or may not be log steps staircase internals #Plotting with linear axes #Fit is a psychopy data fit object. Assuming that it couldn't handle descendingPsycho so have to invert the values from it intensLinear= outOfStaircase(staircase.intensities, staircase, descendingPsycho) print 'intensLinear', intensLinear if fit is not None: #generate psychometric curve intensitiesForCurve = pylab.arange(min(intensLinear), max(intensLinear), 0.01)
def run_session(self): path = os.path.join(self.res_dir, self.subject) if not os.path.exists(path): os.makedirs(path) psydat_path = os.path.join(path, 'psydat') if not os.path.exists(psydat_path): os.makedirs(psydat_path) # welcome msg = visual.TextStim(self.win, 'Welcome!' + '\n' + ' Press any key to start this session :)', color='black', units='deg', pos=(0, 0), height=0.8) msg.draw() self.win.mouseVisible = False self.win.flip() event.waitKeys() # read staircase parameters conditions = [ dict({'stimulus': key}, **value) for key, value in self.param.items() if key.startswith('stimulus') ] if conditions[0]['stairType'] == 'simple': stairs = data.MultiStairHandler(stairType='simple', conditions=conditions, nTrials=self.trial_nmb, method='sequential') elif conditions[0]['stairType'] == 'quest': stairs = [] for cond in conditions: if self.priors_file_path: prior_file = self.priors_file_path + cond[ 'label'] + '.psydat' print(prior_file) prior_handler = misc.fromFile(prior_file) else: prior_handler = None cur_handler = data.QuestHandler(cond['startVal'], cond['startValSd'], pThreshold=cond['pThreshold'], nTrials=self.trial_nmb, minVal=cond['min_val'], maxVal=cond['max_val'], staircase=prior_handler, extraInfo=cond, grain=0.02) stairs.append(cur_handler) elif conditions[0]['stairType'] == 'psi': stairs = [] for cond in conditions: if self.priors_file_path: prior_file = self.priors_file_path + cond['label'] + '.npy' else: prior_file = None print(prior_file) cur_handler = data.PsiHandler(nTrials=self.trial_nmb, intensRange=[1, 10], alphaRange=[1, 10], betaRange=[0.01, 10], intensPrecision=0.1, alphaPrecision=0.1, betaPrecision=0.01, delta=0.01, extraInfo=cond, prior=prior_file, fromFile=(prior_file is not None)) stairs.append(cur_handler) # write configuration files xpp = config_tools.WriteXpp(self.subject, self.idx) xpp_file = xpp.head(self.cfg_file, self.par_file) config_tools.write_xrl(self.subject, cfg_file=self.cfg_file, par_file=self.par_file, xpp_file=xpp_file) xlsname = path + '/' + self.idx + self.param[ 'noise_condition'] + '.xlsx' """ running staircase """ if isinstance(stairs, data.MultiStairHandler): # start running the staircase using the MultiStairHandler for the up-down method count = 0 for rot, cond in stairs: count += 1 direction = (-1)**(cond['label'].endswith('m') ) # direction as -1 if for minus stim rot = rot * direction # rotation for this trial judge, react_time, trial_time_start = self.run_trial( rot, cond, cond['std'], count) # check whether the theta is valid - if not, the rotation given by staircase should be corrected by # realizable values valid_theta = np.round(np.load(self.hue_list), decimals=1) disp_standard = self.take_closest( valid_theta, cond['standard']) # theta actually displayed stair_test = cond[ 'standard'] + stairs._nextIntensity * direction if stair_test < 0: stair_test += 360 disp_test = self.take_closest(valid_theta, stair_test) disp_intensity = disp_test - disp_standard if disp_intensity > 300: disp_intensity = (disp_test + disp_standard) - 360 stairs.addResponse(judge, abs(disp_intensity)) xpp.task(count, cond, rot, float(disp_intensity), judge, react_time, trial_time_start) if 'escape' in event.waitKeys(): config_tools.write_xrl(self.subject, break_info='userbreak') core.quit() config_tools.write_xrl(self.subject, xls_file=xlsname) stairs.saveAsExcel(xlsname) # save results misc.toFile( os.path.join( psydat_path, self.idx + self.param['noise_condition'] + '.psydat'), stairs) elif isinstance(stairs, list): # start running the staircase using custom interleaving stairs for the quest and psi methods count = 0 rot_all = [] rot_all_disp = [] judge_all = [] estimates = {s.extraInfo['label']: [] for s in stairs} for trial_n in range(self.trial_nmb): for handler_idx, cur_handler in enumerate(stairs): count += 1 direction = (-1)**( cur_handler.extraInfo['label'].endswith('m') ) # direction as -1 if for minus stim if cur_handler._nextIntensity >= 10.0: sys.exit( "Hue difference is out of range! Please enlarge the testing range or take more training!" ) rot = cur_handler._nextIntensity * direction # rotation for this trial if trial_n >= 5: # avoid repeating an intensity more than 3 times last_rots = [ np.round(r, decimals=1) for r in [ rot_all_disp[handler_idx][trial_n - 1], rot_all_disp[handler_idx][trial_n - 2], rot_all_disp[handler_idx][trial_n - 3] ] ] last_resp = [ judge_all[handler_idx][trial_n - 1], judge_all[handler_idx][trial_n - 2], judge_all[handler_idx][trial_n - 3] ] if last_rots[0] == last_rots[1] == last_rots[2] \ and last_resp[0] == last_resp[1] == last_resp[2]: if cur_handler._nextIntensity > 0.5: rot = (cur_handler._nextIntensity - 0.5) * direction print('Intensity decreases by 0.5!') if cur_handler._nextIntensity <= 0.5: rot = (cur_handler._nextIntensity + 0.5) * direction print('Intensity increases by 0.5!') cond = cur_handler.extraInfo judge, react_time, trial_time_start = self.run_trial( rot, cond, cond['std'], count) if len(rot_all) <= handler_idx: rot_all.append([]) rot_all[handler_idx].append(rot) if len(judge_all) <= handler_idx: judge_all.append([]) judge_all[handler_idx].append(judge) valid_theta = np.round(np.load(self.hue_list), decimals=1) disp_standard = self.take_closest(valid_theta, cond['standard']) stair_test = cond[ 'standard'] + rot # calculated test hue for this trial if stair_test < 0: stair_test += 360 disp_test = self.take_closest( valid_theta, stair_test) # actual displayed test hue for this trial disp_intensity = disp_test - disp_standard # actual displayed hue difference if disp_intensity > 300: disp_intensity = (disp_test + disp_standard) - 360 cur_handler.addResponse( judge, abs(disp_intensity) ) # only positive number is accepted by addResponse if len(rot_all_disp ) <= handler_idx: # add displayed intensities rot_all_disp.append([]) rot_all_disp[handler_idx].append(disp_intensity) if isinstance(cur_handler, data.PsiHandler): estimates[cur_handler.extraInfo['label']].append([ cur_handler.estimateLambda()[0], # location cur_handler.estimateLambda768()[1], # slope cur_handler.estimateThreshold(0.75) ]) elif isinstance(cur_handler, data.QuestHandler): estimates[cur_handler.extraInfo['label']].append([ cur_handler.mean(), cur_handler.mode(), cur_handler.quantile(0.5) ]) xpp.task(count, cond, rot, disp_intensity, judge, react_time, trial_time_start) if 'escape' in event.waitKeys(): config_tools.write_xrl(self.subject, break_info='userbreak') core.quit() config_tools.write_xrl(self.subject, xls_file=xlsname) # save results in xls-file workbook = xlsxwriter.Workbook(xlsname) for handler_idx, cur_handler in enumerate(stairs): worksheet = workbook.add_worksheet( cur_handler.extraInfo['label']) worksheet.write('A1', 'Reversal Intensities') worksheet.write('B1', 'Reversal Indices') worksheet.write('C1', 'All Intensities') worksheet.write('D1', 'All Responses') for i in range(len(rot_all[handler_idx])): # worksheet.write('C' + str(i + 2), rot_all[handler_idx][i]) worksheet.write('C' + str(i + 2), rot_all_disp[handler_idx][i]) worksheet.write('D' + str(i + 2), judge_all[handler_idx][i]) workbook.close() # print resulting parameters and estimates for each step res_file_path = os.path.join(path, self.idx + '_estimates.csv') res_writer = csv.writer(open(res_file_path, 'w')) for res_stim, res_vals in estimates.items(): for res_val_id, res_val in enumerate(res_vals): res_writer.writerow([ res_stim, res_val_id, res_val[0], res_val[1], res_val[2] ]) # save each handler into a psydat-file and save posterior into a numpy-file for cur_handler in stairs: file_name = os.path.join( psydat_path, self.idx + self.param['noise_condition'] + cur_handler.extraInfo['label']) misc.toFile(file_name + '.psydat', cur_handler) if isinstance(cur_handler, data.PsiHandler): cur_handler.savePosterior(file_name + '.npy')
# -*- coding: utf-8 -*- """ Created on 15 oct. 2015 ANT task. Created for the CreActive study. Based on Rueda et al. 2004. @author: orduek """ from psychopy import core, visual, gui, data, misc, event, sound import time, os, random, numpy abspath = os.path.abspath(__file__) directory = os.path.dirname(abspath) os.chdir(directory) try:#try to get a previous parameters file expInfo = misc.fromFile('ant.pickle') except:#if not there then use a default set expInfo = {'subject no':'','age':''} expInfo['dateStr']= data.getDateStr() #add the current time # dialouge box for name of subject and file dlg = gui.DlgFromDict(expInfo, title='ANT Task', fixed=['dateStr']) if dlg.OK: misc.toFile('ant.pickle', expInfo)#save params to file for next time else: core.quit()#the user hit cancel so exit # check if folder exist and if not, create it if not os.path.exists('results'): os.makedirs('results') fileName = 'ant' + expInfo['subject no'] + expInfo['dateStr']
xlSheet.title = groupName #make a header row for condition in outCols.keys(): xlSheet.cell(outCols[condition]+'1').value = condition outRow = 2#starting row for data #do the actual analysis, file-by-file condNames = [] for fileName in files: # try: #create a python dict for each set of data RTs={} for condition in outCols.keys(): RTs[condition]=[]#a list for each condition that we'll append data to subj = misc.fromFile(fileName) #process each row from this subject's data file inputRow = 2 dataEnded=False for condN, cond in enumerate(subj.trialList): #about this condition thisSetSize=cond['setSize'] thisPresent= cond['present'] thisCondition = "set%i_%s" %(thisSetSize, thisPresent) #e.g. set6_y #about this response thisRT= subj.data['resp.rt'][condN] thisAcc= subj.data['resp.corr'][condN] #add this RT only if correct ans given if thisAcc==1 and thisRT<2.0: RTs[thisCondition].append(thisRT)
# real session - 24. divided to 18 (go or nogo) and 6 (the opposite). stimulus display for 1,2 or 3s. intertrial was 1.5s # attched is a .odt document with the conditions (as suggested by Prof. Andrea Berger). from psychopy import core, visual, gui, data, misc, event, sound import time, os, random, numpy # now turn to right folder directory = os.getcwd() # get folder os.chdir(directory) # use it # folder='/home/ord/Experiments_BP_Clinic/PCT/' #specify the folder of result files to be saved in # savine last experiment data try: # try to get a previous parameters file expInfo = misc.fromFile("gonogo.pickle") except: # if not there then use a default set expInfo = {"subject no": "", "age": ""} expInfo["dateStr"] = data.getDateStr() # add the current time # dialouge box for name of subject and file dlg = gui.DlgFromDict(expInfo, title="Go/NoGo Task", fixed=["dateStr"]) if dlg.OK: misc.toFile("gonogo.pickle", expInfo) # save params to file for next time else: core.quit() # the user hit cancel so exit # check if folder exist and if not, create it if not os.path.exists("results"): os.makedirs("results") fileName = "GonGo" + expInfo["subject no"] + expInfo["dateStr"]
#!/usr/bin/env python # -*- coding: utf-8 -*- """Determine screen gamma using motion-nulling method of Ledgeway and Smith, 1994, Vision Research, 34, 2727–2740 Instructions: on each trial press the up/down cursor keys depending on the apparent direction of motion of the bars.""" from psychopy import visual, core, event, misc, gui, data from psychopy import filters import numpy as num import time try: #try to load previous info info = misc.fromFile('info_gamma.pickle') except: #if no file use some defaults info={} info['lumModNoise']=0.5 info['lumModLum']=0.1 info['contrastModNoise']=1.0 info['observer']='' info['startGamma']=[3.0, 0.8] info['nTrials']=50 dlg = gui.DlgFromDict(info) #save to a file for future use (ie storing as defaults) if dlg.OK: misc.toFile('info_gamma.pickle',info) else: core.quit() #user cancelled. quit
bootLMLumStd = [] bootSLumStd = [] bootLMSStd = [] everything={} everything['bootStd'] = {} everything['bootLin'] = {} everything['StdHiLowCI'] = {} everything['LinHiLowCI']={} everything['LMLumLin']=[] everything['SLumLin']=[] everything['LMSLin']=[] #Open files for thisFileName in files: dat = misc.fromFile(thisFileName) conditions = dat.trialList #Extract edge positions relative to the markers for n in range(len(dat.data['Condition'])): for m in range(dat.nReps): markerPos = dat.data['Marker'][n][m] finalPos = (markerPos - dat.data['LumEdge'][n][m]) if dat.data['Condition'][n][m]=='Lum': LumPositions.append(finalPos) if dat.data['Condition'][n][m]=='LM': LMPositions.append(finalPos) if dat.data['Condition'][n][m]=='S': SPositions.append(finalPos) if dat.data['Condition'][n][m]=='LMLum': LMLumPositions.append(finalPos) if dat.data['Condition'][n][m]=='SLum':
#Blur width is also a fraction of the overall stimulus i.e. a blur of 0.1 would be 10% of the stimulus or 1 degree #Marker position - the output from the staircase - is between 0 and 10 and is in degrees #lumEdgePos - is a randomly generated number which positions the luminance edge, this is a fraction of the stim #i.e. lumEdgePos = 0.2 the luminance edge will be 2 degrees from the left #the LM edge is positioned relative to the luminance edge - i.e. lm edge position = lumEdgePos+Gap from psychopy import visual, event, filters, monitors, data, sound, gui, misc, core import numpy as np import random, time, os, cPickle from numpy.random import shuffle DEBUG=True #Create a dialog box for settings and participant information try: info=misc.fromFile('conflictParams.pickle') except: info = {'participant' : 'RJS', 'Gap' : 0, 'Edge Contrast LM' : 0.1, 'Edge Contrast S' : 0.1, 'Edge Contrast Lum' : 0.1, 'Flip' : 'n', 'Choose' : 'none'} info['dateStr']=time.strftime("%b%d_%H%M", time.localtime()) dlg = gui.DlgFromDict(info, title='Synthetic Edge Experiment', fixed=['dateStr']) if dlg.OK: misc.toFile('conflictParams.pickle', info) else: core.quit()
#!/usr/bin/env python # stimuli for measuring visual field coverage # original code by jwp # updated for PsychoPy3 by ab # can use saved values in retinotopy.py from psychopy import visual, event, core, monitors, gui, misc from psychopy import monitors import scipy try: #try to load previous info visField = misc.fromFile('visualFieldParams.pickle') except: #if no file use some defaults visField = {'centre': scipy.array((0.0, 0.0)), 'size': 6.0} myMon = monitors.Monitor('testMonitor') scrSize = myMon.getSizePix() #create a window to draw in myWin = visual.Window(scrSize, monitor=myMon, allowGUI=False, units='deg') #INITIALISE SOME STIMULI fixSpot = visual.PatchStim(myWin, tex="none", mask='gauss', pos=(0, 0), size=(0.5, 0.5),
# training is go - nogo - go - nogo with feedback. # stimulus displays for 3s with 1.5s intertrial interval. # real session - 24. divided to 18 (go or nogo) and 6 (the opposite). stimulus display for 1,2 or 3s. intertrial was 1.5s # attched is a .odt document with the conditions (as suggested by Prof. Andrea Berger). from psychopy import core, visual, gui, data, misc, event, sound import time, os, random, numpy # now turn to right folder directory=os.getcwd() # get folder os.chdir(directory) # use it #folder='/home/ord/Experiments_BP_Clinic/PCT/' #specify the folder of result files to be saved in # savine last experiment data try:#try to get a previous parameters file expInfo = misc.fromFile('gonogo.pickle') except:#if not there then use a default set expInfo = {'subject no':''} expInfo['dateStr']= data.getDateStr() #add the current time # dialouge box for name of subject and file dlg = gui.DlgFromDict(expInfo, title='Go/NoGo Task', fixed=['dateStr']) if dlg.OK: misc.toFile('gonogo.pickle', expInfo)#save params to file for next time else: core.quit()#the user hit cancel so exit # check if folder exist and if not, create it if not os.path.exists('results'): os.makedirs('results') fileName = expInfo['subject no'] + expInfo['dateStr']
#Determining isoluminance psychophysically - July 2012 #Modified to keep the azimuth flat from psychopy import visual, core, data, misc, event, gui, monitors, filters import time, copy, os, random import numpy as np from numpy.random import shuffle DEBUG=True try: #try to load previous info info = misc.fromFile('color_nulling.pickle') print info except: #if no file use some defaults info={} info['participant']='' info['dateStr'] = time.strftime("%b%d_%H%M", time.localtime()) dlg = gui.DlgFromDict(info, fixed=['dateStr']) #save to a file for future use (ie storing as defaults) if dlg.OK: misc.toFile('color_nulling.pickle',info) else: core.quit() #user cancelled. quit if DEBUG==True: myWin = visual.Window(size=(1024, 768), monitor = 'testMonitor', units = 'degs', fullscr=False, allowGUI=True) conversionMatrix = None myMon= monitors.Monitor('testMonitor')
if DEBUG: myMon = "testMonitor" allowGUI = True fullscr = False bitsMode = None else: allowGUI = False fullscr = True myMon = "sparrow" allowGUI = False bitsMode = "fast" # Create a dialog box for participant information try: info = misc.fromFile("lastParams.pickle") except: info = {"participant": "RJS"} info["dateStr"] = time.strftime("%b%d_%H%M", time.localtime()) dlg = gui.DlgFromDict(info, title="Dyslexia Vernier Acuity Experiment", fixed=["dateStr"]) if dlg.OK: misc.toFile("lastParams.pickle", info) else: core.quit() # Basic Information info["baseSF"] = 1.0 info["patchSize"] = 3.0 info["monitorDist"] = 52.0 info["nComponents"] = 30 info["displayT"] = 1
#!/usr/bin/env python from psychopy import visual, core, event, data, logging, gui, hardware, misc from random import randint import math, random, time, scipy, os, csv import numpy as np #LAST TR=106 #load last run of colorflash experiment try: #try to load previous info config = misc.fromFile('ROILOC_config.pickle') print 'ROILOC_config.pickle is picked!' #if loading fails use these values except: #if no file use some defaults config = { 'Observer': 'Faruk', 'SubjectID': 'SUBJ01', 'SessionNr': '00', 'RunNr': '00', 'Gender': ['Male', 'Female'], 'attTask': True, 'stimSize': 03.50, #degrees of visual angle 'stimPosX': 05.00, #degrees of visual angle 'trialDur': 12.00, #second 'restDur': 12.00, #second 'flickFreq': 16.0, #hertz 'letterDur': 0.200, #second 'letterSize': 0.6, #degrees of visual angle 'offsetDur': 10 } #second print 'ROILOC_config.pickle is not picked! Using default configuration values.'