Increasing Difficulty; Monetary Incentive Delay task

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

OS
PsychoPy version 2022.1.3
midEEG.psyexp (56.6 KB)
sidEEG.psyexp (58.1 KB)

I have created a monetary incentive delay task and a social variant of the classic incentive paradigm. In each trial the participant must respond (click on the white square) in enough time to be able to win (see a rewarding image), or else they lose (see a punishing image). I have attached the experiemental files here.

They are designed to be used for ERP analysis later on hence the need for a substantial number of trials.

The current issue is that the task is too easy and participant will just click continuously when the fixation cross appears until the white square appears subsequently. I’m looking for advice on how I could make this task harder?

Currently there is a staircase structure to the trials loop so that the response duration is adjusted each time depending on how they performed on the previous trial. However this doesn’t seem to be working as intended as particiapnt simply click continuously when the fixation cross appears.

I have considered adding a more substantial jitter to the presentation of the fixation cross, and adding in an additional delay of a blank screen between the fixation cross disappearing and white square appearing to reduce pre-emptive clicking? Any thoughts much appreciated.

Hello Seline,

Since your target is always a white square and all your presentation times and durations are fixed, it only makes sense from the participant’s point of view to click as soon as possible.

How difficult do you want this task to be?

One way to make it more difficult is to introduce some catch trials in which no white square is shown and to “punish” participants for responding in catch trials.

Another way is to jitter the onset of the target, which would be good for the EEG measurement anyway, and “punish” early responses. So introduce a gap between the fixation cross and the target.

You could also define a reaction time window, don’t respond faster than x ms and don’t respond slower than y ms, but this might introduce EEG components you are not interested in.

The task will always be simple. It is a simple reaction task which usually produces very few errors.

By the way, all your loops are set to random, not staircase.

Best wishes Jens

Hi Jens,

Thank you for all the very useful suggestions, your second of jittering the onset of the target is along the lines of what I was also thinking of - so to increase the delay between the fixation cross and target, but importantly jitter this period of time more obviously to reduce the predictability of the stimulus.

Though I understand your point about the task, it is intended to be easy, however I think my structure as it stands is not allowing (or allowing for very few) loss trials to be recorded.

And the staircase structure is set within a code component that adjusts for each new trial based on the participant performance saved from the last routine (or trial).

Many thanks,
Seline

Hello seline,

the code-line

randOnset = random() *(1.5 - 0.5) + 0.5

defines the variable randOnset and sets it to a float with a maximum of 1.5 seconds and minimum of 0.5 seconds. Use $randOnset for the onset of the target.

Not in midEEG.psyexp. Currently onsets of components and durations are fixed. Or I have I missed it.

Best wishes Jens

Hi Jens,

I’ll add this in, re-run the task and let you know how I get on hopefully it will make it less likely for the participant to just start immediately clicking.

So for the target routine the mouse component duration is set to variable $target_stim and in the code component named ‘target_code’ the following code is included in the

##########Begin Experiment######

#define initial response duration
resp_duration = 0.2

#########Each Frame#########

if t < 0.2: 
    if mouse.isPressedIn(target_stim):
        correct = 1
        continueRoutine = False
else: 
    correct = 0 
    continueRoutine = False

#########End Routine###########

if correct == 1:
    resp_duration -= 0.01
else:
    resp_duration += 0.01

#saving custon data to csv output
thisExp.addData("resp_duration", resp_duration)

This code should be working to adjust the period of time the participants can respond for?

Is my problem that I need to add in a variable to the duration of the image component for this to work?

Hello seline

yes, you need to insert the variable resp_duration in the parameter field duration of the image component, $resp_duration.

Best wishes Jens

Hi Jens,

Thank you, just to check for the code line you recommended above would that go into the Before Routine tab?

Many thanks,

Seline

I have inserted $randOnset into the Start space within the image component that is presenting the target…

And after having inserted the code above in ‘Begin Experiment’ or ‘Begin Routine’ I now no longer see the white square at all during each trial?

Hello Seline

here is an example.

Jitter.psyexp (10.7 KB)

Best wishes Jens

