Analyzing the correct and incorrect responses from a .CSV File

If this template helps then use it. If not then just delete and start from scratch.

OS (e.g. Win10): Win 10
PsychoPy version (e.g. 1.84.x): PsychoPy3
Standard Standalone? (y/n): y
**What are you trying to achieve?: I am trying to analyze the number of incorrect and correct responses and the reaction times from the .CSV output.

**What specifically went wrong when you tried that?: The experiment asks participants to click a button on our response box whenever they see the designated letter on the screen. They are not required to click the button otherwise. In the PsychoPy manual, it states that correct answers are coded as “1” in the “key_resp_2.corr” column. However, what is odd that when they were required to respond, it is showing that they responded correctly “key_resp_2keys” =“1”, yet it is saying in the “key_Resp_2.corr” column that they got the answer incorrect “0” and also providing a reaction time.

As you can see in the first photo, in row 8 column f “corrAns” the correct response should be “1”, yet it is showing it as incorrect in the spreadsheet.

image

  • Please show us a screenshot of your keyboard component.
  • Did you insert any custom code at all?
1 Like

@Michael Thanks for the response! I do have some custom code to communicate with the USB-TTL8

Here is a picture of the keyboard component:

Here is the code:
Begin experiment: import serial

# Open usb2ttl8 serial port.
# Make sure the port address is correct for the usb2ttl8 device.
usb2ttl8_serial = serial.Serial(port=‘COM3’, timeout=0.2)

# Set usb2ttl8 to ttl write mode
usb2ttl8_serial.write(b"SET DATA_MODE WRITE\n")
usb2ttl8_serial.write(b"WRITE 0\n")

usb2ttl8_serial.write(b"READ\n")
r = usb2ttl8_serial.readline()

Practice Routine
Begin routine: usb2ttl8_serial.write(b’WRITE 2\n’)
End routine: usb2ttl8_serial.write(b’WRITE 0\n’)

Trial
Begin routine: if set_ttl_val >= 0:
usb2ttl8_serial.write(b’WRITE %d\n’%(set_ttl_val))*
End routine: usb2ttl8_serial.write(b’WRITE 0\n’)
End experiment: usb2ttl8_serial.close()

OK, the custom code doesn’t look to be involved.

What happens if you allow another key e.g. '1', '2' and on some trials, push the 2 key?

Also, can you push the “compile script” button, search through it for the term corrAns, and then paste here the all the code from the relevant routine that is about checking the keyboard response?

@Michael

What happens if you allow another key e.g. '1', '2' and on some trials, push the 2 key?

Another lab is currently using our equipment, but I will check this once they are done.

Is there a way that I can analyze the results easily from the subjects that I have collected data on?

Also, can you push the “compile script” button, search through it for the term corrAns , and then paste here the all the code from the relevant routine that is about checking the keyboard response?

Here are the sections of code that have the term corrAns:

-------Start Routine “trial”-------

