Memory task: word pairs and perseverative errors in final test

OS (e.g. Win10): Windows 10
PsychoPy version: 1.90.1
What are you trying to achieve?: I’m trying to create a memory experiment in which participants in the first phase have to study word pairs, then in the second phase they are given the first word pair (cue) and asked to type the other pair (target), later in the third phase, they are given again the cue word and asked to type the target word. So what I am trying to achieve is to compare the typed response for the target in the second phase, and the typed response for the target in the third phase, so I can see in the output data if there are perseverative errors (errors in the first test that are repeated in the final test).

What did you try to make it work?:
I’ve tried adding a code component in the third phase routine like this:

Begin experiment:

inputText_test2 = ""
correct_test2 = ""
err_pers = ""

Begin Routine:

theseKeys=""
shift_flag = False
phase3_input.alignHoriz ='left'

Each frame:

#code for response text input
n= len(theseKeys)
i = 0
while i < n:

    if theseKeys[i] == 'space':
        # pressing SPACE means time to stop
        continueRoutine = False
        break

    elif theseKeys[i] == 'backspace':
        inputText_test2 = inputText_test2[:-1]  # lose the final character
        i = i + 1

    elif theseKeys[i] in ['lshift', 'rshift']:
        shift_flag = True
        i = i + 1

    else:
        if len(theseKeys[i]) == 1:
            # we only have 1 char so should be a normal key, 
            # otherwise it might be 'ctrl' or similar so ignore it
            if shift_flag:
                inputText_test2 += chr( ord(theseKeys[i]) - ord(' '))
                shift_flag = False
            else:
                inputText_test2 += theseKeys[i]

        i = i + 1

#check if the response in final test is correct
if inputText_test2 == Target:
    correct_test2 = "1"
else :
    correct_test2 = "0"

#check if the error made in the final test is the same as the first test
while correct_test2 = "0":
    if inputText_test1 == inputText_test2:
        err_pers = "1"
    else:
        err_pers = "0"

End routine:

# store the response input for final test
thisExp.addData('inputText_test2', inputText_test2)
inputText_test2=""

#store the counting of correct responses 
thisExp.addData('correct_test2', correct_test2)
correct_test2=""

# store perseverative errors
thisExp.addData('err_pers', err_pers)
err_pers=""

What specifically went wrong when you tried that?:
It doesn’t make the comparison correctly, in the output data for the perseverative errors row (err_pers) it always appears “0” no matter what.

I’m new to Psychopy and I’m still learning Python, so I’m sure there is plenty of mistakes im making.

I would really really appreciate your help, I’ve searched everywhere but I haven’t found any solutions. I’m adding an example of the data output so you can see how it appears now, and also a screenshot of the flow, please let me know if there is something I can do. I’m desperate and have no one I can ask to.

Thanks a lot!

Yeray.

111_EXP3_2019_Mar_25_1756.csv (4.4 KB)

1 Like

I think the problem is with your while loop setting a variable, rather than checking for equality. Try changing the while loop (while correct_test2 = "0":) to the following:

if correct_test2 == "0":  # Is correct_test2 zero?
    err_pers = int(inputText_test1 == inputText_test2)   # True == 1 and False == 0.
1 Like

Thanks a lot for your help, David. I have changed the while loop as you said, but the result in the “err_pers” row keeps being 0. Is there anything else I can do?

I really appreciate your help,

Thanks in advance,

Yeray

222_EXP3_2019_Mar_26_1634.csv (4.3 KB)

Right, I think it would be good to get some debug print statements so we can see if the conditions are satisfied. So. what is the output of:

if correct_test2 == "0": 
    err_pers = int(inputText_test1 == inputText_test2)
    # If we do not get a print out, then correct_test2 is never "0"
    print(err_pers, inputText_test1, inputText_test2)
1 Like

This is the output I get

