def run_block(self, block_num, total_blocks, block_type): cur_block = self.create_block(block_num, self.combinations, block_type) for i in range(cur_block.shape[0]): self.display_trial(i, cur_block, block_type) if block_type == "main": # Add block data to all_data self.all_data = pd.concat([self.all_data, cur_block]) # End of block screen if block_num != total_blocks - 1: # If not the final block self.screen.blit(self.background, (0, 0)) display.text( self.screen, self.font, "End of current block. " "Start next block when you're ready...", 100, "center", ) display.text_space(self.screen, self.font, "center", (self.screen_y / 2) + 100) pygame.display.flip() display.wait_for_space()
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 number_entry(self): user_sequence = "" # Clear the event queue before checking for responses pygame.event.clear() entry = True while entry: for event in pygame.event.get(): if event.type == KEYDOWN and event.key == K_RETURN: entry = False elif event.type == KEYDOWN and event.key == K_F12: sys.exit(0) elif event.type == KEYDOWN and event.key == K_BACKSPACE: if user_sequence: # Remove last number in entered string user_sequence = user_sequence[:-1] elif event.type == KEYDOWN: try: # Only allow key press of used numbers key_pressed = int(pygame.key.name(event.key)) if key_pressed in self.NUMBERS_USED: user_sequence += pygame.key.name(event.key) except ValueError: pass self.screen.blit(self.background, (0, 0)) display.text( self.screen, self.font, "Type the sequence in backwards order:", 50, self.screen_y / 4, ) display.text(self.screen, self.stimulus_font, user_sequence, "center", "center") pygame.display.flip() return user_sequence
def run_block(self, block_num, total_blocks, block_type): cur_block = self.create_block( block_num, self.combinations, block_type) for i in range(cur_block.shape[0]): self.display_trial(i, cur_block, block_type) if block_type == "main": # Add block data to all_data self.all_data = pd.concat([self.all_data, cur_block]) # End of block screen if block_num != total_blocks - 1: # If not the final block self.screen.blit(self.background, (0, 0)) display.text(self.screen, self.font, "End of current block. " "Start next block when you're ready...", 100, "center") display.text_space(self.screen, self.font, "center", (self.screen_y/2) + 100) pygame.display.flip() display.wait_for_space()
def run(self): # Instructions self.screen.blit(self.background, (0, 0)) display.text(self.screen, self.font, "SART", "center", self.screen_y / 2 - 250, (255, 255, 255)) display.text(self.screen, self.font, "Numbers will appear in the center of the screen.", 100, self.screen_y / 2 - 150, (255, 255, 255)) display.text(self.screen, self.font, "Press the spacebar after you see a number.", 100, self.screen_y / 2 - 50, (255, 255, 255)) display.text( self.screen, self.font, "However, if the number is a 3, " "do NOT press the spacebar.", 100, self.screen_y / 2 + 50, (255, 255, 255)) display.text( self.screen, self.font, "Please respond as quickly, " "and as accurately, as possible", 100, self.screen_y / 2 + 150, (255, 255, 255)) display.text_space(self.screen, self.font, "center", self.screen_y / 2 + 300, (255, 255, 255)) 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 few practice trials...", "center", "center", (255, 255, 255)) display.text_space(self.screen, self.font, "center", self.screen_y / 2 + 100, (255, 255, 255)) pygame.display.flip() display.wait_for_space() # Blank screen display.blank_screen(self.screen, self.background, self.BLANK_DURATION) # Show practice trials practice_trials = pd.DataFrame([5, 7, 7, 3, 9, 2, 1, 3, 8, 6], columns=['stimulus']) for i in range(practice_trials.shape[0]): self.display_trial(i, practice_trials) # Practice end screen self.screen.blit(self.background, (0, 0)) display.text(self.screen, self.font, "End of practice trials", 100, self.screen_y / 2 - 100, (255, 255, 255)) display.text(self.screen, self.font, "We will now begin the main trials...", 100, "center", (255, 255, 255)) display.text_space(self.screen, self.font, "center", self.screen_y / 2 + 100, (255, 255, 255)) pygame.display.flip() display.wait_for_space() # Blank screen display.blank_screen(self.screen, self.background, self.BLANK_DURATION) # Show main trials for i in range(self.all_data.shape[0]): self.display_trial(i, self.all_data) # Rearrange dataframe columns = [ 'trial', 'stimulus', 'stimSize', 'RT', 'key press', 'accuracy' ] self.all_data = self.all_data[columns] # End screen self.screen.blit(self.background, (0, 0)) display.text(self.screen, self.font, "End of task", "center", "center", (255, 255, 255)) display.text_space(self.screen, self.font, "center", self.screen_y / 2 + 100, (255, 255, 255)) pygame.display.flip() display.wait_for_space() print("- SART complete") return self.all_data
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 run(self): # Instructions screen self.screen.blit(self.background, (0, 0)) display.text(self.screen, self.font, "Sternberg Task", "center", 100) display.text(self.screen, self.font, "You will see a sequence of numbers, one at a time. " "Try your best to memorize them", 100, 200) display.text(self.screen, self.stim_font, "8 - 5 - 4 - 1 - 0 - 9", "center", 300) display.text(self.screen, self.font, "You will then be shown a single test number in blue", 100, 400) display.text(self.screen, self.stim_font, "0", "center", 500, (0, 0, 255)) display.text(self.screen, self.font, "If this number was in the original sequence, " "press the LEFT arrow", 100, 600) display.text(self.screen, self.font, "If this number was NOT in the original sequence, " "press the RIGHT arrow", 100, 700) display.text(self.screen, self.font, "Try to do this as quickly, " "and as accurately, as possible", 100, 800) display.text_space(self.screen, self.font, "center", 900) pygame.display.flip() display.wait_for_space() # Practice ready screen self.screen.blit(self.background, (0, 0)) display.text(self.screen, self.font, "We will begin with some practice trials...", "center", "center") display.text_space(self.screen, self.font, "center", self.screen_y/2 + 100) pygame.display.flip() display.wait_for_space() # Practice trials for i, r in self.practice_trials.iterrows(): self.display_trial(self.practice_trials, i, r, "practice") # Main trials ready screen self.screen.blit(self.background, (0, 0)) display.text(self.screen, self.font, "End of practice trials.", 100, 100) display.text(self.screen, self.font, "You may move on to the main " "trials when you're ready", 100, 300) display.text(self.screen, self.font, "Remember to respond as quickly " "and as accurately as possible", 100, 500) display.text(self.screen, self.font, "Your reaction time and accuracy" " will be recorded", 100, 600) display.text_space(self.screen, self.font, "center", 800) pygame.display.flip() display.wait_for_space() # Main trials for i, block in enumerate(self.blocks): for j, r in block.iterrows(): self.display_trial(block, j, r, "main") # If this is not the final block, show instructions for next block if i != len(self.blocks)-1: display.text(self.screen, self.font, "End of block.", 100, 200) display.text(self.screen, self.font, "Take a short break, and press space when you're " "ready to start the next block...", 100, 400) display.text_space(self.screen, self.font, "center", 700) pygame.display.flip() display.wait_for_space() # 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() # Concatenate blocks and add trial numbers all_data = pd.concat(self.blocks) all_data['trialNum'] = range(1, len(all_data) + 1) print "- Sternberg Task complete" return all_data
def display_flanker(self, flanker_type, direction): stimulus = self.flanker_stim[direction][flanker_type] display.text( self.screen, self.font_stim, stimulus, "center", "center", self.colour_font )
def start(self): # Store input values sub_num = self.subNumBox.text() condition = self.conditionBox.text() age = self.ageBox.text() ra = self.raBox.text() current_date = datetime.datetime.now().strftime("%Y-%m-%d %H:%M") if self.maleRadio.isChecked(): sex = "male" else: sex = "female" # Get *selected* tasks and task order selected_tasks = [] for index in range(self.taskList.count()): # State 2 is set when item is selected if self.taskList.item(index).checkState() == 2: # Add selected task to task list selected_tasks.append(str(self.taskList.item(index).text())) # Check to see if a random order is desired # If so, shuffle tasks if self.random_order_selected(): random.shuffle(selected_tasks) # Check for required inputs if not selected_tasks: self.error_dialog("No tasks selected") elif not ra: self.error_dialog("Please enter RA name...") elif not sub_num: self.error_dialog("Please enter a subject number...") elif not condition: self.error_dialog("Please enter a condition number...") elif not age: self.error_dialog("Please enter an age...") elif not self.maleRadio.isChecked() and not \ self.femaleRadio.isChecked(): self.error_dialog("Please select a sex...") else: # Store subject info into a dataframe subject_info = pd.DataFrame(data=[ (str(current_date), str(sub_num), str(condition), int(age), str(sex), str(ra), ", ".join(selected_tasks)) ], columns=[ "datetime", "sub_num", "condition", "age", "sex", "RA", "tasks" ]) # Check if subject number already exists existing_subs = [ x.split("_")[0] for x in os.listdir(self.dataPath) ] if sub_num in existing_subs: self.error_dialog("Subject number already exists") else: # Create the excel writer object and save the file data_file_name = "%s_%s.xls" % (sub_num, condition) output_file = os.path.join(self.dataPath, data_file_name) writer = pd.ExcelWriter(output_file) subject_info.to_excel(writer, "info", index=False) writer.save() # Minimize battery UI self.showMinimized() # Get most recent task settings from file self.get_settings() # Center all pygame windows if not fullscreen if not self.task_fullscreen: pos_x = self.res_width // 2 - self.task_width // 2 pos_y = self.res_height // 2 - self.task_height // 2 os.environ["SDL_VIDEO_WINDOW_POS"] = \ "%s, %s" % (str(pos_x), str(pos_y)) # Initialize pygame pygame.init() # Load beep sound beep_sound = pygame.mixer.Sound( os.path.join(self.base_dir, "tasks", "media", "beep_med.wav")) # Set pygame icon image image = os.path.join(self.base_dir, "images", "icon_sml.png") icon_img = pygame.image.load(image) pygame.display.set_icon(icon_img) # Create primary task window # pygame_screen is passed to each task as the display window if self.task_fullscreen: self.pygame_screen = pygame.display.set_mode( (0, 0), pygame.FULLSCREEN) else: if self.task_borderless: self.pygame_screen = pygame.display.set_mode( (self.task_width, self.task_height), pygame.NOFRAME) else: self.pygame_screen = pygame.display.set_mode( (self.task_width, self.task_height)) background = pygame.Surface(self.pygame_screen.get_size()) background = background.convert() # Run each task # Return and save their output to dataframe/excel for task in selected_tasks: if task == "Attention Network Test (ANT)": # Set number of blocks for ANT ant_task = ant.ANT(self.pygame_screen, background, blocks=self.ant_blocks) # Run ANT ant_data = ant_task.run() # Save ANT data to excel ant_data.to_excel(writer, "ANT", index=False) elif task == "Digit Span (backwards)": digitspan_backwards_task = digitspan_backwards.DigitspanBackwards( self.pygame_screen, background) # Run Digit span (Backwards) digitspan_backwards_data = digitspan_backwards_task.run( ) # Save digit span (backwards) data to excel digitspan_backwards_data.to_excel( writer, "Digit span (backwards)", index=False) elif task == "Eriksen Flanker Task": flanker_task = flanker.Flanker( self.pygame_screen, background, self.flanker_dark_mode, self.flanker_sets_practice, self.flanker_sets_main, self.flanker_blocks_compat, self.flanker_blocks_incompat, self.flanker_block_order) # Run Eriksen Flanker flanker_data = flanker_task.run() # Save flanker data to excel flanker_data.to_excel(writer, "Eriksen Flanker", index=False) elif task == "Mental Rotation Task": mrt_task = mrt.MRT(self.pygame_screen, background) # Run MRT mrt_data = mrt_task.run() # Save MRT data to excel mrt_data.to_excel(writer, "MRT", index=False) elif task == "Raven's Progressive Matrices": ravens_task = ravens.Ravens( self.pygame_screen, background, start=self.ravens_start, numTrials=self.ravens_trials) # Run Raven's Matrices ravens_data = ravens_task.run() # Save ravens data to excel ravens_data.to_excel(writer, "Ravens Matrices", index=False) elif task == "Sternberg Task": sternberg_task = sternberg.Sternberg( self.pygame_screen, background, blocks=self.sternberg_blocks) # Run Sternberg Task sternberg_data = sternberg_task.run() # Save sternberg data to excel sternberg_data.to_excel(writer, "Sternberg", index=False) elif task == "Sustained Attention to Response Task (SART)": sart_task = sart.SART(self.pygame_screen, background) # Run SART sart_data = sart_task.run() # Save SART data to excel sart_data.to_excel(writer, "SART", index=False) # Play beep after each task if self.task_beep: beep_sound.play() # Save excel file writer.save() # End of experiment screen pygame.display.set_caption("Cognitive Battery") pygame.mouse.set_visible(1) background.fill((255, 255, 255)) self.pygame_screen.blit(background, (0, 0)) font = pygame.font.SysFont("arial", 30) display.text(self.pygame_screen, font, "End of Experiment", "center", "center") pygame.display.flip() display.wait_for_space() # Quit pygame pygame.quit() print("--- Experiment complete") self.close()
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 run(self): if self.BLOCK_ORDER == "choose": # If the order is "choose" but one of the block types has a 0, then dont show choose screen if self.BLOCKS_COMPAT == 0: self.BLOCK_ORDER = "incompatible" elif self.BLOCKS_INCOMPAT == 0: self.BLOCK_ORDER = "compatible" else: self.screen.blit(self.background, (0, 0)) display.text( self.screen, self.font, "Choose block order:", 100, self.screen_y / 2 - 300, self.colour_font, ) display.text( self.screen, self.font, "1 - Compatible first", 100, self.screen_y / 2 - 200, self.colour_font, ) display.text( self.screen, self.font, "2 - Incompatible first", 100, self.screen_y / 2 - 150, self.colour_font, ) pygame.display.flip() wait_response = True while wait_response: for event in pygame.event.get(): if event.type == KEYDOWN and event.key == K_1: self.BLOCK_ORDER = "compatible" wait_response = False elif event.type == KEYDOWN and event.key == K_2: self.BLOCK_ORDER = "incompatible" wait_response = False elif event.type == KEYDOWN and event.key == K_F12: sys.exit(0) # Set block order if self.BLOCK_ORDER == "compatible": self.block_type_list = (["compatible"] * self.BLOCKS_COMPAT) + ( ["incompatible"] * self.BLOCKS_INCOMPAT ) elif self.BLOCK_ORDER == "incompatible": self.block_type_list = (["incompatible"] * self.BLOCKS_INCOMPAT) + ( ["compatible"] * self.BLOCKS_COMPAT ) # Instructions self.screen.blit(self.background, (0, 0)) display.text( self.screen, self.font, "Eriksen Flanker Task", "center", self.screen_y / 2 - 300, self.colour_font, ) display.text( self.screen, self.font, "Keep your eyes on the fixation cross at the " "start of each trial:", 100, self.screen_y / 2 - 200, self.colour_font, ) display.text( self.screen, self.font, "+", "center", self.screen_y / 2 - 150, self.colour_font, ) display.text( self.screen, self.font, "A set of arrows will appear:", 100, self.screen_y / 2 - 100, self.colour_font, ) display.text( self.screen, self.font_stim, self.flanker_stim["left"]["incongruent"], "center", self.screen_y / 2 - 60, self.colour_font, ) if self.block_type_list[0] == "compatible": display.text( self.screen, self.font, "Use the Left / Right arrow keys to indicate " "the pointing direction of the CENTER arrow.", 100, self.screen_y / 2 + 70, self.colour_font, ) display.text( self.screen, self.font, "In example above, you should press the LEFT key.", 100, self.screen_y / 2 + 120, self.colour_font, ) elif self.block_type_list[0] == "incompatible": display.text( self.screen, self.font, "Use the Left / Right arrow keys to indicate " "the OPPOSITE pointing direction of the CENTER arrow.", 100, self.screen_y / 2 + 70, self.colour_font, ) display.text( self.screen, self.font, "In example above, you should press the RIGHT key.", 100, self.screen_y / 2 + 120, self.colour_font, ) display.text( self.screen, self.font, "Respond as quickly, and as accurately, as you can", 100, self.screen_y / 2 + 200, self.colour_font, ) display.text_space( self.screen, self.font, "center", (self.screen_y / 2) + 300, self.colour_font, ) pygame.display.flip() display.wait_for_space() # Instructions Practice self.screen.blit(self.background, (0, 0)) display.text( self.screen, self.font, "We'll begin with some practice trials...", "center", "center", self.colour_font, ) display.text_space( self.screen, self.font, "center", self.screen_y / 2 + 100, self.colour_font ) pygame.display.flip() display.wait_for_space() # Practice trials self.run_block(0, 1, "practice", self.block_type_list[0]) # Instructions Practice End self.screen.blit(self.background, (0, 0)) display.text( self.screen, self.font, "We will now begin the main trials...", 100, self.screen_y / 2, self.colour_font, ) display.text_space( self.screen, self.font, "center", self.screen_y / 2 + 200, self.colour_font ) pygame.display.flip() display.wait_for_space() # Main task second half if self.block_type_list[0] == "compatible": for i in range(self.BLOCKS_COMPAT): self.run_block(i, self.BLOCKS_COMPAT, "main", self.block_type_list[0]) elif self.block_type_list[0] == "incompatible": for i in range(self.BLOCKS_INCOMPAT): self.run_block(i, self.BLOCKS_INCOMPAT, "main", self.block_type_list[0]) # Second half (if more than one compatibility type) if self.block_type_list[0] != self.block_type_list[-1]: self.screen.blit(self.background, (0, 0)) display.text( self.screen, self.font, "End of first half. Please inform the experimenter.", 100, self.screen_y / 2, self.colour_font, ) display.text_space( self.screen, self.font, "center", self.screen_y / 2 + 200, self.colour_font, ) pygame.display.flip() display.wait_for_space() # Practice instructions self.screen.blit(self.background, (0, 0)) display.text( self.screen, self.font, "For the second half, the task will be slightly different:", 100, self.screen_y / 2 - 300, self.colour_font, ) display.text( self.screen, self.font_stim, self.flanker_stim["left"]["incongruent"], "center", self.screen_y / 2 - 250, self.colour_font, ) if self.block_type_list[-1] == "compatible": display.text( self.screen, self.font, "This time, indicate the pointing direction of the CENTER arrow", 100, self.screen_y / 2 - 100, self.colour_font, ) display.text( self.screen, self.font, "So in the example above, you would press LEFT", 100, self.screen_y / 2, self.colour_font, ) elif self.block_type_list[-1] == "incompatible": display.text( self.screen, self.font, "This time, indicate the OPPOSITE pointing direction of the CENTER arrow", 100, self.screen_y / 2 - 100, self.colour_font, ) display.text( self.screen, self.font, "So in the example above, you would press RIGHT", 100, self.screen_y / 2, self.colour_font, ) display.text( self.screen, self.font, "Respond as quickly, and as accurately, as you can", 100, self.screen_y / 2 + 100, self.colour_font, ) display.text_space( self.screen, self.font, "center", self.screen_y / 2 + 250, self.colour_font, ) pygame.display.flip() display.wait_for_space() # Instructions Practice self.screen.blit(self.background, (0, 0)) display.text( self.screen, self.font, "We'll begin with some practice trials...", "center", "center", self.colour_font, ) display.text_space( self.screen, self.font, "center", self.screen_y / 2 + 100, self.colour_font, ) pygame.display.flip() display.wait_for_space() # Practice trials self.run_block(0, 1, "practice", self.block_type_list[-1]) # Instructions Practice End self.screen.blit(self.background, (0, 0)) display.text( self.screen, self.font, "We will now begin the main trials...", 100, self.screen_y / 2, self.colour_font, ) display.text_space( self.screen, self.font, "center", self.screen_y / 2 + 200, self.colour_font, ) pygame.display.flip() display.wait_for_space() # Main task if self.block_type_list[-1] == "compatible": for i in range(self.BLOCKS_COMPAT): self.run_block( self.BLOCKS_INCOMPAT + i, self.BLOCKS_COMPAT, "main", self.block_type_list[-1], True, ) elif self.block_type_list[-1] == "incompatible": for i in range(self.BLOCKS_INCOMPAT): self.run_block( self.BLOCKS_COMPAT + i, self.BLOCKS_INCOMPAT, "main", self.block_type_list[-1], True, ) # Create trial number column self.all_data["trial"] = list(range(1, len(self.all_data) + 1)) # Rearrange the dataframe columns = [ "trial", "block", "compatibility", "congruency", "direction", "response", "correct", "RT", ] self.all_data = self.all_data[columns] # End screen self.screen.blit(self.background, (0, 0)) display.text( self.screen, self.font, "End of task", "center", "center", self.colour_font ) display.text_space( self.screen, self.font, "center", self.screen_y / 2 + 100, self.colour_font ) pygame.display.flip() display.wait_for_space() print("- Flanker complete") return self.all_data
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, i, data): # Randomly choose font size for this trial size_index = random.randint(0, len(self.stim_fonts) - 1) trial_font = self.stim_fonts[size_index] key_press = 0 data.set_value(i, 'RT', 1150) # Display number self.screen.blit(self.background, (0, 0)) display.text(self.screen, trial_font, str(data["stimulus"][i]), "center", "center", (255, 255, 255)) pygame.display.flip() # Get start time in ms 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_SPACE: key_press = 1 data.set_value(i, 'RT', int(round(time.time() * 1000)) - start_time) elif event.type == KEYDOWN and event.key == K_F12: sys.exit(0) end_time = int(round(time.time() * 1000)) # Stop this loop if stim duration has passed if end_time - start_time >= self.STIM_DURATION: wait_response = False # Display mask self.screen.blit(self.background, (0, 0)) display.image(self.screen, self.img_mask, "center", "center") pygame.display.flip() wait_response = True while wait_response: for event in pygame.event.get(): if event.type == KEYDOWN and event.key == K_SPACE: if key_press == 0: key_press = 1 data.set_value( i, 'RT', int(round(time.time() * 1000)) - start_time) elif event.type == KEYDOWN and event.key == K_F12: sys.exit(0) end_time = int(round(time.time() * 1000)) # Stop this loop if mask duration has passed if end_time - start_time >= self.MASK_DURATION: wait_response = False # Check if response is correct if data["stimulus"][i] == 3: if key_press == 0: accuracy = 1 else: accuracy = 0 else: if key_press == 0: accuracy = 0 else: accuracy = 1 # Store key press data in dataframe data.set_value(i, 'key press', key_press) data.set_value(i, 'accuracy', accuracy) data.set_value(i, 'stimSize', self.STIMSIZES_PT[size_index])
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 start(self): # Store input values sub_num = self.subNumBox.text() experiment_id = self.experimentIDBox.text() condition = self.conditionBox.text() age = self.ageBox.text() ra = self.raBox.text() current_date = datetime.datetime.now().strftime("%Y-%m-%d %H:%M") if self.maleRadio.isChecked(): sex = 'male' else: sex = 'female' # Get *selected* tasks and task order selected_tasks = [] for index in range(self.taskList.count()): # State 2 is set when item is selected if self.taskList.item(index).checkState() == 2: # Add selected task to task list selected_tasks.append(str(self.taskList.item(index).text())) # Check to see if a random order is desired # If so, shuffle tasks if self.random_order_selected(): random.shuffle(selected_tasks) # Check for required inputs if not selected_tasks: self.error_dialog('No tasks selected') elif not ra: self.error_dialog('Please enter RA name...') elif not sub_num: self.error_dialog('Please enter a subject number...') elif not experiment_id: self.error_dialog('Please enter an experiment ID...') elif not condition: self.error_dialog('Please enter a condition number...') elif not age: self.error_dialog('Please enter an age...') elif not self.maleRadio.isChecked() and not \ self.femaleRadio.isChecked(): self.error_dialog('Please select a sex...') else: # Store subject info into a dataframe subject_info = pd.DataFrame( data=[(str(current_date), str(sub_num), str(experiment_id), str(condition), int(age), str(sex), str(ra), ', '.join(selected_tasks))], columns=['datetime', 'sub_num', 'expID', 'condition', 'age', 'sex', 'RA', 'tasks'] ) # Set the output file name data_file_name = "%s_%s_%s.xls" % (experiment_id, sub_num, condition) # Check if file already exists output_file = os.path.join(self.dataPath, data_file_name) if os.path.isfile(output_file): self.error_dialog('Data file already exists') else: # Create the excel writer object and save the file writer = pd.ExcelWriter(output_file) subject_info.to_excel(writer, 'info', index=False) writer.save() # Minimize battery UI self.showMinimized() # Get most recent task window settings from file self.get_task_settings() # Center all pygame windows if not fullscreen if not self.task_fullscreen: pos_x = str(self.res_width / 2 - self.task_width / 2) pos_y = str(self.res_height / 2 - self.task_height / 2) os.environ['SDL_VIDEO_WINDOW_POS'] = \ "%s, %s" % (pos_x, pos_y) # Initialize pygame pygame.init() # Set pygame icon image image = os.path.join(self.directory, "images", "icon_sml.png") icon_img = pygame.image.load(image) pygame.display.set_icon(icon_img) # Create primary task window # pygame_screen is passed to each task as the display window if self.task_fullscreen: self.pygame_screen = pygame.display.set_mode( (0, 0), pygame.FULLSCREEN) else: if self.task_borderless: self.pygame_screen = pygame.display.set_mode( (self.task_width, self.task_height), pygame.NOFRAME) else: self.pygame_screen = pygame.display.set_mode( (self.task_width, self.task_height)) background = pygame.Surface(self.pygame_screen.get_size()) background = background.convert() # Run each task # Return and save their output to dataframe/excel for task in selected_tasks: if task == "Attention Network Test (ANT)": # Set number of blocks for ANT ant_task = ant.ANT(self.pygame_screen, background, blocks=3) # Run ANT ant_data = ant_task.run() # Save ANT data to excel ant_data.to_excel(writer, 'ANT', index=False) elif task == "Mental Rotation Task": mrt_task = mrt.MRT(self.pygame_screen, background) # Run MRT mrt_data = mrt_task.run() # Save MRT data to excel mrt_data.to_excel(writer, 'MRT', index=False) elif task == "Sustained Attention to Response Task (SART)": sart_task = sart.SART(self.pygame_screen, background) # Run SART sart_data = sart_task.run() # Save SART data to excel sart_data.to_excel(writer, 'SART', index=False) elif task == "Digit Span (backwards)": digitspan_backwards_task = \ digitspan_backwards.DigitspanBackwards( self.pygame_screen, background) # Run Digit span (Backwards) digitspan_backwards_data = \ digitspan_backwards_task.run() # Save digit span (backwards) data to excel digitspan_backwards_data.to_excel( writer, 'Digit span (backwards)', index=False) elif task == "Raven's Progressive Matrices": ravens_task = ravens.Ravens( self.pygame_screen, background, start=9, numTrials=12) # Run Raven's Matrices ravens_data = ravens_task.run() # Save ravens data to excel ravens_data.to_excel(writer, 'Ravens Matrices', index=False) elif task == "Sternberg Task": sternberg_task = sternberg.Sternberg( self.pygame_screen, background) # Run Sternberg Task sternberg_data = sternberg_task.run() # Save sternberg data to excel sternberg_data.to_excel(writer, 'Sternberg', index=False) # Save excel file writer.save() # End of experiment screen pygame.display.set_caption("Cognitive Battery") pygame.mouse.set_visible(1) background.fill((255, 255, 255)) self.pygame_screen.blit(background, (0, 0)) font = pygame.font.SysFont("arial", 30) display.text(self.pygame_screen, font, "End of Experiment", "center", "center") pygame.display.flip() display.wait_for_space() # Quit pygame pygame.quit() print "--- Experiment complete" self.close()
def run(self): # Instructions screen self.screen.blit(self.background, (0, 0)) display.text(self.screen, self.font, "Sternberg Task", "center", 100) display.text( self.screen, self.font, "You will see a sequence of numbers, one at a time. " "Try your best to memorize them", 100, 200) display.text(self.screen, self.stim_font, "8 - 5 - 4 - 1 - 0 - 9", "center", 300) display.text(self.screen, self.font, "You will then be shown a single test number in blue", 100, 400) display.text(self.screen, self.stim_font, "0", "center", 500, (0, 0, 255)) display.text( self.screen, self.font, "If this number was in the original sequence, " "press the LEFT arrow", 100, 600) display.text( self.screen, self.font, "If this number was NOT in the original sequence, " "press the RIGHT arrow", 100, 700) display.text( self.screen, self.font, "Try to do this as quickly, " "and as accurately, as possible", 100, 800) display.text_space(self.screen, self.font, "center", 900) pygame.display.flip() display.wait_for_space() # Practice ready screen self.screen.blit(self.background, (0, 0)) display.text(self.screen, self.font, "We will begin with some practice trials...", "center", "center") display.text_space(self.screen, self.font, "center", self.screen_y / 2 + 100) pygame.display.flip() display.wait_for_space() # Practice trials for i, r in self.practice_trials.iterrows(): self.display_trial(self.practice_trials, i, r, "practice") # Main trials ready screen self.screen.blit(self.background, (0, 0)) display.text(self.screen, self.font, "End of practice trials.", 100, 100) display.text(self.screen, self.font, "You may move on to the main " "trials when you're ready", 100, 300) display.text( self.screen, self.font, "Remember to respond as quickly " "and as accurately as possible", 100, 500) display.text(self.screen, self.font, "Your reaction time and accuracy" " will be recorded", 100, 600) display.text_space(self.screen, self.font, "center", 800) pygame.display.flip() display.wait_for_space() # Main trials for i, block in enumerate(self.blocks): for j, r in block.iterrows(): self.display_trial(block, j, r, "main") # If this is not the final block, show instructions for next block if i != len(self.blocks) - 1: display.text(self.screen, self.font, "End of block.", 100, 200) display.text( self.screen, self.font, "Take a short break, and press space when you're " "ready to start the next block...", 100, 400) display.text_space(self.screen, self.font, "center", 700) pygame.display.flip() display.wait_for_space() # 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() # Concatenate blocks and add trial numbers all_data = pd.concat(self.blocks) all_data['trialNum'] = list(range(1, len(all_data) + 1)) print("- Sternberg Task complete") return all_data
def run(self): # Instructions self.screen.blit(self.background, (0, 0)) display.text(self.screen, self.font, "Attentional Network Test", "center", self.screen_y/2 - 300) display.text(self.screen, self.font, "Keep your eyes on the fixation cross at the " "start of each trial:", 100, self.screen_y/2 - 200) display.image(self.screen, self.img_fixation, "center", self.screen_y/2 - 150) display.text(self.screen, self.font, "A set of arrows will appear somewhere on the screen:", 100, self.screen_y/2 - 100) display.image(self.screen, self.img_left_incongruent, "center", self.screen_y/2 - 50) display.text(self.screen, self.font, "Use the Left / Right arrow keys to indicate " "the direction of the CENTER arrow.", 100, self.screen_y/2 + 50) display.text(self.screen, self.font, "In example above, you should press the Left arrow.", 100, self.screen_y/2 + 100) display.text_space(self.screen, self.font, "center", (self.screen_y/2) + 300) pygame.display.flip() display.wait_for_space() # Instructions Practice self.screen.blit(self.background, (0, 0)) display.text(self.screen, self.font, "We'll begin with a some practice trials...", "center", "center") display.text_space(self.screen, self.font, "center", self.screen_y/2 + 100) pygame.display.flip() display.wait_for_space() # Practice trials self.run_block(0, 1, "practice") # Instructions Practice End self.screen.blit(self.background, (0, 0)) display.text(self.screen, self.font, "We will now begin the main trials...", 100, self.screen_y/2 - 50) display.text(self.screen, self.font, "You will not receive feedback after each trial.", 100, self.screen_y/2 + 50) display.text_space(self.screen, self.font, "center", self.screen_y/2 + 200) pygame.display.flip() display.wait_for_space() # Main task for i in range(self.NUM_BLOCKS): self.run_block(i, self.NUM_BLOCKS, "main") # Create trial number column self.all_data["trial"] = range(1, len(self.all_data) + 1) # Rearrange the dataframe columns = ['trial', 'block', 'congruency', 'cue', 'location', 'fixationTime', 'ITI', 'direction', 'response', 'correct', 'RT'] self.all_data = self.all_data[columns] # 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 "- ANT 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 run(self): # Instructions self.screen.blit(self.background, (0, 0)) display.text(self.screen, self.font, "Attentional Network Test", "center", self.screen_y / 2 - 300) display.text( self.screen, self.font, "Keep your eyes on the fixation cross at the " "start of each trial:", 100, self.screen_y / 2 - 200) display.image(self.screen, self.img_fixation, "center", self.screen_y / 2 - 150) display.text(self.screen, self.font, "A set of arrows will appear somewhere on the screen:", 100, self.screen_y / 2 - 100) display.image(self.screen, self.img_left_incongruent, "center", self.screen_y / 2 - 50) display.text( self.screen, self.font, "Use the Left / Right arrow keys to indicate " "the direction of the CENTER arrow.", 100, self.screen_y / 2 + 50) display.text(self.screen, self.font, "In example above, you should press the Left arrow.", 100, self.screen_y / 2 + 100) display.text_space(self.screen, self.font, "center", (self.screen_y / 2) + 300) pygame.display.flip() display.wait_for_space() # Instructions Practice self.screen.blit(self.background, (0, 0)) display.text(self.screen, self.font, "We'll begin with some practice trials...", "center", "center") display.text_space(self.screen, self.font, "center", self.screen_y / 2 + 100) pygame.display.flip() display.wait_for_space() # Practice trials self.run_block(0, 1, "practice") # Instructions Practice End self.screen.blit(self.background, (0, 0)) display.text(self.screen, self.font, "We will now begin the main trials...", 100, self.screen_y / 2 - 50) display.text(self.screen, self.font, "You will not receive feedback after each trial.", 100, self.screen_y / 2 + 50) display.text_space(self.screen, self.font, "center", self.screen_y / 2 + 200) pygame.display.flip() display.wait_for_space() # Main task for i in range(self.NUM_BLOCKS): self.run_block(i, self.NUM_BLOCKS, "main") # Create trial number column self.all_data["trial"] = list(range(1, len(self.all_data) + 1)) # Rearrange the dataframe columns = [ 'trial', 'block', 'congruency', 'cue', 'location', 'fixationTime', 'ITI', 'direction', 'response', 'correct', 'RT' ] self.all_data = self.all_data[columns] # 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("- ANT complete") return self.all_data
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)