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 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_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 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)
prevState = -2 #needed in while loop prevAttState = -1 #needed in while loop attTargetState = -1 #safeguard if the subject presses any button before the scanner signal prevAttTargetState = attTargetState-1 #safeguard logDataLine = -1 logDataArray = [] #create a clock clock = core.Clock() print 'Core clock has been resetted.' print int(clock.getTime()) #GUI OK Cancel if configDlg.OK: #this will be True (user hit OK) or False (cancelled) misc.toFile('ROI_LOC_config.pickle',config) print config['Date'] print 'Configurations saved as "ROILOC_config.pickle"' print 'Waiting for the scanner signal...' #wait for the scanner signal to start scannerStartSignal = True while scannerStartSignal: for keys in event.getKeys(): if keys in ['6']: #UMRAM scanner sends "6". scannerStartSignal = False print int(clock.getTime()) clock.reset()#whenever you like print int(clock.getTime()) print 'The experiment has begun!'
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'] dataFile = open(directory+'/results/'+fileName+'.csv', 'w')#a simple text file with 'comma-separated-values' dataFile.write('trialNo,trial,RT,press,answer\n') # adjust sequence of presentation mywin = visual.Window(fullscr=True,monitor="testMonitor",allowGUI=False,color="White") #rgb=[1,1,1])
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()
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"
#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() #Clocks and Sounds trialClock = core.Clock() tick = sound.Sound('A', octave=6, secs=0.01); tick.setVolume(0.3) if DEBUG==True: myWin = visual.Window(size=(1024, 768), monitor = 'testMonitor', units = 'deg', fullscr=False, allowGUI=True, bitsMode=None) myMon = monitors.Monitor('testMonitor') conversionMatrix = None edgeSize = 10.0 edgeSF = 1.0/10.0 import colorFunctions
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')
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')
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() # the user hit cancel so exit random.seed(expInfo['Seed']) # Initialisierung vom Monitor erfolgt später in Experiment-Klasse, vorübergehend hier background_color = (-1, -1, -1) # Achtung: -1 bis 1 fenster = visual.Window((800, 600), rgb = background_color, monitor="testMonitor", units="deg") trial = Trial(fenster) trial.main() #cleanup
#!/usr/bin/env python """measure your JND in orientation using a staircase method""" from psychopy import core, visual, gui, data, misc, event import time, numpy try: #try to get a previous parameters file expInfo = misc.fromFile('lastParams.pickle') except: #if not there then use a default set expInfo = {'observer': 'jwp', 'refOrientation': 0} dateStr = time.strftime("%b_%d_%H%M", time.localtime()) #add the current time #present a dialogue to change params dlg = gui.DlgFromDict(expInfo, title='simple JND Exp', fixed=['date']) if dlg.OK: misc.toFile('lastParams.pickle', expInfo) #save params to file for next time else: core.quit() #the user hit cancel so exit #make a text file to save data fileName = expInfo['observer'] + dateStr dataFile = open(fileName + '.txt', 'w') dataFile.write('targetSide oriIncrement correct\n') #create window and stimuli globalClock = core.Clock() #to keep track of time trialClock = core.Clock() #to keep track of time win = visual.Window([800, 600], allowGUI=False, monitor='testMonitor', units='deg')
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" Col7 = "ActPass" Col8 = "CanRel" Col9 = "Stx" Col10 = "Anlnan" Col11 = "VrbType"
#create a window to draw in myWin =visual.Window((1280,1024), allowGUI=True, bitsMode=None, units='norm', winType='pyglet', color=(-1,-1,-1)) # Admin expInfo = {'subject':'test','date':data.getDateStr(),'practice':True,'speed time':speedTime,'trial time':1500} #expInfo['dateStr']= data.getDateStr() #add the current time #expInfo['practice'] = True #present a dialogue to change params ok = False while(not ok): dlg = gui.DlgFromDict(expInfo, title='Moving Dots', fixed=['dateStr'],order=['date','subject','practice','speed time','trial time']) if dlg.OK: misc.toFile('lastParams.pickle', expInfo)#save params to file for next time ok = True else: core.quit()#the user hit cancel so exit # setup data file fileName = 'Data/' + expInfo['subject'] + expInfo['date'] + '.csv' dataFile = open(fileName, 'w') #a simple text file with 'comma-separated-values' dataFile.write('subject = ' + str(expInfo['subject']) + "; date = " + str(expInfo['date']) + "; speed time = " + str(expInfo['speed time']) + "; trial time = " + str(expInfo['trial time']) + '\n') dataFile.close() trialClock = core.Clock() speedTime = float(expInfo['speed time'])/1000 trialTime = float(expInfo['trial time'])/1000 practiceTask = expInfo['practice']
'degrees', 'outerRadius': 'degrees', 'fixFraction': 'fraction of the time the fixation point could change', #'wedgeWidth':'width of wedge (deg) for rotating wedge', #'dutyCycle':'eccentricity width of ring (\%)', 'animFreq': 'animation frequency, Hz (drift/flicker frequency)', 'pairWedge': 'draw a second set of wedges on the opposite side (rotating wedges only); 0 o r1 (no/yes)' }) if infoDlg.OK: print(scanDict) #running--save the params misc.toFile('lastrun.pickle', scanDict) else: print('user cancelled') core.quit() if '3T' in scanDict['monitor']: scanDict['monCalFile'] = 'testMonitor' elif 'AS' in scanDict['monitor']: #monCal = '7TAScaldate' #monCal='ASrearProj' scanDict['monCalFile'] = 'testMonitor' elif 'PS' in scanDict['monitor']: scanDict['monCalFile'] = '7TPS' # monCal = '7TPS20120921' elif 'debug' in scanDict['monitor']: scanDict['monCalFile'] = 'laptopSelfScreen'
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 info['nReversals'] = 1
info['N_X'] = mc.N_X # size of image info['N_Y'] = mc.N_Y # size of image info['N_frame_total'] = mc.N_frame # a full period. in time frames info['N_frame'] = mc.N_frame # length of the presented period. in time frames try: dlg = gui.DlgFromDict(info) except: print('Could not load gui... running with defaut parameters') print(info) info['timeStr'] = time.strftime("%b_%d_%H%M", time.localtime()) fileName = 'data/discriminating_v2_' + info['observer'] + '_' + info['timeStr'] + '.pickle' #save to a file for future use (ie storing as defaults) if dlg.OK: misc.toFile(fileName, info) else: print('Interrupted gui... quitting') core.quit() #user cancelled. quit print('generating data') alphas = [-1., -.5, 0., 0.5, 1., 1.5, 2.] fx, fy, ft = mc.get_grids(info['N_X'], info['N_Y'], info['N_frame_total']) colors = [mc.envelope_color(fx, fy, ft, alpha=alpha) for alpha in alphas] slows = [2*mc.rectif(mc.random_cloud(color * mc.envelope_gabor(fx, fy, ft, V_Y=0., V_X = 1.1, B_sf = 10.))) - 1 for color in colors] fasts = [2*mc.rectif(mc.random_cloud(color * mc.envelope_gabor(fx, fy, ft, V_Y=0., V_X = 0.9, B_sf = 10.))) - 1 for color in colors] print('go! ') win = visual.Window([info['screen_width'], info['screen_height']], fullscr=True)
fixed_fields = ['date', 'computer'] while True: # Bring up the dialogue dlg = gui.DlgFromDict(gui_data, order=ordered_names, fixed=fixed_fields, tip=field_tips) if not dlg.OK: core.quit() subj_info = dict(gui_data) if check_exists(subj_info): popup_error('That subj_id already exists.') else: misc.toFile(last_subj_info, subj_info) break if save_order: subj_info['_order'] = ordered_names + fixed_fields return subj_info def load_sounds(stim_dir, match='*.wav'): sound_files = unipath.Path(stim_dir).listdir(match) sounds = {} for sound_file in sound_files: str_path = str(sound_file) # psychopy chokes on unipath.Path sounds[sound_file.stem] = sound.Sound(str_path) return sounds
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'] dataFile = open(directory+'/results/'+fileName+'.csv', 'w')#a simple text file with 'comma-separated-values' dataFile.write('trialNo,block,trialCond,rt,response,answer,stimulus\n') rectColor="DarkSlateBlue" # set retangle default color # make a functino that will get mouse click position # adjust sequence of presentation
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], vertices=((-.02,.02),(-.02,.2),(.02,.2),(.02,.02), (.2,.02),(.2,-.02),(.02,-.02),(.02,-.2),(-.02,-.2), (-.02,-.02),(-.2,-.02),(-.2,.02)), lineColor=None,fillColor=(1,1,1), name='fix') # create stim list vis_stims1 = []
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 info['timeStr']=time.strftime("%b_%d_%H%M", time.localtime()) nFrames=3 cyclesTime=2 cyclesSpace=2 pixels=128 myWin = visual.Window((1024,768), units='pix', allowGUI=True, bitsMode=None) visual.TextStim(myWin, text='building stimuli').draw() myWin.update() globalClock = core.Clock()
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"
center.draw() status.draw() message1.draw() message2.draw() myWin.update() #redraw the buffer for key in event.getKeys(): if key in ['escape', 'q']: carryOn = False event.clearEvents() myWin.close() saveDlg = gui.Dlg('Save params') saveDlg.addText('Save params to file? (cancel to leave previous params)') wasOk = saveDlg.show() if saveDlg.OK: misc.toFile('visualFieldParams.pickle', { 'size': surr.size[0], 'centre_x': surr.pos[0], 'centre_y': surr.pos[1] }) print('Fixation=%.2f,%.2f; Size(radius)=%.2f [SAVED]' % (surr.pos[0], surr.pos[1], surr.size[0] / 2.0)) else: print('Fixation=%.2f,%.2f; Size(radius)=%.2f [not saved]' % (surr.pos[0], surr.pos[1], surr.size[0] / 2.0)) core.quit()
# create a pickle file with important arrays try: os.chdir(outFolderName) # create python dictionary containing important arrays output = { 'ExperimentName': expInfo['expName'], 'Date': expInfo['date'], 'SubjectID': expInfo['participant'], 'Run_Number': expInfo['run'], 'Conditions': conditions, 'Durations': durations, 'KeyPresses': TimeKeyPressedArray, 'DetectedTargets': targetDetected, } # save dictionary as a pickle in output folder misc.toFile(outFileName + '.pickle', output) print 'Pickle data saved as: ' + outFileName + '.pickle' print "***" os.chdir(_thisDir) except: print '(OUTPUT folder could not be created.)' # create prt files for BV try: os.chdir(prtFolderName) durationsMsec = (durations * 1000) durationsMsec = durationsMsec.astype(int) # Set Conditions Names CondNames = [
if interruption: print('!!! \nInterrupted! \n!!!') break if DEBUG: print(' Estimated duration : {0:.3f}'.format(state_cumsum[i])) print(' Block completed in : {0:.3f}'.format(clock.getTime())) i += 1 playSwitch = True print('Estimated total duration: %f' % total_time) print('Completed in: %f' % clock.getTime()) # Output ---------------------------------------------------------------------- # TODO: Change the output format to something else, pickles are bad. output = { 'Run_Number': IDX_RUN, 'blocks': blocks, 'block_durations': block_durations, 'Trigger_Time': trigTime, 'Sound_Play': soundPlay, 'Interruption': interruption } out_file_name = '{}-{}.pickle'.format(SESSION_ID, DATE) misc.toFile(os.path.join(PATH_OUTPUT, out_file_name), output) print('{:~^80}'.format(' Finished ')) win.close() core.quit()
if not error: for name, opts in options.items(): given = subj_info[name] if given not in opts: popup_error('{} not a valid option for {}. ' 'Options are {}'.format(given, name, opts)) error = True break if not error: if Path(data_file_fmt.format(**subj_info)).exists(): popup_error('A data file already exists for that subject.') error = True if not error: misc.toFile(last_subj_info, subj_info) break return subj_info def popup_error(text): errorDlg = gui.Dlg(title="Error", pos=(200, 400)) errorDlg.addText('Error: ' + text, color='Red') errorDlg.show() if __name__ == '__main__': subj = get_subj_info('subj_info.yaml', DATA_FILE) exp = Experiment(subj) exp.run()
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==False: myWin = visual.Window(size=(1280, 1024), monitor = 'heron', units = 'degs', fullscr=True, allowGUI=False, bitsMode='fast') myMon=monitors.Monitor('heron') conversionMatrix = myMon.getDKL_RGB(RECOMPUTE=False) #Checking Responses
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() tick = sound.Sound('A', octave=6, secs=0.01); tick.setVolume(0.3) if DEBUG==True: myWin = visual.Window(size=(1024, 768), monitor = 'testMonitor', units = 'deg', fullscr=False, allowGUI=True, bitsMode=None) myMon = monitors.Monitor('testMonitor') conversionMatrix = None edgeSize = 10.0 edgeSF = 1.0/10.0 import colorFunctions
hlsGrList[2]) rgbBl = colorsys.hls_to_rgb(hlsBlList[0], hlsBlList[1], hlsBlList[2]) rgbYe = colorsys.hls_to_rgb(hlsYeList[0], hlsYeList[1], hlsYeList[2]) #f*****g psychopy SPECIAL RGB transformation S_rgbRe = rgb_to_rgbPsychopy( rgbRe) #S_ stands for psychopy's special RGB S_rgbGr = rgb_to_rgbPsychopy(rgbGr) S_rgbBl = rgb_to_rgbPsychopy(rgbBl) S_rgbYe = rgb_to_rgbPsychopy(rgbYe) #colors.pickle output equilumColors = { 'S_equiRed': S_rgbRe, 'S_equiGreen': S_rgbGr, 'S_equiBlue': S_rgbBl, 'S_equiYellow': S_rgbYe, #S_ stands for psychopy's special RGB 'equiRed': rgbRe, 'equiGreen': rgbGr, 'equiBlue': rgbBl, 'equiYellow': rgbYe } misc.toFile('equilumColors.pickle', equilumColors) print 'Adjusted colors saved as "equilumColors.pickle"' myWin.close() print int(clock.getTime()) core.quit()
'cycleTime': 24, 'nCycles': 10, 'dutyCycleWedge': 0.125, 'dutyCycleAnn': 0.25, } #set some more that don't change params['timeStr'] = time.strftime("%b_%d_%H%M", time.localtime()) params['size'] = float(visField['size']) params['centre_x'] = visField['centre_x'] params['centre_y'] = visField['centre_y'] dlg = gui.DlgFromDict(dictionary=params, title="Retinotopy", fixed=['timeStr']) if dlg.OK: misc.toFile('retinotopyParams.pickle', params) else: core.quit() #user cancelled. quit print("Observer:%s, run:%s, time:%s" % (params['observer'], params['direction'], params['timeStr'])) DEBUG = True if DEBUG: winSize = (1024, 768) myWin = visual.Window(size=winSize, monitor='testMonitor', bitsMode=None, allowGUI=True, units='deg')
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'] dataFile = open(directory+'/results/'+fileName+'.csv', 'w')#a simple text file with 'comma-separated-values' dataFile.write('nTrial,trialList,ans,press,block,rt,length\n') rectColor="Blue" # set retangle default color # make a functino that will get mouse click position # adjust sequence of presentation
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 info["ISI"] = 1.0 info["cycles"] = 1 # number of times the trial handler will cycle through the conditions reactionClock = core.Clock() tick = sound.Sound("A", octave=6, secs=0.01) tick.setVolume(0.3) error = sound.Sound("C", octave=4, secs=0.75)
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