1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
0  m
0  m
0  m
0  m
0  m
0  m
0  m
0  m
0  m
0  m
0  m
0  m
0  m
0  m
0  m
0  m
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
0  p
0  p
0  p
0  pe
0  pe
0  pe
0  per
0  per
0  per
0  per
0  per
0  per
0  per
0  per
0  pera
0  pera
0  pera
0  pera
0  pera
0  pera
0  pera
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
0  m
0  m
0  m
0  ma
0  ma
0  ma
0  ma
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
1  
0  f
0  f
0  f
0  f
0  f
0  f
0  f
0  f
0  f
0  fr
0  fr
0  fr
0  fr
0  fre
0  fre
0  fre
0  fre
0  fre
0  fre
0  fre
0  fre
0  fre
0  fres
0  fres
0  fres
0  fres
0  fres
0  fres
0  fres
0  fres
0  fresa
0  fresa
0  fresa
0  fresa
0  fresa
0  fresa
0  fresa
0  fresa
0  fresa
0  fresa
0  fresa
0  fresa
0  fresa
0  fresa
0  fresa
0  fresa

The problem there is that inputText_test1 appears to be empty and does not hold the previously typed words from phase 2. So, err_pers will always be zero, because typed text in inputText_test2 will never be the same as an empty inputText_test1. It may be a good idea to store all the typed words from the second phase in a list, and check whether any of the typed words in phase 3 are in the list.

See how this goes. Create a new list at the beginning of the experiment, fill that list with the typed words at the end of every trial in the second phase, and check the typed words in phase 3 for membership within the new list:

Phase 2

# Begin Experiment
phase2Words = []

# End Routine - second phase
phase2Words.append(inputText_test1)

Phase 3

if correct_test2 == "0":  # Is correct_test2 zero?
    err_pers = int(inputText_test2 in phase2Words)
1 Like

So I’ve tried what you said, but it is still not working, also I’ve printed the output for “phase2.words”, so I can check the stored words in the created list, and this is the output I get:

# End Routine - second phase
phase2Words.append(inputText_test1)
print (phase2Words)

Output:

['']
['', '']
['', '', '']

I hope it helps. Thanks again for your help and time.

So that looks like inputText_test1 is not holding any typed text, unless it is being overwrittten. Would you mind sharing the code from the second phase?

Here you have David, is this what you need?

