def PresentStimulus(self): if self.debug: print "Experiment.PresentStimulus" commonFunc.writeFile( self.exptLogFileName, "%s, Beginning of Experiment.PresentStimulus()\n" % commonFunc.get_time_stamp()) ret_delay = self.E_UI.mediaPanel.presentStimulus(self.currTrial) ''' if the the stimuli are sounds (or it needs some delay before accepting user-response for some reason), the function should return the length of all the sounds to be played, therefore trial_start_time and user_response is properly started in time. ''' if ret_delay == None: # no delay indicated ### enable the user-response right away if self.timeoutTime != None: self.timeoutTimerSetUp() # TimeOut Setting self.trialStartTime = time.time() # record trial-starting-time self.E_UI.EnableResponseGUI() else: if exptApp.settings.has_key("ONSET_OF_RT_MEASUREMENT"): self.response_enabling_timer = wx.FutureCall( ret_delay + exptApp.settings["ONSET_OF_RT_MEASUREMENT"], self.OnEnableResponse) else: self.response_enabling_timer = wx.FutureCall( ret_delay, self.OnEnableResponse) self.E_UI.DisableResponseGUI() commonFunc.writeFile( self.exptLogFileName, "%s, End of Experiment.PresentStimulus()\n" % commonFunc.get_time_stamp())
def PreSection_SlideShow(self, preSectionType): # Process for the pre-section (Slide-Show) ; show images with the interval if self.debug: print "Experiment.PreSection_SlideShow" commonFunc.writeFile( self.exptLogFileName, "%s, Experiment.PreSection_SlideShow()\n" % commonFunc.get_time_stamp()) trialInterval = exptApp.exptDetails["-1"][ "TRIAL_INTERVAL"] / 1000 # trial-interval is in millisecond for i in range(exptApp.exptDetails["-1"]["NUM_TRIALS"]): self.currTrial = exptApp.exptDetails["-1"][str( i)] # store stimuli-list to be displayed in this trial ### randomize the stimuli when the setting allows. self.stimuliIndices = range(self.currTrial["NUM_STIMULI"] ) # indices of stimuli for this trial if exptApp.settings["RANDOMIZE_STIMULI"]: shuffle(self.stimuliIndices) self.E_UI.mediaPanel.showImage(self.currTrial) # show image wx.SafeYield() ### play the sound when it's applicable if preSectionType == "SLIDESHOW_WITH_SOUND": soundStim = self.currTrial[ str(self.currTrial["NUM_STIMULI"] - 1)] # the last one is sound-stimulus self.E_UI.mediaPanel.LoadSound(soundStim) self.E_UI.mediaPanel.PlaySound() # play it. time.sleep(trialInterval) # wait for the interval self.currTrial = "" self.stimuliIndices = []
def Timeout(self): ''' Function for processes on the time-out event. ''' if self.debug: print "Experiment.Timeout" commonFunc.writeFile( self.exptLogFileName, "%s, Experiment.Timeout()\n" % commonFunc.get_time_stamp()) self.E_UI.DisableResponseGUI( ) # Disabling subject-input until the new-trial begins. self.E_UI.mediaPanel.panel.Hide( ) # Hide the panel containing the stimulus ### Giving a negative-feedback feedback = self.E_UI.getFeedback() if feedback != 'none' and feedback != None: if feedback == 'custom': # if feedback is customized self.E_UI.mediaPanel.presentFeedback( "negative") # call the function in the mediaPanel else: result = self.E_UI.presentFeedback( "negative", feedback) # call the regular function if result == 'delay': time.sleep(1.5) self.userTimedOut = True # timed out self.currCorrectness = 'Incorrect' self.RT = -1 # negative reaction-time self.EndTrial(response=None) # move to 'EndTrial'
def EndTrial(self, response): if self.debug: print "Experiment.EndTrial" commonFunc.writeFile( self.exptLogFileName, "%s, Experiment.EndTrial()\n" % commonFunc.get_time_stamp()) if self.exptRunning == False: wx.MessageBox('The experiment is over!\nPlease inform your host.', 'Notice') return if self.userTimedOut == True: print " Time Out!" else: if self.timeoutTime != None: self.timeoutTimer.Stop() if response != 'CANCEL_RESPONSE': self.WriteResponse(response) # Store the result data # when the individual module has its own result data saving function, it sends the message, 'CANCEL_RESPONSE' ### Imply Post-Trial-Interval when it's applicable. if self.ITI == None or self.ITI == 0: # no inter-trial-interval self.repeat_trial_decision() else: self.ITI_timer = wx.FutureCall(self.ITI, self.repeat_trial_decision) '''
def StartTrial(self): if self.debug: print "Experiment.StartTrial" try: self.exptApp.expt.ITI_timer.Stop() except: pass self.currTrialIdx = self.trialIndices[self.trialCounter] # currently chosen trial-index self.currTrial = exptApp.exptDetails[str(self.currSectionIdx)][str(self.currTrialIdx)] # store stimuli-list to be displayed in this trial ### randomize the stimuli when the setting allows. self.stimuliIndices = range(self.currTrial["NUM_STIMULI"]) # indices of stimuli for this trial if exptApp.settings["RANDOMIZE_STIMULI"] and self.repeated_trial == False: # RANDOMIZE_STIMULI is True and the current trials is NOT a repeated trial shuffle(self.stimuliIndices) self.currCorrectness = "None" # will be 'Correct' when 'correctResponse' matches with the actual response from the subject self.RT = None # Reaction time will be recorded in 'HandleGUIResponse' of the 'display' self.trialStartTime = None # trialStartTime init. It will be recorded after all the stimuli are presented. self.E_UI.mediaPanel.panel.Show() # show the panel for presenting stimulus commonFunc.writeFile(self.exptLogFileName, "%s, Experiment.StartTrial(), trial#%.2i\n"%(commonFunc.get_time_stamp(), self.currTrialIdx)) if exptApp.settings.has_key("PULSE_ON_TRIAL") and exptApp.settings["PULSE_ON_TRIAL"] == True: self.E_UI.play_pulse() # play a pulse-sound as a signal of the beginning of each trial wx.CallAfter(self.E_UI.Raise) # E_UI frame gets focus self.PresentStimulus() ### Hide cursor on the objects when the setting allows it. if exptApp.settings["HIDE_CURSOR"]: cursor = wx.StockCursor(wx.CURSOR_BLANK) wx.FutureCall(1, self.E_UI.set_cursor_on_objects, cursor)
def WriteResponse(self, response): if self.debug: print "Experiment.WriteResponse" commonFunc.writeFile( self.exptLogFileName, "%s, Experiment.WriteResponse()\n" % commonFunc.get_time_stamp()) if self.exptRunning == True: files = '' for i in range(self.currTrial["NUM_STIMULI"]): files += self.currTrial[str(i)]["FILEPATH"] + ' | ' files = files.rstrip(' | ') correctResponse = "None" if self.currTrial.has_key("CORRECT_RESPONSE"): correctResponse = self.currTrial["CORRECT_RESPONSE"] responseString = "" if response == None: # user timed out if self.userTimedOut == True: responseString = str( correctResponse) + ", timeout, timeout" else: responseString = str(correctResponse) + ", None, None" else: response = str(response) responseString = str(correctResponse) + ", " + str( response) + ", " + self.currCorrectness outString = "%i, %i, %.3f, %s, %s\n" % (self.currSectionIdx, self.currTrialIdx, self.RT, responseString, files) commonFunc.writeFile(self.exptDataFileName, outString)
def play_pulse(self): ''' play a pulse-sound as a signal ''' if self.debug: print "E_UI.play_pulse" self.sound = wx.Sound(os.path.join(exptApp.input_path, exptApp.file_pulse_sound)) self.sound.Play(wx.SOUND_ASYNC) commonFunc.writeFile(self.expt.exptLogFileName, "%s, A pluse sound was played\n"%commonFunc.get_time_stamp())
def EndSection(self): if self.debug: print "Experiment.EndSection" commonFunc.writeFile(self.exptLogFileName, "%s, Experiment.EndSection()\n"%commonFunc.get_time_stamp()) self.sectionCounter += 1 if self.sectionCounter < exptApp.exptDetails["NUM_SECTIONS"]: # when a Section ends, wait for the same amount of time for the 'ITI'-setting time.sleep(self.ITI/1000) self.StartSection() else: self.EndExpt()
def EndExpt(self): if self.debug: print "Experiment.EndExpt" commonFunc.writeFile(self.exptLogFileName, "%s, Experiment.EndExpt()\n"%commonFunc.get_time_stamp()) self.exptRunning = False if exptApp.settings["POST_Q"]: # if there is a post-experiment Questionnaire post_Q_answer = self.E_UI.mediaPanel.show_post_Q() commonFunc.writeFile(self.exptDataFileName, post_Q_answer) wx.MessageBox('Experiment Finished.\nThank you for participating!', 'Acknowledgement') self.E_UI.OnCloseWindow(None)
def play_pulse(self): ''' play a pulse-sound as a signal ''' if self.debug: print "E_UI.play_pulse" self.sound = wx.Sound( os.path.join(exptApp.input_path, exptApp.file_pulse_sound)) self.sound.Play(wx.SOUND_ASYNC) commonFunc.writeFile( self.expt.exptLogFileName, "%s, A pluse sound was played\n" % commonFunc.get_time_stamp())
def EndSection(self): if self.debug: print "Experiment.EndSection" commonFunc.writeFile( self.exptLogFileName, "%s, Experiment.EndSection()\n" % commonFunc.get_time_stamp()) self.sectionCounter += 1 if self.sectionCounter < exptApp.exptDetails["NUM_SECTIONS"]: # when a Section ends, wait for the same amount of time for the 'ITI'-setting time.sleep(self.ITI / 1000) self.StartSection() else: self.EndExpt()
def InitExpt(self): if self.debug: print "Experiment.InitExpt" sInfo = self.GetSubjectInfo() # runs dialog and retrieve the subject's info self.subjectInfo = sInfo if sInfo != None: self.exptDateTime = time.asctime() ### Defining result-filename time_stamp = commonFunc.get_time_stamp() self.exptDataFileName = os.path.join(exptApp.output_path, time_stamp + ".csv") self.exptLogFileName = os.path.join(exptApp.output_path, time_stamp + ".log") msg = "* Time-stamp (year_month_day_hour_minute_second_microsecond) was obtained from built-in <datetime> function of Python.\n" msg += "Time-stamp, Log\n" msg += "----------------------------\n" commonFunc.writeFile(self.exptLogFileName, msg) # Just for the case the same file-name exists. while os.path.isfile(self.exptDataFileName): self.exptDataFileName = self.exptDataFileName.replace(".csv", "X.csv") # writing some info and header _txt = "Experiment started at, %s\n"%self.exptDateTime _txt += "Subject info: \n" for key in sInfo.iterkeys(): _txt += "%s, %s\n"%(key, sInfo[key]) _txt += "========================\n" commonFunc.writeFile(self.exptDataFileName, _txt) if exptApp.settings.has_key("RESULT_HEADER"): commonFunc.writeFile(self.exptDataFileName, exptApp.settings["RESULT_HEADER"] + "\n--------------------\n") else: commonFunc.writeFile(self.exptDataFileName, "\n--------------------\n") if self.debug == True: print "Subject Info: ", sInfo print "Starting Experimenter Debugger" self.StartExpt()
def StartExpt(self): if self.debug: print "Experiment.StartExpt" self.exptRunning = True commonFunc.writeFile(self.exptLogFileName, "%s, Experiment.StartExpt()\n"%commonFunc.get_time_stamp()) if exptApp.exptDetails.has_key("-1"): # There's some pre-section self.sectionCounter = -1 preSectionType = exptApp.exptDetails["-1"]["SECTION_TYPE"].upper() if preSectionType == "SLIDESHOW" or preSectionType == "SLIDESHOW_WITH_SOUND": # This pre-section's type is 'SlideShow' self.PreSection_SlideShow(preSectionType) self.sectionCounter = 0 self.sectionIndices = range(exptApp.exptDetails["NUM_SECTIONS"]) # indices of sections if exptApp.settings["RANDOMIZE_SECTIONS"]: shuffle(self.sectionIndices) # randomize the sections when the setting allows. self.StartSection()
def EndExpt(self): if self.debug: print "Experiment.EndExpt" commonFunc.writeFile( self.exptLogFileName, "%s, Experiment.EndExpt()\n" % commonFunc.get_time_stamp()) self.exptRunning = False if exptApp.settings[ "POST_Q"]: # if there is a post-experiment Questionnaire post_Q_answer = self.E_UI.mediaPanel.show_post_Q() commonFunc.writeFile(self.exptDataFileName, post_Q_answer) wx.MessageBox('Experiment Finished.\nThank you for participating!', 'Acknowledgement') self.E_UI.OnCloseWindow(None)
def HandleGUIResponse(self, value, additionalInfo = None): ''' Function for getting response from the experiment module and proceed with it ''' if self.debug: print "E_UI.HandleGUIResponse" commonFunc.writeFile(self.expt.exptLogFileName, "%s, E_UI.HandleGUIResponse()\n"%commonFunc.get_time_stamp()) self.DisableResponseGUI() # Disabling subject-input until the new-trial begins. self.mediaPanel.panel.Hide() # Hide the panel containing the stimulus # If there's additionalInfo from the caller module, then put it after 'value' if value == 'CANCEL_RESPONSE': self.expt.ProcessGUIResponse(value) # Go to the next step right away else: if self.expt.RT == None: self.expt.RT = (time.time() - self.expt.trialStartTime) # Record the response-time # if 'self.expt.RT' is not None, it means RT was already recorded in the ResponsePanel for some reason. if self.expt.timeoutTime != None: self.expt.timeoutTimer.Stop() ### Decide 'correctness' when 'correctResponse'-key exists and it's not 'none' if self.expt.currTrial.has_key("CORRECT_RESPONSE") and self.expt.currTrial["CORRECT_RESPONSE"] != None and self.expt.currTrial["CORRECT_RESPONSE"].lower() <> 'none': correctResponse = [] correctResponse = self.expt.currTrial["CORRECT_RESPONSE"].split("/") # there could be multiple correctResponses self.expt.currCorrectness = 'Incorrect' for i in range(len(correctResponse)): # if any of correct-responses matches with the subject's response, then change the variable to the 'Correct' if correctResponse[i].strip().lower() == value.lower(): self.expt.currCorrectness = 'Correct' feedback = self.getFeedback() feedback_result = None if feedback != 'none' and feedback != None: # Giving a proper feedback when 'feedback'-key exists and it's not 'none' feedBackType = "negative" if self.expt.currCorrectness == 'Correct': feedBackType = "positive" if feedback == 'custom': # if feedback is customized self.mediaPanel.presentFeedback(feedBackType) # call the function in the mediaPanel else: feedback_result = self.presentFeedback(feedBackType, feedback) # call the regular function if additionalInfo != None: value = str(value) + ", " + str(additionalInfo) ### passes the GUI value back to the Expt object if feedback_result == 'delay': wx.FutureCall(1500, self.expt.ProcessGUIResponse, value) elif feedback_result == None: self.expt.ProcessGUIResponse(value)
def StartSection(self): if self.debug: print "Experiment.StartSection" self.currSectionIdx = self.sectionIndices[self.sectionCounter] # currently chosen section-index commonFunc.writeFile(self.exptLogFileName, "%s, Experiment.StartSection(), section#%.2i\n"%(commonFunc.get_time_stamp(), self.currSectionIdx)) self.trialCounter = 0 self.trialIndices = range(exptApp.exptDetails[str(self.currSectionIdx)]["NUM_TRIALS"]) # indices of trials if exptApp.settings["RANDOMIZE_TRIALS"]: shuffle(self.trialIndices) # randomize the trials when the setting allows. ### show the section-title & section-description when it's applicable if exptApp.exptDetails[str(self.currSectionIdx)].has_key("SECTION_TITLE"): # if there's a section-title if len(exptApp.exptDetails[str(self.currSectionIdx)]["SECTION_TITLE"].strip()) > 0 : # and it's not a blank msg = exptApp.exptDetails[str(self.currSectionIdx)]["SECTION_TITLE"] if exptApp.exptDetails[str(self.currSectionIdx)].has_key("SECTION_DESC"): # if there's a section-description if len(exptApp.exptDetails[str(self.currSectionIdx)]["SECTION_DESC"].strip()) > 0 : # and it's not a blank msg = msg + "\n" + exptApp.exptDetails[str(self.currSectionIdx)]["SECTION_DESC"] dlg = PopupDialog(self.E_UI, -1, "Note", msg, None, (350, 200), cancel_btn=False) dlg.ShowModal() dlg.Destroy() if exptApp.exptDetails[str(self.currSectionIdx)].has_key("SECTION_TIMEOUT"): # if there's 'section_timeout', apply it self.timeoutTime = exptApp.exptDetails[str(self.currSectionIdx)]["SECTION_TIMEOUT"] else: self.timeoutTime = None if exptApp.exptDetails[str(self.currSectionIdx)].has_key("SECTION_ITI"): # if there's 'section_iti' (InterTrialInterval; value in milliseconds from user response to next trial) self.ITI = exptApp.exptDetails[str(self.currSectionIdx)]["SECTION_ITI"] else: self.ITI = None if exptApp.exptDetails[str(self.currSectionIdx)].has_key("SECTION_RTOI") and \ exptApp.exptDetails[str(self.currSectionIdx)]["SECTION_RTOI"] == True: # if there's 'section_RTOI(REPEAT_TRIAL_ON_INCORRECT)', SECTION_RTOI gets applied rather than general 'REPEAT_TRIAL_ON_INCORRECT'. self.REPEAT_TRIAL_ON_INCORRECT = True else: self.REPEAT_TRIAL_ON_INCORRECT = False # SECTION_FEEDBACK is used in the 'getFeedback()' in the E_UI class. self.StartTrial()
def StartTrial(self): if self.debug: print "Experiment.StartTrial" try: self.exptApp.expt.ITI_timer.Stop() except: pass self.currTrialIdx = self.trialIndices[ self.trialCounter] # currently chosen trial-index self.currTrial = exptApp.exptDetails[str(self.currSectionIdx)][str( self.currTrialIdx )] # store stimuli-list to be displayed in this trial ### randomize the stimuli when the setting allows. self.stimuliIndices = range( self.currTrial["NUM_STIMULI"]) # indices of stimuli for this trial if exptApp.settings[ "RANDOMIZE_STIMULI"] and self.repeated_trial == False: # RANDOMIZE_STIMULI is True and the current trials is NOT a repeated trial shuffle(self.stimuliIndices) self.currCorrectness = "None" # will be 'Correct' when 'correctResponse' matches with the actual response from the subject self.RT = None # Reaction time will be recorded in 'HandleGUIResponse' of the 'display' self.trialStartTime = None # trialStartTime init. It will be recorded after all the stimuli are presented. self.E_UI.mediaPanel.panel.Show( ) # show the panel for presenting stimulus commonFunc.writeFile( self.exptLogFileName, "%s, Experiment.StartTrial(), trial#%.2i\n" % (commonFunc.get_time_stamp(), self.currTrialIdx)) if exptApp.settings.has_key("PULSE_ON_TRIAL") and exptApp.settings[ "PULSE_ON_TRIAL"] == True: self.E_UI.play_pulse( ) # play a pulse-sound as a signal of the beginning of each trial wx.CallAfter(self.E_UI.Raise) # E_UI frame gets focus self.PresentStimulus() ### Hide cursor on the objects when the setting allows it. if exptApp.settings["HIDE_CURSOR"]: cursor = wx.StockCursor(wx.CURSOR_BLANK) wx.FutureCall(1, self.E_UI.set_cursor_on_objects, cursor)
def StartExpt(self): if self.debug: print "Experiment.StartExpt" self.exptRunning = True commonFunc.writeFile( self.exptLogFileName, "%s, Experiment.StartExpt()\n" % commonFunc.get_time_stamp()) if exptApp.exptDetails.has_key("-1"): # There's some pre-section self.sectionCounter = -1 preSectionType = exptApp.exptDetails["-1"]["SECTION_TYPE"].upper() if preSectionType == "SLIDESHOW" or preSectionType == "SLIDESHOW_WITH_SOUND": # This pre-section's type is 'SlideShow' self.PreSection_SlideShow(preSectionType) self.sectionCounter = 0 self.sectionIndices = range( exptApp.exptDetails["NUM_SECTIONS"]) # indices of sections if exptApp.settings["RANDOMIZE_SECTIONS"]: shuffle(self.sectionIndices ) # randomize the sections when the setting allows. self.StartSection()
def EndTrial(self, response): if self.debug: print "Experiment.EndTrial" commonFunc.writeFile(self.exptLogFileName, "%s, Experiment.EndTrial()\n"%commonFunc.get_time_stamp()) if self.exptRunning == False: wx.MessageBox('The experiment is over!\nPlease inform your host.', 'Notice') return if self.userTimedOut == True: print " Time Out!" else: if self.timeoutTime != None: self.timeoutTimer.Stop() if response != 'CANCEL_RESPONSE': self.WriteResponse(response) # Store the result data # when the individual module has its own result data saving function, it sends the message, 'CANCEL_RESPONSE' ### Imply Post-Trial-Interval when it's applicable. if self.ITI == None or self.ITI == 0: # no inter-trial-interval self.repeat_trial_decision() else: self.ITI_timer = wx.FutureCall(self.ITI, self.repeat_trial_decision) '''
def WriteResponse(self, response): if self.debug: print "Experiment.WriteResponse" commonFunc.writeFile(self.exptLogFileName, "%s, Experiment.WriteResponse()\n"%commonFunc.get_time_stamp()) if self.exptRunning == True: files = '' for i in range(self.currTrial["NUM_STIMULI"]): files += self.currTrial[str(i)]["FILEPATH"] + ' | ' files = files.rstrip(' | ') correctResponse = "None" if self.currTrial.has_key("CORRECT_RESPONSE"): correctResponse = self.currTrial["CORRECT_RESPONSE"] responseString = "" if response == None: # user timed out if self.userTimedOut == True: responseString = str(correctResponse) + ", timeout, timeout" else: responseString = str(correctResponse) + ", None, None" else: response = str(response) responseString = str(correctResponse) + ", " + str(response) + ", " + self.currCorrectness outString = "%i, %i, %.3f, %s, %s\n"% (self.currSectionIdx, self.currTrialIdx, self.RT, responseString, files) commonFunc.writeFile(self.exptDataFileName, outString)
def PreSection_SlideShow(self, preSectionType): # Process for the pre-section (Slide-Show) ; show images with the interval if self.debug: print "Experiment.PreSection_SlideShow" commonFunc.writeFile(self.exptLogFileName, "%s, Experiment.PreSection_SlideShow()\n"%commonFunc.get_time_stamp()) trialInterval = exptApp.exptDetails["-1"]["TRIAL_INTERVAL"] / 1000 # trial-interval is in millisecond for i in range(exptApp.exptDetails["-1"]["NUM_TRIALS"]): self.currTrial = exptApp.exptDetails["-1"][str(i)] # store stimuli-list to be displayed in this trial ### randomize the stimuli when the setting allows. self.stimuliIndices = range(self.currTrial["NUM_STIMULI"]) # indices of stimuli for this trial if exptApp.settings["RANDOMIZE_STIMULI"]: shuffle(self.stimuliIndices) self.E_UI.mediaPanel.showImage(self.currTrial) # show image wx.SafeYield() ### play the sound when it's applicable if preSectionType == "SLIDESHOW_WITH_SOUND": soundStim = self.currTrial[str(self.currTrial["NUM_STIMULI"]-1)] # the last one is sound-stimulus self.E_UI.mediaPanel.LoadSound(soundStim) self.E_UI.mediaPanel.PlaySound() # play it. time.sleep(trialInterval) # wait for the interval self.currTrial = "" self.stimuliIndices = []
def PresentStimulus(self): if self.debug: print "Experiment.PresentStimulus" commonFunc.writeFile(self.exptLogFileName, "%s, Beginning of Experiment.PresentStimulus()\n"%commonFunc.get_time_stamp()) ret_delay = self.E_UI.mediaPanel.presentStimulus(self.currTrial) ''' if the the stimuli are sounds (or it needs some delay before accepting user-response for some reason), the function should return the length of all the sounds to be played, therefore trial_start_time and user_response is properly started in time. ''' if ret_delay == None: # no delay indicated ### enable the user-response right away if self.timeoutTime != None: self.timeoutTimerSetUp() # TimeOut Setting self.trialStartTime = time.time() # record trial-starting-time self.E_UI.EnableResponseGUI() else: if exptApp.settings.has_key("ONSET_OF_RT_MEASUREMENT"): self.response_enabling_timer = wx.FutureCall(ret_delay + exptApp.settings["ONSET_OF_RT_MEASUREMENT"], self.OnEnableResponse) else: self.response_enabling_timer = wx.FutureCall(ret_delay, self.OnEnableResponse) self.E_UI.DisableResponseGUI() commonFunc.writeFile(self.exptLogFileName, "%s, End of Experiment.PresentStimulus()\n"%commonFunc.get_time_stamp())
def Timeout(self): ''' Function for processes on the time-out event. ''' if self.debug: print "Experiment.Timeout" commonFunc.writeFile(self.exptLogFileName, "%s, Experiment.Timeout()\n"%commonFunc.get_time_stamp()) self.E_UI.DisableResponseGUI() # Disabling subject-input until the new-trial begins. self.E_UI.mediaPanel.panel.Hide() # Hide the panel containing the stimulus ### Giving a negative-feedback feedback = self.E_UI.getFeedback() if feedback != 'none' and feedback != None: if feedback == 'custom': # if feedback is customized self.E_UI.mediaPanel.presentFeedback("negative") # call the function in the mediaPanel else: result = self.E_UI.presentFeedback("negative", feedback) # call the regular function if result == 'delay': time.sleep(1.5) self.userTimedOut = True # timed out self.currCorrectness = 'Incorrect' self.RT = -1 # negative reaction-time self.EndTrial(response = None) # move to 'EndTrial'
def InitExpt(self): if self.debug: print "Experiment.InitExpt" sInfo = self.GetSubjectInfo( ) # runs dialog and retrieve the subject's info self.subjectInfo = sInfo if sInfo != None: self.exptDateTime = time.asctime() ### Defining result-filename time_stamp = commonFunc.get_time_stamp() self.exptDataFileName = os.path.join(exptApp.output_path, time_stamp + ".csv") self.exptLogFileName = os.path.join(exptApp.output_path, time_stamp + ".log") msg = "* Time-stamp (year_month_day_hour_minute_second_microsecond) was obtained from built-in <datetime> function of Python.\n" msg += "Time-stamp, Log\n" msg += "----------------------------\n" commonFunc.writeFile(self.exptLogFileName, msg) # Just for the case the same file-name exists. while os.path.isfile(self.exptDataFileName): self.exptDataFileName = self.exptDataFileName.replace( ".csv", "X.csv") # writing some info and header _txt = "Experiment started at, %s\n" % self.exptDateTime _txt += "Subject info: \n" for key in sInfo.iterkeys(): _txt += "%s, %s\n" % (key, sInfo[key]) _txt += "========================\n" commonFunc.writeFile(self.exptDataFileName, _txt) if exptApp.settings.has_key("RESULT_HEADER"): commonFunc.writeFile( self.exptDataFileName, exptApp.settings["RESULT_HEADER"] + "\n--------------------\n") else: commonFunc.writeFile(self.exptDataFileName, "\n--------------------\n") if self.debug == True: print "Subject Info: ", sInfo print "Starting Experimenter Debugger" self.StartExpt()
def HandleGUIResponse(self, value, additionalInfo=None): ''' Function for getting response from the experiment module and proceed with it ''' if self.debug: print "E_UI.HandleGUIResponse" commonFunc.writeFile( self.expt.exptLogFileName, "%s, E_UI.HandleGUIResponse()\n" % commonFunc.get_time_stamp()) self.DisableResponseGUI( ) # Disabling subject-input until the new-trial begins. self.mediaPanel.panel.Hide() # Hide the panel containing the stimulus # If there's additionalInfo from the caller module, then put it after 'value' if value == 'CANCEL_RESPONSE': self.expt.ProcessGUIResponse( value) # Go to the next step right away else: if self.expt.RT == None: self.expt.RT = (time.time() - self.expt.trialStartTime ) # Record the response-time # if 'self.expt.RT' is not None, it means RT was already recorded in the ResponsePanel for some reason. if self.expt.timeoutTime != None: self.expt.timeoutTimer.Stop() ### Decide 'correctness' when 'correctResponse'-key exists and it's not 'none' if self.expt.currTrial.has_key( "CORRECT_RESPONSE") and self.expt.currTrial[ "CORRECT_RESPONSE"] != None and self.expt.currTrial[ "CORRECT_RESPONSE"].lower() <> 'none': correctResponse = [] correctResponse = self.expt.currTrial[ "CORRECT_RESPONSE"].split( "/") # there could be multiple correctResponses self.expt.currCorrectness = 'Incorrect' for i in range(len(correctResponse)): # if any of correct-responses matches with the subject's response, then change the variable to the 'Correct' if correctResponse[i].strip().lower() == value.lower(): self.expt.currCorrectness = 'Correct' feedback = self.getFeedback() feedback_result = None if feedback != 'none' and feedback != None: # Giving a proper feedback when 'feedback'-key exists and it's not 'none' feedBackType = "negative" if self.expt.currCorrectness == 'Correct': feedBackType = "positive" if feedback == 'custom': # if feedback is customized self.mediaPanel.presentFeedback( feedBackType) # call the function in the mediaPanel else: feedback_result = self.presentFeedback( feedBackType, feedback) # call the regular function if additionalInfo != None: value = str(value) + ", " + str(additionalInfo) ### passes the GUI value back to the Expt object if feedback_result == 'delay': wx.FutureCall(1500, self.expt.ProcessGUIResponse, value) elif feedback_result == None: self.expt.ProcessGUIResponse(value)
def StartSection(self): if self.debug: print "Experiment.StartSection" self.currSectionIdx = self.sectionIndices[ self.sectionCounter] # currently chosen section-index commonFunc.writeFile( self.exptLogFileName, "%s, Experiment.StartSection(), section#%.2i\n" % (commonFunc.get_time_stamp(), self.currSectionIdx)) self.trialCounter = 0 self.trialIndices = range(exptApp.exptDetails[str( self.currSectionIdx)]["NUM_TRIALS"]) # indices of trials if exptApp.settings["RANDOMIZE_TRIALS"]: shuffle(self.trialIndices ) # randomize the trials when the setting allows. ### show the section-title & section-description when it's applicable if exptApp.exptDetails[str(self.currSectionIdx)].has_key( "SECTION_TITLE"): # if there's a section-title if len(exptApp.exptDetails[str(self.currSectionIdx)] ["SECTION_TITLE"].strip()) > 0: # and it's not a blank msg = exptApp.exptDetails[str( self.currSectionIdx)]["SECTION_TITLE"] if exptApp.exptDetails[str(self.currSectionIdx)].has_key( "SECTION_DESC"): # if there's a section-description if len( exptApp.exptDetails[str(self.currSectionIdx)] ["SECTION_DESC"].strip()) > 0: # and it's not a blank msg = msg + "\n" + exptApp.exptDetails[str( self.currSectionIdx)]["SECTION_DESC"] dlg = PopupDialog(self.E_UI, -1, "Note", msg, None, (350, 200), cancel_btn=False) dlg.ShowModal() dlg.Destroy() if exptApp.exptDetails[str( self.currSectionIdx)].has_key("SECTION_TIMEOUT"): # if there's 'section_timeout', apply it self.timeoutTime = exptApp.exptDetails[str( self.currSectionIdx)]["SECTION_TIMEOUT"] else: self.timeoutTime = None if exptApp.exptDetails[str( self.currSectionIdx)].has_key("SECTION_ITI"): # if there's 'section_iti' (InterTrialInterval; value in milliseconds from user response to next trial) self.ITI = exptApp.exptDetails[str( self.currSectionIdx)]["SECTION_ITI"] else: self.ITI = None if exptApp.exptDetails[str(self.currSectionIdx)].has_key("SECTION_RTOI") and \ exptApp.exptDetails[str(self.currSectionIdx)]["SECTION_RTOI"] == True: # if there's 'section_RTOI(REPEAT_TRIAL_ON_INCORRECT)', SECTION_RTOI gets applied rather than general 'REPEAT_TRIAL_ON_INCORRECT'. self.REPEAT_TRIAL_ON_INCORRECT = True else: self.REPEAT_TRIAL_ON_INCORRECT = False # SECTION_FEEDBACK is used in the 'getFeedback()' in the E_UI class. self.StartTrial()