def display_sequence(self, sequence): for i, number in enumerate(sequence): # Display number self.screen.blit(self.background, (0, 0)) display.text(self.screen, self.stim_font, number, "center", "center") pygame.display.flip() display.wait(self.STIM_DURATION) # Display blank screen display.blank_screen(self.screen, self.background, self.BETWEEN_STIM_DURATION)
def display_numbers(self, i, data): for number in data['sequence'][i]: self.screen.blit(self.background, (0, 0)) display.text(self.screen, self.stimulus_font, number, "center", "center") pygame.display.flip() display.wait(self.STIM_DURATION) self.screen.blit(self.background, (0, 0)) pygame.display.flip() display.wait(self.INTER_NUMBER_DURATION) return data['sequence'][i]
def display_trial(self, trial_num, data, trial_type): # Check for a quit press after stimulus was shown for event in pygame.event.get(): if event.type == KEYDOWN and event.key == K_F12: sys.exit(0) # Display fixation self.screen.blit(self.background, (0, 0)) display.image(self.screen, self.img_fixation, "center", "center") pygame.display.flip() display.wait(data["fixationTime"][trial_num]) # Display cue self.screen.blit(self.background, (0, 0)) cue_type = data["cue"][trial_num] if cue_type == "nocue": # Display fixation in the center display.image(self.screen, self.img_fixation, "center", "center") elif cue_type == "center": # Display cue in the center display.image(self.screen, self.img_cue, "center", "center") elif cue_type == "double": # Display fixation in the center display.image(self.screen, self.img_fixation, "center", "center") # Display cue above and below fixation display.image( self.screen, self.img_cue, "center", self.screen_y / 2 - self.fixation_h - self.TARGET_OFFSET) display.image(self.screen, self.img_cue, "center", self.screen_y / 2 + self.TARGET_OFFSET) elif cue_type == "spatial": cue_location = data["location"][trial_num] # Display fixation in the center display.image(self.screen, self.img_fixation, "center", "center") # Display cue at target location if cue_location == "top": display.image( self.screen, self.img_cue, "center", self.screen_y / 2 - self.fixation_h - self.TARGET_OFFSET) elif cue_location == "bottom": display.image(self.screen, self.img_cue, "center", self.screen_y / 2 + self.TARGET_OFFSET) pygame.display.flip() # Display cue for certain duration display.wait(self.CUE_DURATION) # Prestim interval with fixation self.screen.blit(self.background, (0, 0)) display.image(self.screen, self.img_fixation, "center", "center") pygame.display.flip() display.wait(self.PRE_STIM_FIXATION_DURATION) # Display flanker target self.screen.blit(self.background, (0, 0)) display.image(self.screen, self.img_fixation, "center", "center") self.display_flanker(data["congruency"][trial_num], data["location"][trial_num], data["direction"][trial_num]) pygame.display.flip() start_time = int(round(time.time() * 1000)) # Clear the event queue before checking for responses pygame.event.clear() response = "NA" wait_response = True while wait_response: for event in pygame.event.get(): if event.type == KEYDOWN and event.key == K_LEFT: response = "left" wait_response = False elif event.type == KEYDOWN and event.key == K_RIGHT: response = "right" wait_response = False elif event.type == KEYDOWN and event.key == K_F12: sys.exit(0) end_time = int(round(time.time() * 1000)) # If time limit has been reached, consider it a missed trial if end_time - start_time >= self.FLANKER_DURATION: wait_response = False # Store reaction time and response rt = int(round(time.time() * 1000)) - start_time data.set_value(trial_num, 'RT', rt) data.set_value(trial_num, 'response', response) correct = 1 if response == data["direction"][trial_num] else 0 data.set_value(trial_num, 'correct', correct) # Display feedback if practice trials if trial_type == "practice": self.screen.blit(self.background, (0, 0)) if correct == 1: display.text(self.screen, self.font, "correct", "center", "center", (0, 255, 0)) else: display.text(self.screen, self.font, "incorrect", "center", "center", (255, 0, 0)) pygame.display.flip() display.wait(self.FEEDBACK_DURATION) # Display fixation during ITI self.screen.blit(self.background, (0, 0)) display.image(self.screen, self.img_fixation, "center", "center") pygame.display.flip() iti = self.ITI_MAX - rt - data["fixationTime"][trial_num] data.set_value(trial_num, 'ITI', iti) display.wait(iti)
def run(self): # Instructions self.screen.blit(self.background, (0, 0)) display.text(self.screen, self.font, "Backwards Digit Span", "center", self.screen_y / 2 - 300) display.text( self.screen, self.font, "You will be shown a number sequence, " "one number at a time", 100, self.screen_y / 2 - 200) display.text(self.screen, self.font, "Memorize the number sequence", 100, self.screen_y / 2 - 100) display.text( self.screen, self.font, "You will then be asked to type the sequence " "in reverse/backwards order. For example...", 100, "center") display.text(self.screen, self.font, "Sequence: 1 2 3 4 5", "center", self.screen_y / 2 + 100) display.text(self.screen, self.font, "Correct: 5 4 3 2 1", "center", self.screen_y / 2 + 150) display.text( self.screen, self.font, "The sequences will get longer throughout the experiment", 100, self.screen_y / 2 + 250) display.text_space(self.screen, self.font, "center", self.screen_y / 2 + 350) pygame.display.flip() display.wait_for_space() # Instructions Practice self.screen.blit(self.background, (0, 0)) display.text(self.screen, self.font, "We will begin with a practice trial...", 100, "center") display.text_space(self.screen, self.font, "center", self.screen_y / 2 + 100) pygame.display.flip() display.wait_for_space() # Practice trial practice_data = pd.DataFrame(['13579'], columns=['sequence']) correct_sequence_p = self.display_numbers(0, practice_data) user_sequence_p = self.number_entry() # Practice feedback screen self.screen.blit(self.background, (0, 0)) # Check if reverse of user input matches the correct sequence if self.check_answer(user_sequence_p, correct_sequence_p): display.text(self.screen, self.font, "Correct", "center", "center", (0, 255, 0)) else: display.text(self.screen, self.font, "Incorrect", "center", "center", (255, 0, 0)) pygame.display.flip() display.wait(self.FEEDBACK_DURATION) # Practice end screen self.screen.blit(self.background, (0, 0)) display.text(self.screen, self.font, "We will now begin the main trials...", 100, "center") display.text_space(self.screen, self.font, "center", self.screen_y / 2 + 100) pygame.display.flip() display.wait_for_space() # Main trials for i in range(len(self.all_data)): correct_sequence = self.display_numbers(i, self.all_data) user_sequence = self.number_entry() self.all_data.set_value(i, 'user_sequence', user_sequence) if self.check_answer(user_sequence, correct_sequence): self.all_data.set_value(i, 'correct', 1) else: self.all_data.set_value(i, 'correct', 0) # End screen self.screen.blit(self.background, (0, 0)) display.text(self.screen, self.font, "End of task", "center", "center") display.text_space(self.screen, self.font, "center", self.screen_y / 2 + 100) pygame.display.flip() display.wait_for_space() print("- Digit span (backwards) complete") return self.all_data
def display_trial(self, trial_num, data): # Check for a quit press after stimulus was shown for event in pygame.event.get(): if event.type == KEYDOWN and event.key == K_F12: sys.exit(0) # Display fixation self.screen.blit(self.background, (0, 0)) display.text(self.screen, self.font, "+", "center", "center", self.colour_font) pygame.display.flip() display.wait(self.FIXATION_DURATION) # Display flanker stimulus self.screen.blit(self.background, (0, 0)) self.display_flanker( data["congruency"][trial_num], data["direction"][trial_num] ) pygame.display.flip() # Clear the event queue before checking for responses pygame.event.clear() response = "NA" too_slow = False wait_response = True post_flanker_blank_shown = False start_time = int(round(time.time() * 1000)) while wait_response: for event in pygame.event.get(): if event.type == KEYDOWN and event.key == K_LEFT: response = "left" wait_response = False elif event.type == KEYDOWN and event.key == K_RIGHT: response = "right" wait_response = False elif event.type == KEYDOWN and event.key == K_F12: sys.exit(0) end_time = int(round(time.time() * 1000)) if end_time - start_time >= self.FLANKER_DURATION: if not post_flanker_blank_shown: self.screen.blit(self.background, (0, 0)) pygame.display.flip() post_flanker_blank_shown = True if end_time - start_time >= self.MAX_RESPONSE_TIME: # If time limit has been reached, consider it a missed trial wait_response = False too_slow = True # Store reaction time and response rt = int(round(time.time() * 1000)) - start_time data.set_value(trial_num, "RT", rt) data.set_value(trial_num, "response", response) if data["compatibility"][trial_num] == "compatible": correct = 1 if response == data["direction"][trial_num] else 0 else: correct = 1 if response != data["direction"][trial_num] else 0 data.set_value(trial_num, "correct", correct) # Display feedback self.screen.blit(self.background, (0, 0)) if too_slow: display.text( self.screen, self.font, "too slow", "center", "center", self.colour_font ) else: if correct == 1: display.text( self.screen, self.font, "correct", "center", "center", (0, 255, 0) ) else: display.text( self.screen, self.font, "incorrect", "center", "center", (255, 0, 0) ) pygame.display.flip() display.wait(self.FEEDBACK_DURATION) if trial_num != data.shape[0] - 1: # Display fixation self.screen.blit(self.background, (0, 0)) display.text( self.screen, self.font, "+", "center", "center", self.colour_font ) pygame.display.flip() display.wait(self.ITI)
def display_trial(self, trial_num, data, trial_type): # Check for a quit press after stimulus was shown for event in pygame.event.get(): if event.type == KEYDOWN and event.key == K_F12: sys.exit(0) # Display fixation self.screen.blit(self.background, (0, 0)) display.image(self.screen, self.img_fixation, "center", "center") pygame.display.flip() display.wait(data["fixationTime"][trial_num]) # Display cue self.screen.blit(self.background, (0, 0)) cue_type = data["cue"][trial_num] if cue_type == "nocue": # Display fixation in the center display.image(self.screen, self.img_fixation, "center", "center") elif cue_type == "center": # Display cue in the center display.image(self.screen, self.img_cue, "center", "center") elif cue_type == "double": # Display fixation in the center display.image(self.screen, self.img_fixation, "center", "center") # Display cue above and below fixation display.image( self.screen, self.img_cue, "center", self.screen_y/2 - self.fixation_h - self.TARGET_OFFSET) display.image(self.screen, self.img_cue, "center", self.screen_y/2 + self.TARGET_OFFSET) elif cue_type == "spatial": cue_location = data["location"][trial_num] # Display fixation in the center display.image(self.screen, self.img_fixation, "center", "center") # Display cue at target location if cue_location == "top": display.image( self.screen, self.img_cue, "center", self.screen_y/2 - self.fixation_h - self.TARGET_OFFSET) elif cue_location == "bottom": display.image(self.screen, self.img_cue, "center", self.screen_y/2 + self.TARGET_OFFSET) pygame.display.flip() # Display cue for certain duration display.wait(self.CUE_DURATION) # Prestim interval with fixation self.screen.blit(self.background, (0, 0)) display.image(self.screen, self.img_fixation, "center", "center") pygame.display.flip() display.wait(self.PRE_STIM_FIXATION_DURATION) # Display flanker target self.screen.blit(self.background, (0, 0)) display.image(self.screen, self.img_fixation, "center", "center") self.display_flanker(data["congruency"][trial_num], data["location"][trial_num], data["direction"][trial_num]) pygame.display.flip() start_time = int(round(time.time() * 1000)) # Clear the event queue before checking for responses pygame.event.clear() response = "NA" wait_response = True while wait_response: for event in pygame.event.get(): if event.type == KEYDOWN and event.key == K_LEFT: response = "left" wait_response = False elif event.type == KEYDOWN and event.key == K_RIGHT: response = "right" wait_response = False elif event.type == KEYDOWN and event.key == K_F12: sys.exit(0) end_time = int(round(time.time() * 1000)) # If time limit has been reached, consider it a missed trial if end_time - start_time >= self.FLANKER_DURATION: wait_response = False # Store reaction time and response rt = int(round(time.time() * 1000)) - start_time data.set_value(trial_num, 'RT', rt) data.set_value(trial_num, 'response', response) correct = 1 if response == data["direction"][trial_num] else 0 data.set_value(trial_num, 'correct', correct) # Display feedback if practice trials if trial_type == "practice": self.screen.blit(self.background, (0, 0)) if correct == 1: display.text(self.screen, self.font, "correct", "center", "center", (0, 255, 0)) else: display.text(self.screen, self.font, "incorrect", "center", "center", (255, 0, 0)) pygame.display.flip() display.wait(self.FEEDBACK_DURATION) # Display fixation during ITI self.screen.blit(self.background, (0, 0)) display.image(self.screen, self.img_fixation, "center", "center") pygame.display.flip() iti = self.ITI_MAX - rt - data["fixationTime"][trial_num] data.set_value(trial_num, 'ITI', iti) display.wait(iti)
def display_trial(self, df, i, r, trial_type): # Clear screen self.screen.blit(self.background, (0, 0)) pygame.display.flip() # Display number sequence self.display_sequence(r['set']) # Display probe warning self.screen.blit(self.background, (0, 0)) display.text(self.screen, self.stim_font, "+", "center", "center") pygame.display.flip() display.wait(self.PROBE_WARN_DURATION) # Display blank screen display.blank_screen(self.screen, self.background, self.BETWEEN_STIM_DURATION) # Display probe self.screen.blit(self.background, (0, 0)) display.text(self.screen, self.stim_font, r['probe'], "center", "center", (0, 0, 255)) # Display key reminders if practice trials if trial_type == "practice": display.image(self.screen, self.img_left, 450 - self.img_left.get_rect().width / 2, self.screen_y / 2 + 150) yes_text = self.font.render("(yes)", 1, (0, 0, 0)) display.text(self.screen, self.font, yes_text, 450 - yes_text.get_rect().width / 2, self.screen_y / 2 + 160) display.image( self.screen, self.img_right, self.screen_x - 450 - self.img_right.get_rect().width / 2, self.screen_y / 2 + 150) no_text = self.font.render("(no)", 1, (0, 0, 0)) display.text(self.screen, self.font, no_text, self.screen_x - 450 - no_text.get_rect().width / 2, self.screen_y / 2 + 160) pygame.display.flip() start_time = int(round(time.time() * 1000)) # Clear the event queue before checking for responses pygame.event.clear() wait_response = True while wait_response: for event in pygame.event.get(): if event.type == KEYDOWN and event.key == K_LEFT: df.set_value(i, "response", "present") wait_response = False elif event.type == KEYDOWN and event.key == K_RIGHT: df.set_value(i, "response", "absent") wait_response = False elif event.type == KEYDOWN and event.key == K_F12: sys.exit(0) end_time = int(round(time.time() * 1000)) # If time limit has been reached, consider it a missed trial if end_time - start_time >= self.PROBE_DURATION: wait_response = False # Store RT rt = int(round(time.time() * 1000)) - start_time df.set_value(i, "RT", rt) # Display blank screen display.blank_screen(self.screen, self.background, self.BETWEEN_STIM_DURATION) # Display feedback self.screen.blit(self.background, (0, 0)) if rt >= self.PROBE_DURATION: df.set_value(i, "correct", 0) display.text(self.screen, self.font, "too slow", "center", "center", (255, 165, 0)) else: if df["probeType"][i] == df["response"][i]: df.set_value(i, "correct", 1) display.text(self.screen, self.font, "correct", "center", "center", (0, 255, 0)) else: df.set_value(i, "correct", 0) display.text(self.screen, self.font, "incorrect", "center", "center", (255, 0, 0)) pygame.display.flip() display.wait(self.FEEDBACK_DURATION) # Display blank screen (ITI) display.blank_screen(self.screen, self.background, self.ITI)
def display_trial(self, df, i, r, trial_type): # Clear screen self.screen.blit(self.background, (0, 0)) pygame.display.flip() # Display number sequence self.display_sequence(r['set']) # Display probe warning self.screen.blit(self.background, (0, 0)) display.text(self.screen, self.stim_font, "+", "center", "center") pygame.display.flip() display.wait(self.PROBE_WARN_DURATION) # Display blank screen display.blank_screen(self.screen, self.background, self.BETWEEN_STIM_DURATION) # Display probe self.screen.blit(self.background, (0, 0)) display.text(self.screen, self.stim_font, r['probe'], "center", "center", (0, 0, 255)) # Display key reminders if practice trials if trial_type == "practice": display.image(self.screen, self.img_left, 450 - self.img_left.get_rect().width/2, self.screen_y/2 + 150) yes_text = self.font.render("(yes)", 1, (0, 0, 0)) display.text(self.screen, self.font, yes_text, 450 - yes_text.get_rect().width/2, self.screen_y/2 + 160) display.image( self.screen, self.img_right, self.screen_x - 450 - self.img_right.get_rect().width/2, self.screen_y/2 + 150) no_text = self.font.render("(no)", 1, (0, 0, 0)) display.text(self.screen, self.font, no_text, self.screen_x - 450 - no_text.get_rect().width/2, self.screen_y/2 + 160) pygame.display.flip() start_time = int(round(time.time() * 1000)) # Clear the event queue before checking for responses pygame.event.clear() wait_response = True while wait_response: for event in pygame.event.get(): if event.type == KEYDOWN and event.key == K_LEFT: df.set_value(i, "response", "present") wait_response = False elif event.type == KEYDOWN and event.key == K_RIGHT: df.set_value(i, "response", "absent") wait_response = False elif event.type == KEYDOWN and event.key == K_F12: sys.exit(0) end_time = int(round(time.time() * 1000)) # If time limit has been reached, consider it a missed trial if end_time - start_time >= self.PROBE_DURATION: wait_response = False # Store RT rt = int(round(time.time() * 1000)) - start_time df.set_value(i, "RT", rt) # Display blank screen display.blank_screen(self.screen, self.background, self.BETWEEN_STIM_DURATION) # Display feedback self.screen.blit(self.background, (0, 0)) if rt >= self.PROBE_DURATION: df.set_value(i, "correct", 0) display.text(self.screen, self.font, "too slow", "center", "center", (255, 165, 0)) else: if df["probeType"][i] == df["response"][i]: df.set_value(i, "correct", 1) display.text(self.screen, self.font, "correct", "center", "center", (0, 255, 0)) else: df.set_value(i, "correct", 0) display.text(self.screen, self.font, "incorrect", "center", "center", (255, 0, 0)) pygame.display.flip() display.wait(self.FEEDBACK_DURATION) # Display blank screen (ITI) display.blank_screen(self.screen, self.background, self.ITI)