Presenting the same pairs of stimuli until a same response were got twice

I have some pairs of stimuli to present. Participant will at least response to each pair twice. The rules I want to set were discribed below. When the same response was accumulated twice, the pair will not be presented, if not the pair will continue to be presented in the next iteration until same responses were got twice. In other words, response this iteration is compared with the response to the same pair of stimuli last iteration, if same responses were got twice, the pair will not be presented next iteration, if not, the pair will keep presented until we attain the same answer in two consecutive iterations.
I was trying to realize my goal by firstly, storing the response(mouse.clicked_image) as a variable in thisTrial, and then comparing it with the response in the next iteration, if the response were same(MOUSE==mouse.clicked_name), I will code the pair by adding another variable called ‘correct’ = 2 in thisTrial, if the response is not the same, I update the variable ‘Mouse’ as the response in the current iteration, and code the variable called ‘correct’ = 1. Finally, at the beginning of each routine, I add on condition to skip certain routines.
My codes have reported no errors, however didn’t work. When I tried to check the datafile. I found that MOUSE becomes a list but not a string. And the iteration can only run twice. I can’t fix it, can anybody help ? :grinning: :grinning:

# I set nReps to 5, I think it's not necessarily be 5? can be even larger?
trials = data.TrialHandler(nReps=5.0, method='random',
    extraInfo=expInfo, originPath=-1,
    trialList=data.importConditions('free_force.csv'),
    seed=None, name='trials')
    
thisExp.addLoop(trials)  # add the loop to the experiment
    # -------Run Routine "trial"-------
    if trials.thisRepN == 0:
        continueRoutine = True
    if trials.thisRepN >= 0:
        if thisTrial['correct'] == 1:
            continueRoutine = True
        if thisTrial['correct'] == 2:
            continueRoutine = False

    while continueRoutine:
        # get current time
        t = trialClock.getTime()
        tThisFlip = win.getFutureFlipTime(clock=trialClock)
        tThisFlipGlobal = win.getFutureFlipTime(clock=None)
        frameN = frameN + 1  # number of completed frames (so 0 is the first frame)
        # update/draw components on each frame
        
        # *IMG_2* updates
        if IMG_2.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
            # keep track of start time/frame for later
            IMG_2.frameNStart = frameN  # exact frame index
            IMG_2.tStart = t  # local t and not account for scr refresh
            IMG_2.tStartRefresh = tThisFlipGlobal  # on global time
            win.timeOnFlip(IMG_2, 'tStartRefresh')  # time at next scr refresh
            IMG_2.setAutoDraw(True)
        
        # *IMG_1* updates
        if IMG_1.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
            # keep track of start time/frame for later
            IMG_1.frameNStart = frameN  # exact frame index
            IMG_1.tStart = t  # local t and not account for scr refresh
            IMG_1.tStartRefresh = tThisFlipGlobal  # on global time
            win.timeOnFlip(IMG_1, 'tStartRefresh')  # time at next scr refresh
            IMG_1.setAutoDraw(True)
            
        # *mouse* updates (I should store info of clicked)
        if mouse.status == NOT_STARTED and t >= 0.0-frameTolerance:
            # keep track of start time/frame for later
            mouse.frameNStart = frameN  # exact frame index
            mouse.tStart = t  # local t and not account for scr refresh
            mouse.tStartRefresh = tThisFlipGlobal  # on global time
            win.timeOnFlip(mouse, 'tStartRefresh')  # time at next scr refresh
            mouse.status = STARTED
            mouse.mouseClock.reset()
            prevButtonState = mouse.getPressed()  # if button is down already this ISN'T a new click
        if mouse.status == STARTED:  # only update if started and not finished!
            buttons = mouse.getPressed()
            if buttons != prevButtonState:  # button state changed?
                prevButtonState = buttons
                if sum(buttons) > 0:  # state changed to a new click
                    # check if the mouse was inside our 'clickable' objects
                    gotValidClick = False
                    if typee == 'free':
                        clickableList = [IMG_1, IMG_2]
                    if typee == 'forc':
                        if contains(str(IMG_1.image), 'D') == True:
                            clickableList = [IMG_1]
                        if contains(str(IMG_2.image), 'D') == True:
                            clickableList = [IMG_2]
                    try:
                        iter(clickableList)
                        clickableList = clickableList
                    except:
                        clickableList = [clickableList]
                    for obj in clickableList:
                        if obj.contains(mouse):
                            gotValidClick = True
                            mouse.clicked_image.append(obj.image)
                    if gotValidClick:  # abort routine on response
                        continueRoutine = False
        
        # check for quit (typically the Esc key)
        if endExpNow or defaultKeyboard.getKeys(keyList=["escape"]):
            core.quit()
        
        # check if all components have finished
        if not continueRoutine:  # a component has requested a forced-end of Routine
            break
        continueRoutine = False  # will revert to True if at least one component still running
        for thisComponent in trialComponents:
            if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
                continueRoutine = True
                break  # at least one component has not yet finished
        
        # refresh the screen
        if continueRoutine:  # don't flip if this routine is over or we'll get a blank screen
            win.flip()
    # -------Ending Routine "trial"------- meanings of trials and trialComponents
    for thisComponent in trialComponents:
        if hasattr(thisComponent, "setAutoDraw"):
            thisComponent.setAutoDraw(False)
    trials.addData('IMG_2.started', IMG_2.tStartRefresh)
    trials.addData('IMG_2.stopped', IMG_2.tStopRefresh)
    trials.addData('IMG_1.started', IMG_1.tStartRefresh)
    trials.addData('IMG_1.stopped', IMG_1.tStopRefresh)
    # store data for trials (TrialHandler)
    x, y = mouse.getPos()
    buttons = mouse.getPressed()
    if sum(buttons):
        # check if the mouse was inside our 'clickable' objects
        gotValidClick = False
        try:
            iter([IMG_1,IMG_2])
            clickableList = [IMG_1,IMG_2]
        except:
            clickableList = [[IMG_1,IMG_2]]
        for obj in clickableList:
            if obj.contains(mouse):
                gotValidClick = True
                mouse.clicked_image.append(obj.image)
    trials.addData('mouse.x', x)
    trials.addData('mouse.y', y)
    trials.addData('mouse.leftButton', buttons[0])
    trials.addData('mouse.midButton', buttons[1])
    trials.addData('mouse.rightButton', buttons[2])
    if len(mouse.clicked_image):
        trials.addData('mouse.clicked_image', mouse.clicked_image[0])
    trials.addData('mouse.started', mouse.tStart)
    trials.addData('mouse.stopped', mouse.tStop)
    # the Routine "trial" was not non-slip safe, so reset the non-slip timer
    IMG_11.append(IMG_1.image)
    IMG_22.append(IMG_2.image)
    Typee_1.append(typee)
    Mouse.append(mouse.clicked_image)
    if trials.thisRepN == 0 :
         thisTrial['MOUSE'] = mouse.clicked_image
    if trials.thisRepN >= 1 :
         if mouse.clicked_image != thisTrial['MOUSE']:
            thisTrial['MOUSE'] = mouse.clicked_image
            thisTrial['correct'] = 1
         if mouse.clicked_image == thisTrial['MOUSE']:
            thisTrial['correct'] = 2
    #There are some other methods that might fail for the same reason
    #if mouse.clicked_image == MOUSE :
        #1:may be I can also delete thisTrial ?
    #if mouse.clicked_image != MOUSE:
        #1: thisTrial['MOUSE'] = mouse.clicked_image
        #3: somebody has mentioned another method to created index to rows
        # when I import the first conditionk, and to add some rows to the incorrect list
    routineTimer.reset()
    thisExp.nextEntry()

