Designing a Maze task
I'm trying to design a maze task that requires two separate text displays of sequences of words. Essentially, a participant needs to decide if the word to complete the sentence is on the left or right. So a participant would be presented with "The", "man", "wants", "pizza." with competitor sequences "###", "to", "schoolbus", "in". Participants would first see [ "###" The ] and choose 'The' as the first word and then move on to [ man to ]...
I've found code that would allow me to present a single word like in self-paced reading, but I don't know how to get OpenSesame to go through a sequence for two sentences and then to do this for say 30 trials. I'm sure that I'll encounter difficulties with some of the details, but mainly I'm concerned with how to layout a table or csv for the block/trial_loop.
The way that I would have done this would have been to present all the words in a column with another column to say which trial they are a part of and yet another column to display the sequence they should be in, but from other answers on the forum it seems like putting the sentence into its own row would be better (and then making two columns for 'sentence_words' and 'competitors', but I can't get this to happen simultaneously.
Any help about the best/most logical way to set this up would be appreciated. Apologies if I've missed relevant answers on the forum.
Forster, K. I. (2010). Using a maze task to track lexical and sentence processing. The Mental Lexicon, 5(3), 347–357. https://doi.org/10.1075/ml.5.3.05for
 
				 
							 
							
Comments
Hi,
Nested loops (one for the trials, the second one for the word in the sentence) and every word in a separate column. See the attached experiment.
Hope this helps,
Eduard
Hi Eduard,
Thanks for the suggestion - I've moved forward with that basic design.
I've been using SigmundAI to help design the experiment - It's pretty limited and really likes stick with solutions that don't work, but it's good for providing code that I can manipulate. (My Python, OpenSesame, and general programming skills are pretty limited).
The problem with having all the stimuli in separate columns for each row is that by default the standard 'subject-0.csv' results file only gives me data (response time, whether correct, etc) for the final word in the sentence, but I need the data for each one. Sigmund's solution was to use datamatrix to create an additional results file (which will eventually need to be named dynamically). But this would only give me the results for all the word in the last trial. I suggested to Sigmund to store the trial results in one datamatrix and then add it to another data matrix called 'all_results' and then save 'all_results.csv' The code that Sigmund produced seems like it should do this, but it doesn't work and I'm really stumped as to why - I really don't understand how all_results is getting copied over.
import random import os from datamatrix import DataMatrix, io print("Run Phase Started") # Ensure that primary_words and alt_words are lists primary_words = eval(var.primary_words) if isinstance(var.primary_words, str) else var.primary_words alt_words = eval(var.alt_words) if isinstance(var.alt_words, str) else var.alt_words # Debugging: Check the types and content of the word lists print(f"Primary words type: {type(primary_words)}, content: {primary_words}") print(f"Alternative words type: {type(alt_words)}, content: {alt_words}") # Debugging: Check the writable path print("Writable path:", writable_path) # Verify the directory and path permissions directory = os.path.dirname(writable_path) print(f"Current working directory: {os.getcwd()}") if not os.path.exists(directory): print(f"Directory does not exist: {directory}") elif not os.access(directory, os.W_OK): print(f"Directory is not writable: {directory}") else: print(f"Directory is writable: {directory}") # Create a Canvas object my_canvas = Canvas() # Variable to track consecutive incorrect answers consecutive_incorrect = 0 # Initialize DataMatrix for logging results for each trial num_trials = len(primary_words) # Initialize DataMatrix for accumulating all results all_results = DataMatrix() # Loop through the primary words and display them for i in range(num_trials): # If two consecutive incorrect answers occur, end the session. if consecutive_incorrect >= 2: print("Ending the trial due to two consecutive incorrect answers.") break x_position_p = random.choice([-200, 200]) # Random position for primary word x_position_a = -x_position_p # Opposite position for alternative word y_position = 0 # Always centered on y-axis # Log the actual word for debugging current_word = primary_words[i] print(f"Displaying word: '{current_word}'") # Clear the canvas and then display the words my_canvas.clear() my_canvas.text(primary_words[i], x=x_position_p, y=y_position, color='white', font_size=30) # Display primary word my_canvas.text(alt_words[i], x=x_position_a, y=y_position, color='white', font_size=30) # Display alternative word t0 = my_canvas.show() # Show the canvas # Initialize a Keyboard object and capture input my_keyboard = Keyboard(keylist=['left', 'right']) key, t1 = my_keyboard.get_key() reaction_time = t1 - t0 var.response = key var.response_time = reaction_time # Determine if the response is correct based on the primary word correct = (key == 'left' and x_position_p == -200) or (key == 'right' and x_position_p == 200) # Log key responses, reaction times, and correctness for debugging print(f"Pressed key: {key}, Reaction time: {reaction_time}, Word: {current_word}, Correct: {correct}") # Increment or reset the consecutive incorrect counter if correct: consecutive_incorrect = 0 # Reset counter on correct response else: consecutive_incorrect += 1 # Increment counter on incorrect response # Create DataMatrix for the current trial trial_result = DataMatrix(length=1) trial_result["response"] = [key] trial_result["response_time"] = [reaction_time] trial_result["word"] = [current_word] trial_result["correct"] = [correct] # Debugging: Print the trial result to ensure it's correct print(f"Trial result:\n{trial_result}") # Append current trial results to all_results if len(all_results) == 0: all_results = trial_result else: all_results = all_results << trial_result # Debugging: Print the all_results after each append print(f"All results after trial {i+1}:\n{all_results}") print("Run Phase Completed") # Remove any rows that were not used due to early termination all_results = all_results[:len(all_results) - consecutive_incorrect] # Debugging: Print the final all_results before saving print(f"Final results:\n{all_results}") # Save the results to CSV print("Results type", type(all_results)) print(all_results) for colname, col in all_results.columns: print(f"Column: {colname}, Type: {type(col).__name__}, Data: {col}") print(f"Type of results immediately before saving: {type(all_results)}") # Save results only if directory is writable if os.path.exists(directory) and os.access(directory, os.W_OK): io.writetxt(all_results, writable_path) print("Results saved to:", writable_path) else: print("Could not save results due to unwritable directory") print("Script execution complete.")The issue is in the prepare phase, but if it helps I'll add the prepare phase and the stimuli csv.
# Prepare phase script to fetch primary and alternative words from loop table and store them primary_words = [] alt_words = [] for i in range(1, 10): primary_var = f'primary_word{i}' # Variable name e.g., primary_word1 alt_var = f'alt_word{i}' # Variable name e.g., alt_word1 # Fetch the values using experiment variables defined in loop primary = var.get(primary_var, "").strip() alt = var.get(alt_var, "").strip() # Add the words to the lists if they are not empty if primary: primary_words.append(primary) if alt: alt_words.append(alt) # Combine words without shuffling to maintain a specific order combined_words = primary_words + alt_words # Store combined words and types as experiment variables var.combined_words = combined_words # Define a writable path (use absolute path) writable_path = '/pathy/mcpath/face/all_prep_results.csv' # Change this to your actual path # Debugging: Print to verify whole words and types print(f"Primary words ({len(primary_words)}):", primary_words) print("Alternative words:", alt_words) print("Combined words:", combined_words) print("Primary words:", type(primary_words)) # Should output: <class 'list'> print("Combined words:", type(primary_words)) # Should output: <class 'list'>I've also attached, in order, the csv of the stim for this minimum working example, the log file, and the 'all_results'. And my experiment. Hopefully, you (or someone) can see the issue from the run phase above.
Any help is greatly appreciated.
Best,
Actually, revisiting your original advice, I realize that Sigmund got me to move away from the original recommendation of nested loops with one for the trials, the second one for the word in the sentence. If I can get that back it might (should) solve my problem. I'll try to get that working, but any advice would still be appreciated.
Best,
Your problem sounds to me, as if you simply need to move the logger one layer inside the nested loops. New lines to the data file are only added, if a logger is passed. If it is not included inside a loop but only after it, it will only log the variables from the last iteration.
is this the issue?
Eduard