Reset randomization of list

OS : Windows 10
PsychoPy version: 3.1.5
Standard Standalone? (y/n) :
What are you trying to achieve?:
I have a CSV file with 14 letters to be presented in trials of different sizes from 2-10. It’s currently set on random, not fullrandom, so there are no repeats. However, if trials are presented in a particular order for example a 6 letter trial, then a 4 letter trial, then a 6 letter trial it runs out of letters in the 3rd trial and then risks repeating letters within the 3rd list. So I need it to reset randomization between each trial. Right now I have an ITI that is only presented right before the next trial, so if I can get a piece of code at the beginning of that routine that resets the randomization of the letters it should work great!



image

Code from codeITI object

# only present intertrial interval immediately before the 
# beginning of the next trial:
if choicetrials.thisN != show_prompt_trial - 1:
    continueRoutine = False

Thank you!

If i read it right, you have a different letter on each row of the file? That’s not really how Builder expects to work with conditions files: it is structured around all the information for a given trial being together in the same row of the file.

I suspect in this case that you actually want the selection of letters to be done in code, rather than drawn from a conditions file, but to give advice on how to implement that, we would need a very precise description of the design and procedure, particularly, the randomisation and its constraints.

Hi Michael, you helped me set up my experiment this way because each repeat of the loop is not one trial, and I needed different set sizes.

Here is my original post that you helped me with. I need to be able to randomize length of study lists

So, I have 14 letters and I want them presented in set sizes of 2, 4, 6, 8, and 10. 6 trials of each size so I would end with 30 trials. We accomplished this with this coding.

As you can see in my previous screenshots and the one above psychopy is randomly generating lists or trials of 2, 4, 6, 8, or 10 letters from the conditions file of 14 letters for a memory task, after all of the letters in that trial are presented participants are asked to report all of the letters they remember. At the beginning of each trial they are told how many letters they will need to remember. The Report Word and ITI routine only run if it is the last repeat of the loop before the next trial. Within each trial, there can’t be repeated letters, which I am having occasionally right now when a new repetition of the conditions file begins in the middle of a trial.

Please let me know if this doesn’t make any sense and you need way more information!

Thank you!!

Please forgive me for contradicting myself!

So as I understand it, there are 30 trials in an experiment design sense, but Builder will run the routine 180 times. What I didn’t understand correctly from that previous thread is that the conditions file only has 14 rows, not 180.

So to achieve this, I think you need two loops, one nested within the other. The outer loop is set to have an nReps of 30, and not be connected to a conditions file. i.e. This loop will run once per trial.

The inner loop is the one you have already, that is connected to the conditions file, and should have an nReps of 1, and will run once for each letter presented.

The thing that was missing before is that this inner loop needs to terminate when the selected number of letters (2, 4, 6, 8, or 10) is reached on this trial. I guess at the moment it will keep going, meaning that you will run out of letters. Instead, as you say, you want to reset things, by terminating this loop and starting afresh for the next trial (i.e. the next iteration of the outer loop).

So take the existing code you have in the routine at the end of the inner loop and change it to look like this:

# only ask for a report on the iteration immediately before the 
# beginning of the next trial:
if your_loop_name.thisN != show_prompt_trial - 1:
    continueRoutine = False

# new code to end the inner loop so the next trial can run
# with afresh set of letters to select from:
if your_loop_name.thisN + 1 == current_length:
    your_loop_name.thisN.finished = True

Hi Michael

Thanks for your response, I believe I implemented everything correctly. But I get this error when I try to run.

image
image

Sorry, there was a typo in my code above (now corrected), which should have used == instead of =, i.e.

if your_loop_name.thisN + 1 == current_length:

Hi Michael,

Implementing the outer loop changed something else that you helped me to set up.


Above you can see I have this listlength routine at the beginning of the loop. In this routine, it shuffles the list lengths, and creates the variable show_prompt_trial (shown below).

It is supposed to run at the beginning of every trial and tell the participant how many items they will have to remember.
However, since adding the second loop it only comes up on the first trial.

I am fairly certain this if-else statement needs updating but I just can’t wrap my head around how to fix it.

# check if this is the beginning of a trial, where
# you need to show the prompt:
if choicetrials.thisN == show_prompt_trial:
   current_length = list_lengths.pop()
   lengthnumber.text = str(f'{current_length}')

   # update for the next time it will be shown:
   show_prompt_trial = show_prompt_trial + current_length 
else:
   continueRoutine = False # skip this routine on most iterations

This is the component that shows the number of items that will need to be remembered.

Thank you

Edit: I would also like to add that I will most likely have to add a third loop. I want 2 blocks of 30 trials counterbalanced with just different instructions for both blocks. This would affect the count of show_prompt_trial I think.

I might have lost a bit of my sense for what is going on, but now there is an outer loop running once per trial, I guess the check for whether to show the prompt is now simpler: all you need to do is check if the trial number of the inner loop is zero (i.e. you don’t need to keep track of the show_prompt_trial variable any more):

# check if this is the beginning of a trial, where
# you need to show the prompt:
if choicetrials.thisN == 0:
   current_length = list_lengths.pop()
else:
   continueRoutine = False # skip this routine on subsequent iterations

and put

$str(current_length)

in the relevant text field, set to update every repeat. Make sure the code component is above the text field, so the latter gets the current value.