This is what happened in my datafile:

It seemed that I had solved this problem. My friend suggested the idea of a frequency counter. And he helped me check the syntax errors of the usages of “if” and “elif”. I think I can share my codes in case anybody needs helps in the future.
In summary, I inserted some codes at the begin routine part together with some at the ending routine part.

    if trials.thisRepN == 0:
        continueRoutine = True
    elif trials.thisRepN > 0:
        if thisTrial['SIMG1'] == 3 or thisTrial['SIMG2'] == 3:
            continueRoutine = False
        else:
            continueRoutine = True

    while continueRoutine:
...

if len(mouse.clicked_image):
    trials.addData('mouse.clicked_image', mouse.clicked_image[0])
trials.addData('mouse.started', mouse.tStart)
trials.addData('mouse.stopped', mouse.tStop)
if trials.thisRepN == 0:
    if mouse.clicked_image[0] == IMG_1.image:
        # this sentence was not executed
        thisTrial['SIMG1'] = 1
        thisTrial['SIMG2'] = 0
    elif mouse.clicked_image[0] == IMG_2.image:
        thisTrial['SIMG1'] = 0
        thisTrial['SIMG2'] = 1
elif trials.thisRepN > 0:
    if mouse.clicked_image[0] == IMG_1.image and thisTrial['SIMG1'] !=3 and thisTrial['SIMG2'] !=3:
        i = thisTrial['SIMG1']
        i += 1
        thisTrial['SIMG1'] = i
        thisTrial['SIMG2'] = 0            
    elif mouse.clicked_image[0] == IMG_2.image and thisTrial['SIMG1'] !=3 and thisTrial['SIMG2'] !=3:
        i = thisTrial['SIMG2']
        i += 1
        thisTrial['SIMG2'] = i
        thisTrial['SIMG1'] = 0