Feedback for Two Response Options

Hello All,

I’m trying to create a feedback message that will present for two response types. Participants can press either a left or right trigger for a correct response to stim1 or press nothing for a correct response to stim2. For practice trials, I am trying to present a message either “correct” or “incorrect” for each of these responses. While, I’ve had success presenting feedback for one response style, I’m having difficulty presenting feedback for either of these response options. Any suggestions on how to write this code?

Thank you!
Danielle

Any suggestions would require knowing more about your task, how it is conducted, what things are called, what your current code looks like, and how it doesn’t work in the way you want.

Think “what would a person need to know if they were to give me the answer to this problem, given only what I tell them in my message?”.

Hey Mike,
Apologies for not providing the necessary information! We are coding this task on a Dell 32 bit computer using psychopy version 1.82.01.

I am attempting to create a variation of the “Go/No-go” task with response feedback, in which participants are to respond (by pressing either the left or right trigger on a game controller) when they see certain stimuli (i.e., “2” and “3”) and withhold responses when another appears (i.e., “1”). A trial will contain a fixation cross “+” for 900 ms., then one of the three stimuli for 250 ms., and then a blank screen for 450 ms. After the blank screen, I would like the participant to receive a feedback message “correct” or “incorrect” for the response that they made. The presented stimuli will be random and is located in a conditions file. A basic break down of the stimuli + response = message loop is below.
-Stimuli “1” + no trigger response = “correct” message
-Stimuli “1” + trigger response = “incorrect” message
-Stimuli “2” or “3” + no trigger response = “incorrect” message
-Stimuli “2” or “3” + trigger response = “correct” message

I have been able to present feedback using only one of the triggers in the past; however, I am having difficulty with coding for the use of the option of left and right trigger response. Essentially our feedback seems to be coming in at random instead of lining up with our above expectations.

The coding the experiment is below:
-Within the stimuli presentation routine, the response code is:
Begin Experiment-

response_ttl = parallel.ParallelPort(address='0x0378')

Begin Routine-

response_event=None
trial_start=0
io.clearEvents()

Each Frame-

if frameN == 0:
    io.clearEvents('all')
    trial_start=core.getTime()
gp_triggers = gamepad.getTriggers()
trig_time = gp_triggers['time']
left_val, right_val = gp_triggers['left_trigger'], gp_triggers['right_trigger']
if frameN >= 12 and frameN <= 48:
    if left_val > 0.2 or right_val > 0.2:
        if left_val > 0.2:
            response = 'left_trigger'
        if right_val > 0.2:
            response = 'right_trigger'
        if response == 'left_trigger' or response == 'right_trigger':
            response_ttl.setData(16)
            if response_ttl.status == STARTED and frameN >= (response_ttl.frameNStart + 4):
                response_ttl.setData(0)
    else:
        response = 'None'

End routine-

 response_ttl.setData(0)

-Within the feedback presentation routine, the code is:

Begin Routine-

if response == 'None' and Stim == 1:
    msg="Correct!"
elif response == 'left_trigger' or 'right_trigger' and Stim == 2 or 3:
    msg="Correct!"
else:
    msg="Oops! That was wrong."

End routine-

io.clearEvents('all')

The conditions file looks like:

Jitter  Stim  Stim_Signal  corrAns       msg
42	    1	  2            None          Incorrect!
48	    2	  4 	       left_trigger	 Correct!
54	    3	  8 	       left_trigger	 Incorrect!
60	    1	  2 	       None	         Correct!
66	    2	  4 	       left_trigger  Incorrect!
42	    3	  8            left_trigger	 Correct!
48	    1	  2 	       None	         Incorrect!
54	    2	  4 	       left_trigger	 Correct!
60	    3	  8 	       left_trigger	 Incorrect!
66	    1	  2            None	         Correct!
42	    2	  4 	       left_trigger  Incorrect!
48	    3	  8 	       left_trigger	 Correct!
54	    1	  2 	       None	         Incorrect!
60	    2	  4 	       left_trigger	 Correct!
66	    3	  8 	       left_trigger	 Incorrect!

Let me know if any other information is needed. Your help is very much appreciated.

Best,
Danielle

Hi Danielle

That is now an excellent level of detail.

My guess is that this is because of the construction of your if/then checks. Note how you did it earlier (correctly):

if response == 'left_trigger' or response == 'right_trigger':

Boolean logic produces either a 0 (False) or a 1 (True) for the entire expression. In this case, each sub-test (the expressions either side of the ‘or’) produces a 1 or a 0, and the overall expression (the result of the ‘or’ operation) produces a 1 if either or both of them is True, and a 0 if neither is True.

Compare that to this:

elif response == 'left_trigger' or 'right_trigger' and Stim == 2 or 3:

I’m not entirely sure how Python will evaluate this, but it almost certainly won’t fit with what you intend. You need to explicitly include brackets to influence the order of evaluation and be careful about what you are oring.

e.g. Stim == 2 or 3 needs to explicitly be

Stim == 2 or Stim ==3

Otherwise you are checking whether Stim is equal to the result of the expression 2 or 3 (in Python, 2 or 3 is itself a mathematical operation, which evaluates to the single result 2). So I’m guessing you want your test to be something like this:

elif (response == 'left_trigger' or response == 'right_trigger') and (Stim == 2 or Stim == 3):

If response is ‘left_trigger’ and Stimuli is 2, then the underlying Boolean logic evaluates like this:

(1 or 0) and (1 or 0):  # one thing is True in each set of brackets.
1 and 1                 # as each 'or' evaluated to True,
1                       # the whole 'and' expression evaluates to True

Boolean logic takes a bit of getting used to. It can be worthwhile to insert some print() statements under each condition while debugging this stuff, to make sure that the logic does what you expect.

Hello Again Michael,

Thank you again for the always thorough help! I think I understand what you are saying here, and I have tried to implement it into my experiment using a few different variations of what you have suggested. However, the feedback is still appearing at random, and our first trial of the loop presents a “doh” message.
Just as confirmation, this is our new feedback code:

In begin experiment:

msg='doh!'#if this comes up we forgot to update the msg!

And in begin routine:

if response == 'None' and Stim == 1:
    msg="Correct!"
elif (response == 'left_trigger' or response == 'right_trigger') and (Stim == 2 or Stim == 3):
        msg="Correct!"
else:
        msg="Oops! That was wrong."

I have an idea of where my problem is though I’m not entirely confident in my determination, and obviously I have yet to figure out how to fix it.

Is it possible that my having responses recorded in one routine and having the code for feedback in a separate routine is a problem?

Thank you again,
Danielle

Ahh, OK, having the default value for the message of D'oh! is useful for debugging this.

It indicates that on that first trial, the variable response likely had none of the values you were testing for ('left_trigger', 'right_trigger', or 'None'). (I’m guessing it must must get an initial value defined somewhere too though, or else we would get an undefined variable error?)

In your code, you should (temporarily) insert some print(response) lines at various points in your code so you can see how and if that variable changes. I would guess that you would want to reset it to some default (or ‘None’) value on frame 0, to stop it potentially carrying over the value from a previous trial.

I don’t know how your game pad works, but is it possible that after a left or right response is detected, on the next or subsequent frames, the response variable might get reset to 'None’ if no key is pressed?

Is the ttl triggering working as expected?

Lastly, it can be worthwhile choosing another value rather than 'None' (such as 'no_response'. It is all too easy to get that mixed up with the Python object None (with no quotes).