Thanks again,

    # ------Prepare to start Routine "phase2_test1"-------
    t = 0
    phase2_test1Clock.reset()  # clock
    frameN = -1
    continueRoutine = True
    # update component parameters for each repeat
    phase2_cue.setText(Cue)
    phase2_key_resp = event.BuilderKeyResponse()
    theseKeys=""
    shift_flag = False
    phase2_input.alignHoriz ='left'
    
    
    # keep track of which components have finished
    phase2_test1Components = [phase2_cue, phase2_input, phase2_key_resp]
    for thisComponent in phase2_test1Components:
        if hasattr(thisComponent, 'status'):
            thisComponent.status = NOT_STARTED
    
    # -------Start Routine "phase2_test1"-------
    while continueRoutine:
        # get current time
        t = phase2_test1Clock.getTime()
        frameN = frameN + 1  # number of completed frames (so 0 is the first frame)
        # update/draw components on each frame
        
        # *phase2_cue* updates
        if t >= 0.0 and phase2_cue.status == NOT_STARTED:
            # keep track of start time/frame for later
            phase2_cue.tStart = t
            phase2_cue.frameNStart = frameN  # exact frame index
            phase2_cue.setAutoDraw(True)
        
        # *phase2_input* updates
        if t >= 0.0 and phase2_input.status == NOT_STARTED:
            # keep track of start time/frame for later
            phase2_input.tStart = t
            phase2_input.frameNStart = frameN  # exact frame index
            phase2_input.setAutoDraw(True)
        if phase2_input.status == STARTED:  # only update if drawing
            phase2_input.setText(inputText_test1, log=False)
        
        # *phase2_key_resp* updates
        if t >= 0.0 and phase2_key_resp.status == NOT_STARTED:
            # keep track of start time/frame for later
            phase2_key_resp.tStart = t
            phase2_key_resp.frameNStart = frameN  # exact frame index
            phase2_key_resp.status = STARTED
            # keyboard checking is just starting
            win.callOnFlip(phase2_key_resp.clock.reset)  # t=0 on next screen flip
            event.clearEvents(eventType='keyboard')
        if phase2_key_resp.status == STARTED:
            theseKeys = event.getKeys()
            
            # check for quit:
            if "escape" in theseKeys:
                endExpNow = True
            if len(theseKeys) > 0:  # at least one key was pressed
                phase2_key_resp.keys.extend(theseKeys)  # storing all keys
                phase2_key_resp.rt.append(phase2_key_resp.clock.getTime())
        n= len(theseKeys)
        i = 0
        while i < n:
        
            if theseKeys[i] == 'space':
                # pressing SPACE means time to stop
                continueRoutine = False
                break
        
            elif theseKeys[i] == 'backspace':
                inputText_test1 = inputText_test1[:-1]  # lose the final character
                i = i + 1
        
            elif theseKeys[i] in ['lshift', 'rshift']:
                shift_flag = True
                i = i + 1
        
            else:
                if len(theseKeys[i]) == 1:
                    # we only have 1 char so should be a normal key, 
                    # otherwise it might be 'ctrl' or similar so ignore it
                    if shift_flag:
                        inputText_test1 += chr( ord(theseKeys[i]) - ord(' '))
                        shift_flag = False
                    else:
                        inputText_test1 += theseKeys[i]
                i = i + 1
        
        if inputText_test1 == Target:
            correct_test1 = "1"
        else :
            correct_test1 = "0"
        
        
        
        
        # 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 phase2_test1Components:
            if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
                continueRoutine = True
                break  # at least one component has not yet finished
        
        # check for quit (the Esc key)
        if endExpNow or event.getKeys(keyList=["escape"]):
            core.quit()
        
        # refresh the screen
        if continueRoutine:  # don't flip if this routine is over or we'll get a blank screen
            win.flip()
    
    # -------Ending Routine "phase2_test1"-------
    for thisComponent in phase2_test1Components:
        if hasattr(thisComponent, "setAutoDraw"):
            thisComponent.setAutoDraw(False)
    # check responses
    if phase2_key_resp.keys in ['', [], None]:  # No response was made
        phase2_key_resp.keys=None
    phase2_trial.addData('phase2_key_resp.keys',phase2_key_resp.keys)
    if phase2_key_resp.keys != None:  # we had a response
        phase2_trial.addData('phase2_key_resp.rt', phase2_key_resp.rt)
    # store the response input for initial test
    thisExp.addData('inputText_test1', inputText_test1)
    inputText_test1=""
    
    # End Routine - second phase
    phase2Words.append(inputText_test1)
    
    
    #store the counting of correct responses 
    thisExp.addData('correct_test1', correct_test1)
    correct_test1=""
    
    
    # the Routine "phase2_test1" was not non-slip safe, so reset the non-slip timer
    routineTimer.reset()
    

@Yeray_Mera, looks like you are clearing the variable just before you add it to the list. Instead, try clearing the variable at the beginning of each routine. The problem code is highlighted below with comments:

# store the response input for initial test
    thisExp.addData('inputText_test1', inputText_test1)
    ###################################################
    ##Delete this line and move to begin routine tab##
    inputText_test1=""
    ###################################################
    
    # End Routine - second phase
    phase2Words.append(inputText_test1)
1 Like

It’s working!!! You are amazing David!! Thank you so much for your incredible help!!

Hope you have a great week :blush::smiling_face_with_three_hearts:

Yeray

1 Like

Thanks! I had the same problem, but it helped!

1 Like