while continueRoutine:
    # get current time
    t = trialClock.getTime()
    frameN = frameN + 1  # number of completed frames (so 0 is the first frame)
    # update/draw components on each frame
    
    # *text* updates
    if t >= delay and text.status == NOT_STARTED:
        # keep track of start time/frame for later
        text.tStart = t  # not accounting for scr refresh
        text.frameNStart = frameN  # exact frame index
        win.timeOnFlip(text, 'tStartRefresh')  # time at next scr refresh
        text.setAutoDraw(True)
    frameRemains = delay + display- win.monitorFramePeriod * 0.75  # most of one frame period left
    if text.status == STARTED and t >= frameRemains:
        # keep track of stop time/frame for later
        text.tStop = t  # not accounting for scr refresh
        text.frameNStop = frameN  # exact frame index
        win.timeOnFlip(text, 'tStopRefresh')  # time at next scr refresh
        text.setAutoDraw(False)
    
    # *key_resp_2* updates
    if t >= delay and key_resp_2.status == NOT_STARTED:
        # keep track of start time/frame for later
        key_resp_2.tStart = t  # not accounting for scr refresh
        key_resp_2.frameNStart = frameN  # exact frame index
        win.timeOnFlip(key_resp_2, 'tStartRefresh')  # time at next scr refresh
        key_resp_2.status = STARTED
        # keyboard checking is just starting
        win.callOnFlip(key_resp_2.clock.reset)  # t=0 on next screen flip
    frameRemains = delay + display- win.monitorFramePeriod * 0.75  # most of one frame period left
    if key_resp_2.status == STARTED and t >= frameRemains:
        # keep track of stop time/frame for later
        key_resp_2.tStop = t  # not accounting for scr refresh
        key_resp_2.frameNStop = frameN  # exact frame index
        win.timeOnFlip(key_resp_2, 'tStopRefresh')  # time at next scr refresh
        key_resp_2.status = FINISHED
    if key_resp_2.status == STARTED:
        theseKeys = key_resp_2.getKeys(keyList=['1'], waitRelease=False)
        if len(theseKeys):
            theseKeys = theseKeys[0]  # at least one key was pressed
            
            # check for quit:
            if "escape" == theseKeys:
                endExpNow = True
            if key_resp_2.keys == []:  # then this was the first keypress
                key_resp_2.keys = theseKeys.name  # just the first key pressed
                key_resp_2.rt = theseKeys.rt
                # was this 'correct'?
                if (key_resp_2.keys == str(corrAns)) or (key_resp_2.keys == corrAns):
                    key_resp_2.corr = 1
                else:
                    key_resp_2.corr = 0

-------Ending Routine “trial”-------

for thisComponent in trialComponents:
    if hasattr(thisComponent, "setAutoDraw"):
        thisComponent.setAutoDraw(False)
trials.addData('text.started', text.tStartRefresh)
trials.addData('text.stopped', text.tStopRefresh)
# check responses
if key_resp_2.keys in ['', [], None]:  # No response was made
    key_resp_2.keys = None
    # was no response the correct answer?!
    if str(corrAns).lower() == 'none':
       key_resp_2.corr = 1;  # correct non-response
    else:
       key_resp_2.corr = 0;  # failed to respond (incorrectly)
# store data for trials (TrialHandler)
trials.addData('key_resp_2.keys',key_resp_2.keys)
trials.addData('key_resp_2.corr', key_resp_2.corr)
if key_resp_2.keys != None:  # we had a response
    trials.addData('key_resp_2.rt', key_resp_2.rt)
trials.addData('key_resp_2.started', key_resp_2.tStartRefresh)
trials.addData('key_resp_2.stopped', key_resp_2.tStopRefresh)
usb2ttl8_serial.write(b'WRITE 0\n')
# the Routine "trial" was not non-slip safe, so reset the non-slip timer
routineTimer.reset()
thisExp.nextEntry()

@Michael

What happens if you allow another key e.g. '1', '2' and on some trials, push the 2 key?

I attached an image of the output

So you’ve already collected data, without checking that it was working? I guess there isn’t much point in trying to address the situation in the experiment then.

If the data file is correctly recording both the response and the correct answer, then you just need to calculate your own correct/incorrect column to replace what currently seems to be not working properly. If you are still collecting data, you certainly don’t want to change things in the experiment, as otherwise you’ll end up with incompatible data across subjects.

@Michael

Not exactly… We were collecting data without the TTL8 and everything was working properly, the only thing that was changed was the incorporation of the TTL8, and that’s when I noticed that this issue was occurring. I wouldn’t have thought that incorporating the TTL8 would change the way the test is scored. We collect physiologic data in a program called LabChart which was programmed to insert comments at specified time points to link up with the stage of the test. The TTL8 simply communicates with LabChart to tell it when to insert a comment for a given stage.

I would like to fix this issue so that I do not have to calculate the correct and incorrect responses by hand when we use this test in future protocols.