Hi Jens,

Really appreciate your help on this but I am experiencing the problem I had earlier - I included the components you provided and inserted them in my routine (as seen below).

Here is the updated version of the task
midEEG.psyexp (62.5 KB)
MID Task - BP EEG.zip (1.1 MB)

However, now the white square doesn’t appear at all nor is the jitter working. Whenever I try to adjust the start time of target_stim (the image component) or target_mouse (the mouse component) linked with it either the white square doesn’t appear or the delayed start time is ignored - do you know why this might be?

I am aiming to try and make it so that participant’s will be receive a loss as feedback for making a click before the white square appears (in addition to clicking too late as its set up now) but due to the above problems I can’t see how to do that within the same routine currently.

Any help is much appreciated.

Hello Seline,

I can’t run your experiment because I don’t have the stimuli and condition files you use. So you might want to create a toy version of your experiment.

I have added the text components jitter and jitter_cross in my toy-experiment just to show you the principle. You do not need to add these to your experiment. Try the following

Take a look at the following trial-definition:

  1. copy the definition of random onset, delete the jitter-code component, the jitter-text component and the jitter-fixation cross component.

  1. paste the definition of random onset to your code-component target_code in the Begin routine tab. There is no need to have multiple code-components here. Delete the now empty jitter code-component

  1. add randOnset to the Onset-parameter of your stimulus (BTW, you know that you can create a white square via the polygon-component?)

  1. do the same for the response device target_mouse

Do you now see your target-stimulus?

Don’t you want the mouse-click to end the routine? Currently it is set that the mouse-click never ends the routine.

Best wishes Jens

Hi Jens,

Thank for the suggestions, I’ve attached a zip folder of my experimental folder which should allow you to run as it will contain everything you need. I’ve created a reduced version so I can just focus on getting this work within a set of trials for now.

MID Task.zip (1.1 MB)

Unfortunately still no white square (also this is an image rather than a polygon as I am trying to keep all stimuli as images to try and standardise any trigger delays with stimulus presentation), I added the changes in you outlined as you’ll see in the zip folder.

I think I may be due to a line of code in the every frame tab in my code component (see below), I think t refers to time since the start of the routine so maybe that is intefering with the other start times? This is set up currently to monitor whether the mouse pressed during the target presentation but I suppose this is redundant now. However I don’t know currently how to add code for a start time for each of the target_stim and target_mouse components in the Coder.

#check correct response
if t < 0.2: 
    if target_mouse.isPressedIn(target_stim):
        correct = 1
        continueRoutine = False
else: 
    correct = 0 
    continueRoutine = False

Many thanks.

Seline

Hello Seline,

your check

#check correct response
if target_mouse.isPressedIn(target_stim):
        correct = 1
        continueRoutine = False
else: 
    correct = 0 
    continueRoutine = False

prevents the white square to be shown. Delete it or at least delete the line .

continueRoutine = False

So,

will start the presentation of target_stim at randOnset for a duration of resp_duration. Specify Start time and duration for the mouse-component in the same way.

Best wishes Jens

Hi Jens,

I’m making headway, can’t thank you enough for your help with this. So now a white square is appearing and I have included the randOnset and resp_duration into the components sucessfully.

Now I am trying to add my final step of ending the routine when a mouse click is made before the white square appears, I’ve attached an updated version of the task.

midEEG.psyexp (55.2 KB)

Whilst I can get the routine to end if the mouse click happens early (i.e. pre the target/white square) it isn’t registering as a loss when the feedback is shown. Here is the code below -

#check correct response
if pre_target_mouse.getPressed(getTime=False):
    correct = 0   
else: 
    correct = 1

if target_mouse.isPressedIn(target_stim):
    correct = 1
else: 
    correct = 0

Do I have incorrect code here to check for a mouse click? This process works when checking for mouse clicks int he second liens of code so Im not sure what the issue is

Many thanks,

Seline

I’ve tried a different strategy that has allowed me to get a little further but still doesn’t resolve the issue.

midEEG.psyexp (57.3 KB)

I’ve added in a larger transparent rectangle that displays before the white square appears. I’ve set it up in the code component that if this is clicked then this registers as too early.

Begin Routine

#define correst response variable and early response variable
correct = 0
tooearly = 0

Each Frame

#check correct response
if target_mouse.isPressedIn(target_stim):
    correct = 1
else: 
    correct = 0
    
if pre_target_mouse.isPressedIn(pre_target):
    tooearly = 1
else: 
    tooearly = 0

End Routine

if correct == 1 and tooearly == 0:
    resp_duration -= 0.01
else:
    resp_duration += 0.01

#saving custon data to csv output
thisExp.addData("resp_duration", resp_duration)

I’ve then also included it as an additional condition for the feedback code component for determining which feedback is displayed, please see below.

#show different feedback depending on trial type
#set trigger values based on trial type
if trial_type == "incentive":
    if correct == 1 and tooearly == 0:
        image_feedback = "win.jpg"
        this_earnings = 0.2
        feedback_trigger = 4
    else:
        image_feedback = "loss.png"
        this_earnings = -0.2
        feedback_trigger = 5

else:
    image_feedback = "neutral.png"
    this_earnings = 0
    feedback_trigger = 6

However all I now see is loss feedback, even after I have definitely clicked the white square AND have not clicked early, is this statement set up incorrectly or am I thinking about it the wrong way?

Many thanks,
Seline

Hello Seline,

Are you sure you clicked fast enough? 200 ms is extremely short, even for a simple RT-task. Your routine ends after randOnset + resp_duration (plus transparent rectangle), regardless of when you responded. One way to check if timing is an issue here is to increase your RT-window and see if you still get only losses. Another way to check the if-else construction is to include some print statements. Simply print the values of correct and tooearly to the console in your feedback-routine.

print("too early: ", tooearly)
print("correct: ", correct)

It could be that you are never correct.

Best wishes Jens

Hi Jens,

I substantially increased the duration of each of the variables above and the same thing occurs. It seems that I’m always getting feedback that is always a win or always a loss - is there another way of coding to present loss feedback to an early mouse click than the method I have taken?

Many thanks,

Seline

Hello Seline,

I don’t understand you here. It can only be either a win or either a loss, can’t it?

Currently you are coding two possibilities for the trial type incentive:

  1. correct and not too early
  2. incorrect or too early

Incorrect or too early get the same feedback. There is neural-feedback for all other trial types. When I understand you correctly, you want three types of feedback

  1. too early
  2. correct and not too early
  3. incorrect

Simply instruct the computer to do so :wink:

if trial_type == "incentive":
    if correct == 1 and tooearly == 0:
        image_feedback = "win.jpg"
        this_earnings = 0.2
        feedback_trigger = 4
    elif correct == 1 and tooearly == 1:
        image_feedback = "tooearly.jpg"
        this_earnings = -0.2    # whatever your earnings would be 
        feedback_trigger = 5    #whatever trigger your need here.
    elif correct == 0:         #you might need to define this condition in a more restrictive manner
        image_feedback = "loss.png"
        this_earnings = -0.2
        feedback_trigger = 5
else:
    image_feedback = "neutral.png"
    this_earnings = 0
    feedback_trigger = 6

It is really helpful to print the variables your are testing to the console. :stuck_out_tongue_winking_eye:

Best wishes Jens

Hi Jens,

So, getting closer. Yes you’ve understood the conditions I essentially end up with under the Incentive trial types. Adding in the elif statements you recommended I can no achieve 2 out of 3 of those things.

Specifically, if no click is made (i.e. they don’t click early but don’t click the white square in time) then you get a loss, and if you click early (but haven’t clicked the white square) you get a loss.

The problem is if you don’t click early and have clicked the white square it is still coming up as a loss, when the first if statement should mean this is now a win, which leads me to think I am always getting a loss.

I have included more print statements but due to low memory I can’t monitor the Runner whilst the task is running, the statements also don’t appear quickly enough for me to compare (again due to computer constraints on memory).

I’ll keep playing around with the elif statements, my only guess is that all the conditions aren’t being fully captured?

Many thanks,

Seline