Millisecond Forums

Disregard response triggers that have less than 50s RT or 2500 ms RT

https://forums.millisecond.com/Topic34507.aspx

By smo - 7/3/2022

Hi,

Our team is hoping to add some EEG triggers to an Inquisit task (Behavioral Pattern Separation Task - Object Version - Set C - English). All stimulus and response triggers work, but we have an issue when the response time (RT) of one trial was too long that the response trigger of that trial was counted as a response trigger of the following trial. We found this issue because we saw some trials had a RT of less than or equal to 50 ms, which is not a propobale RT people could have. We also saw one trial with two response triggers, one of which is probably from the previous trial. Therefore, we wanted to disregard those trials that have a 50 ms response trigger, which is a response trigger of the previous trial but is counted as a response trigger of the following trial.

Another issue we have are with those trials that have a 2500 ms response trigger and have a 2500 ms RT in the behavioural data (2500 ms indicates the end of trial, so we want to disregard those too). The behavioural data generated by Inquisit 6 worked well as it counted trials that had a 2500 ms RT as no response, but the bdf file (i.e. the EEG data file) will show one trigger only, which is a combination of a response trigger from the previous trial and a stimulus trigger for the next trial.

We wonder:
1. Is there a 50 ms buffer we can add to our code that can prevent any response that is <50 ms to send out a reposne trigger?
2. Is there a way to disregard a 2500 ms response trigger and make sure there is always a stimulus trigger sent out when there is an overalp between stimulus and response trigger?

The following is our trigger code.

Stimulus trigger
//20 for Targetsignal
<port targetsignal>
/ port = LPT1
/ subport = data
/ items = ("00010100")
</port>

//30 for luresignal
<port luresignal>
/ port = LPT1
/ subport = data
/ items = ("00011110")
</port>

//40 for foilsignal
<port foilsignal>
/ port = LPT1
/ subport = data
/ items = ("00101000")
</port>


Response Trigger
// 55
<port oldsignal>
/ port = LPT1
/ subport = data
/ items = ("00110111")
</port>

//66 for similar trials
<port similarsignal>
/ port = LPT1
/ subport = data
/ items = ("01000010")
</port>

//77 for new trials
<port newsignal>
/ port = LPT1
/ subport = data
/ items = ("01001101")
</port>[code]Stimulus trigger
//20 for Targetsignal
<port targetsignal>
/ port = LPT1
/ subport = data
/ items = ("00010100")
</port>

//30 for luresignal
<port luresignal>
/ port = LPT1
/ subport = data
/ items = ("00011110")
</port>

//40 for foilsignal
<port foilsignal>
/ port = LPT1
/ subport = data
/ items = ("00101000")
</port>


Response Trigger
// 55
<port oldsignal>
/ port = LPT1
/ subport = data
/ items = ("00110111")
</port>

//66 for similar trials
<port similarsignal>
/ port = LPT1
/ subport = data
/ items = ("01000010")
</port>

//77 for new trials
<port newsignal>
/ port = LPT1
/ subport = data
/ items = ("01001101")
</port>

<trial target>
/ontrialbegin = [
    values.stimulusselect = list.targets.nextvalue;
    trial.target.insertstimulusframe(picture.target, 1);
    trial.target.insertstimulustime(clearscreen, parameters.stimulusduration);
    trial.target.insertstimulustime(port.targetsignal, 50)
]

/stimulusframes = [1 = responsekeys_part2, targetsignal]
/validresponse = (values.responsekey_old, values.responsekey_similar, values.responsekey_new)
/ correctresponse = (values.responsekey_old)
/ responsemessage = (values.responsekey_old, oldsignal, 0)
/ responsemessage = (values.responsekey_similar, similarsignal, 0)
/ responsemessage = (values.responsekey_new, newsignal, 0)

/beginresponseframe = 1
/responseinterrupt = frames

/ontrialend = [
    trial.target.resetstimulusframes();
    if (trial.target.responsetext == values.responsekey_old) {
        values.responseCategory = "old";    
    } else if (trial.target.responsetext == values.responsekey_new) {
        values.responseCategory = "new";    
    } else if (trial.target.responsetext == values.responsekey_similar) {
        values.responseCategory = "similar";    
    } else if (trial.target.response == 0) {
        values.responseCategory = "";
        values.count_noresponses += 1;
    };

    values.stimulus = picture.target.currentitem;
    
    values.count_targets += 1;
    if (trial.target.response != 0) {
        values.count_targets_corr += 1;
        if (trial.target.correct) {
            values.count_oldtargets += 1;
        } else if (trial.target.responsetext == values.responsekey_similar) {
            values.count_simtargets += 1;    
        } else if (trial.target.responsetext == values.responsekey_new) {
            values.count_newtargets += 1        
        };    
    };

]
/trialduration = (parameters.stimulusduration + parameters.ISI)
/recorddata = true
/branch = [return trial.part2;]
</trial>

Note:
* presents a foil for parameters.stimulusduration
* collects response during that time
* updates summary variables
* calls trial.part2
<trial foil>
/ontrialbegin = [
    values.stimulusselect = list.foils.nextvalue;
    trial.foil.insertstimulusframe(picture.foil, 1);             
    trial.foil.insertstimulustime(clearscreen, parameters.stimulusduration);
    trial.target.insertstimulustime(port.foilsignal, 50)
]

/stimulusframes = [1 = responsekeys_part2, foilsignal]
/validresponse = (values.responsekey_old, values.responsekey_similar, values.responsekey_new)
/ correctresponse = (values.responsekey_new)
/ responsemessage = (values.responsekey_old, oldsignal, 0)
/ responsemessage = (values.responsekey_similar, similarsignal, 0)
/ responsemessage = (values.responsekey_new, newsignal, 0)
/beginresponseframe = 1
/responseinterrupt = frames
/ontrialend = [
    trial.foil.resetstimulusframes();
    
    if (trial.foil.responsetext == values.responsekey_old) {
        values.responseCategory = "old";        
    } else if (trial.foil.responsetext == values.responsekey_new) {
        values.responseCategory = "new";    
    } else if (trial.foil.responsetext == values.responsekey_similar) {
        values.responseCategory = "similar";    
    } else if (trial.foil.response == 0) {
        values.responseCategory = "";
        values.count_noresponses += 1;
    };
    
    values.stimulus = picture.foil.currentitem;
    
    values.count_foils += 1;
    if (trial.foil.response != 0) {
        values.count_foils_corr += 1;
        if (trial.foil.correct) {
            values.count_newfoils += 1;
        } else if (trial.foil.responsetext == values.responsekey_old) {
            values.count_oldfoils += 1            
        } else if (trial.foil.responsetext == values.responsekey_similar) {
            values.count_simfoils += 1;                
        };        
    };
]
/trialduration = (parameters.stimulusduration + parameters.ISI)
/recorddata = true
/branch = [return trial.part2;]
</trial>

Note:
* presents a lure for parameters.stimulusduration
* collects response during that time
* updates summary variables
* calls trial.part2
<trial lure>
/ontrialbegin = [
    values.stimulusselect = list.lures.nextvalue;    
    values.lurebin = item.lurebins.item(values.stimulusselect);    
    
    if (values.lurebin == 1) {
        values.L1 += 1;        
    } else if (values.lurebin == 2) {
        values.L2 += 1;        
    } else if (values.lurebin == 3) {
        values.L3 += 1;        
    } else if (values.lurebin == 4) {
        values.L4 += 1;        
    } else if (values.lurebin == 5) {
        values.L5 += 1;        
    } else {
        values.lurebin = "NA";        
    };

    trial.lure.insertstimulusframe(picture.lure, 1);        
    trial.lure.insertstimulustime(clearscreen, parameters.stimulusduration);
    trial.target.insertstimulustime(port.luresignal, 50)
]

/stimulusframes = [1 = responsekeys_part2, luresignal]
/validresponse = (values.responsekey_old, values.responsekey_similar, values.responsekey_new)
/beginresponseframe = 1
/ correctresponse = (values.responsekey_similar)
/ responsemessage = (values.responsekey_similar, similarsignal, 0)
/ responsemessage = (values.responsekey_old, oldsignal, 0)
/ responsemessage = (values.responsekey_new, newsignal, 0)
/responseinterrupt = frames

/ontrialend = [
    trial.lure.resetstimulusframes();
    
    if (trial.lure.responsetext == values.responsekey_old) {
        values.responseCategory = "old";        
    } else if (trial.lure.responsetext == values.responsekey_new) {
        values.responseCategory = "new";        
    } if (trial.lure.responsetext == values.responsekey_similar) {
        values.responseCategory = "similar";        
    } else if (trial.lure.response == 0) {
        values.responseCategory = "";
        values.count_noresponses += 1;
    };
    
    values.stimulus = picture.lure.currentitem;
    
    values.count_lures += 1;
    if (trial.lure.response != 0) {
        values.count_lures_corr += 1;
        if (trial.lure.correct) {
            values.count_simlures += 1;
        } else if (trial.lure.responsetext == values.responsekey_old) {
            values.count_oldlures += 1;            
        } else if (trial.lure.responsetext == values.responsekey_new) {
            values.count_newlures += 1;            
        };        
    };

    if (values.lurebin == "1"){
        if (trial.lure.responsetext == values.responsekey_old){
            values.L1O +=1;
        } else if (trial.lure.responsetext == values.responsekey_similar){
            values.L1S +=1;
        } else if (trial.lure.responsetext == values.responsekey_new){
            values.L1N +=1;            
        } else if ( trial.lure.response == 0){
            values.L1_NR += 1;
        };
    } else if (values.lurebin == "2"){
        if (trial.lure.responsetext == values.responsekey_old){
            values.L2O +=1;
        } else if (trial.lure.responsetext == values.responsekey_similar){
            values.L2S +=1;
        } else if (trial.lure.responsetext == values.responsekey_new){
            values.L2N +=1;            
        } else if ( trial.lure.response == 0){
            values.L2_NR += 1;
        };
    } else if (values.lurebin == "3"){
        if (trial.lure.responsetext == values.responsekey_old){
            values.L3O +=1;
        } else if (trial.lure.responsetext == values.responsekey_similar){
            values.L3S +=1;
        } else if (trial.lure.responsetext == values.responsekey_new){
            values.L3N +=1;            
        } else if ( trial.lure.response == 0){
            values.L3_NR += 1;
        };
    } else if (values.lurebin == "4"){
        if (trial.lure.responsetext == values.responsekey_old){
            values.L4O +=1;
        } else if (trial.lure.responsetext == values.responsekey_similar){
            values.L4S +=1;
        } else if (trial.lure.responsetext == values.responsekey_new){
            values.L4N +=1;            
        } else if ( trial.lure.response == 0){
            values.L4_NR += 1;
        };
    } else if (values.lurebin == "5"){
        if (trial.lure.responsetext == values.responsekey_old){
            values.L5O +=1;
        } else if (trial.lure.responsetext == values.responsekey_similar){
            values.L5S +=1;
        } else if (trial.lure.responsetext == values.responsekey_new){
            values.L5N +=1;            
        } else if ( trial.lure.response == 0){
            values.L5_NR += 1;
        };
    };
]
/trialduration = (parameters.stimulusduration + parameters.ISI)
/recorddata = true
/branch = [return trial.part2;]
</trial>
By smo - 7/3/2022

smo - 7/4/2022
Hi,

Our team is hoping to add some EEG triggers to an Inquisit task (Behavioral Pattern Separation Task - Object Version - Set C - English). All stimulus and response triggers work, but we have an issue when the response time (RT) of one trial was too long that the response trigger of that trial was counted as a response trigger of the following trial. We found this issue because we saw some trials had a RT of less than or equal to 50 ms, which is not a propobale RT people could have. We also saw one trial with two response triggers, one of which is probably from the previous trial. Therefore, we wanted to disregard those trials that have a 50 ms response trigger, which is a response trigger of the previous trial but is counted as a response trigger of the following trial.

Another issue we have are with those trials that have a 2500 ms response trigger and have a 2500 ms RT in the behavioural data (2500 ms indicates the end of trial, so we want to disregard those too). The behavioural data generated by Inquisit 6 worked well as it counted trials that had a 2500 ms RT as no response, but the bdf file (i.e. the EEG data file) will show one trigger only, which is a combination of a response trigger from the previous trial and a stimulus trigger for the next trial.

We wonder:
1. Is there a 50 ms buffer we can add to our code that can prevent any response that is <50 ms to send out a reposne trigger?
2. Is there a way to disregard a 2500 ms response trigger and make sure there is always a stimulus trigger sent out when there is an overalp between stimulus and response trigger?

The following is our trigger code.

Stimulus trigger
//20 for Targetsignal
<port targetsignal>
/ port = LPT1
/ subport = data
/ items = ("00010100")
</port>

//30 for luresignal
<port luresignal>
/ port = LPT1
/ subport = data
/ items = ("00011110")
</port>

//40 for foilsignal
<port foilsignal>
/ port = LPT1
/ subport = data
/ items = ("00101000")
</port>


Response Trigger
// 55
<port oldsignal>
/ port = LPT1
/ subport = data
/ items = ("00110111")
</port>

//66 for similar trials
<port similarsignal>
/ port = LPT1
/ subport = data
/ items = ("01000010")
</port>

//77 for new trials
<port newsignal>
/ port = LPT1
/ subport = data
/ items = ("01001101")
</port>[code]Stimulus trigger
//20 for Targetsignal
<port targetsignal>
/ port = LPT1
/ subport = data
/ items = ("00010100")
</port>

//30 for luresignal
<port luresignal>
/ port = LPT1
/ subport = data
/ items = ("00011110")
</port>

//40 for foilsignal
<port foilsignal>
/ port = LPT1
/ subport = data
/ items = ("00101000")
</port>


Response Trigger
// 55
<port oldsignal>
/ port = LPT1
/ subport = data
/ items = ("00110111")
</port>

//66 for similar trials
<port similarsignal>
/ port = LPT1
/ subport = data
/ items = ("01000010")
</port>

//77 for new trials
<port newsignal>
/ port = LPT1
/ subport = data
/ items = ("01001101")
</port>

<trial target>
/ontrialbegin = [
    values.stimulusselect = list.targets.nextvalue;
    trial.target.insertstimulusframe(picture.target, 1);
    trial.target.insertstimulustime(clearscreen, parameters.stimulusduration);
    trial.target.insertstimulustime(port.targetsignal, 50)
]

/stimulusframes = [1 = responsekeys_part2, targetsignal]
/validresponse = (values.responsekey_old, values.responsekey_similar, values.responsekey_new)
/ correctresponse = (values.responsekey_old)
/ responsemessage = (values.responsekey_old, oldsignal, 0)
/ responsemessage = (values.responsekey_similar, similarsignal, 0)
/ responsemessage = (values.responsekey_new, newsignal, 0)

/beginresponseframe = 1
/responseinterrupt = frames

/ontrialend = [
    trial.target.resetstimulusframes();
    if (trial.target.responsetext == values.responsekey_old) {
        values.responseCategory = "old";    
    } else if (trial.target.responsetext == values.responsekey_new) {
        values.responseCategory = "new";    
    } else if (trial.target.responsetext == values.responsekey_similar) {
        values.responseCategory = "similar";    
    } else if (trial.target.response == 0) {
        values.responseCategory = "";
        values.count_noresponses += 1;
    };

    values.stimulus = picture.target.currentitem;
    
    values.count_targets += 1;
    if (trial.target.response != 0) {
        values.count_targets_corr += 1;
        if (trial.target.correct) {
            values.count_oldtargets += 1;
        } else if (trial.target.responsetext == values.responsekey_similar) {
            values.count_simtargets += 1;    
        } else if (trial.target.responsetext == values.responsekey_new) {
            values.count_newtargets += 1        
        };    
    };

]
/trialduration = (parameters.stimulusduration + parameters.ISI)
/recorddata = true
/branch = [return trial.part2;]
</trial>

Note:
* presents a foil for parameters.stimulusduration
* collects response during that time
* updates summary variables
* calls trial.part2
<trial foil>
/ontrialbegin = [
    values.stimulusselect = list.foils.nextvalue;
    trial.foil.insertstimulusframe(picture.foil, 1);             
    trial.foil.insertstimulustime(clearscreen, parameters.stimulusduration);
    trial.target.insertstimulustime(port.foilsignal, 50)
]

/stimulusframes = [1 = responsekeys_part2, foilsignal]
/validresponse = (values.responsekey_old, values.responsekey_similar, values.responsekey_new)
/ correctresponse = (values.responsekey_new)
/ responsemessage = (values.responsekey_old, oldsignal, 0)
/ responsemessage = (values.responsekey_similar, similarsignal, 0)
/ responsemessage = (values.responsekey_new, newsignal, 0)
/beginresponseframe = 1
/responseinterrupt = frames
/ontrialend = [
    trial.foil.resetstimulusframes();
    
    if (trial.foil.responsetext == values.responsekey_old) {
        values.responseCategory = "old";        
    } else if (trial.foil.responsetext == values.responsekey_new) {
        values.responseCategory = "new";    
    } else if (trial.foil.responsetext == values.responsekey_similar) {
        values.responseCategory = "similar";    
    } else if (trial.foil.response == 0) {
        values.responseCategory = "";
        values.count_noresponses += 1;
    };
    
    values.stimulus = picture.foil.currentitem;
    
    values.count_foils += 1;
    if (trial.foil.response != 0) {
        values.count_foils_corr += 1;
        if (trial.foil.correct) {
            values.count_newfoils += 1;
        } else if (trial.foil.responsetext == values.responsekey_old) {
            values.count_oldfoils += 1            
        } else if (trial.foil.responsetext == values.responsekey_similar) {
            values.count_simfoils += 1;                
        };        
    };
]
/trialduration = (parameters.stimulusduration + parameters.ISI)
/recorddata = true
/branch = [return trial.part2;]
</trial>

Note:
* presents a lure for parameters.stimulusduration
* collects response during that time
* updates summary variables
* calls trial.part2
<trial lure>
/ontrialbegin = [
    values.stimulusselect = list.lures.nextvalue;    
    values.lurebin = item.lurebins.item(values.stimulusselect);    
    
    if (values.lurebin == 1) {
        values.L1 += 1;        
    } else if (values.lurebin == 2) {
        values.L2 += 1;        
    } else if (values.lurebin == 3) {
        values.L3 += 1;        
    } else if (values.lurebin == 4) {
        values.L4 += 1;        
    } else if (values.lurebin == 5) {
        values.L5 += 1;        
    } else {
        values.lurebin = "NA";        
    };

    trial.lure.insertstimulusframe(picture.lure, 1);        
    trial.lure.insertstimulustime(clearscreen, parameters.stimulusduration);
    trial.target.insertstimulustime(port.luresignal, 50)
]

/stimulusframes = [1 = responsekeys_part2, luresignal]
/validresponse = (values.responsekey_old, values.responsekey_similar, values.responsekey_new)
/beginresponseframe = 1
/ correctresponse = (values.responsekey_similar)
/ responsemessage = (values.responsekey_similar, similarsignal, 0)
/ responsemessage = (values.responsekey_old, oldsignal, 0)
/ responsemessage = (values.responsekey_new, newsignal, 0)
/responseinterrupt = frames

/ontrialend = [
    trial.lure.resetstimulusframes();
    
    if (trial.lure.responsetext == values.responsekey_old) {
        values.responseCategory = "old";        
    } else if (trial.lure.responsetext == values.responsekey_new) {
        values.responseCategory = "new";        
    } if (trial.lure.responsetext == values.responsekey_similar) {
        values.responseCategory = "similar";        
    } else if (trial.lure.response == 0) {
        values.responseCategory = "";
        values.count_noresponses += 1;
    };
    
    values.stimulus = picture.lure.currentitem;
    
    values.count_lures += 1;
    if (trial.lure.response != 0) {
        values.count_lures_corr += 1;
        if (trial.lure.correct) {
            values.count_simlures += 1;
        } else if (trial.lure.responsetext == values.responsekey_old) {
            values.count_oldlures += 1;            
        } else if (trial.lure.responsetext == values.responsekey_new) {
            values.count_newlures += 1;            
        };        
    };

    if (values.lurebin == "1"){
        if (trial.lure.responsetext == values.responsekey_old){
            values.L1O +=1;
        } else if (trial.lure.responsetext == values.responsekey_similar){
            values.L1S +=1;
        } else if (trial.lure.responsetext == values.responsekey_new){
            values.L1N +=1;            
        } else if ( trial.lure.response == 0){
            values.L1_NR += 1;
        };
    } else if (values.lurebin == "2"){
        if (trial.lure.responsetext == values.responsekey_old){
            values.L2O +=1;
        } else if (trial.lure.responsetext == values.responsekey_similar){
            values.L2S +=1;
        } else if (trial.lure.responsetext == values.responsekey_new){
            values.L2N +=1;            
        } else if ( trial.lure.response == 0){
            values.L2_NR += 1;
        };
    } else if (values.lurebin == "3"){
        if (trial.lure.responsetext == values.responsekey_old){
            values.L3O +=1;
        } else if (trial.lure.responsetext == values.responsekey_similar){
            values.L3S +=1;
        } else if (trial.lure.responsetext == values.responsekey_new){
            values.L3N +=1;            
        } else if ( trial.lure.response == 0){
            values.L3_NR += 1;
        };
    } else if (values.lurebin == "4"){
        if (trial.lure.responsetext == values.responsekey_old){
            values.L4O +=1;
        } else if (trial.lure.responsetext == values.responsekey_similar){
            values.L4S +=1;
        } else if (trial.lure.responsetext == values.responsekey_new){
            values.L4N +=1;            
        } else if ( trial.lure.response == 0){
            values.L4_NR += 1;
        };
    } else if (values.lurebin == "5"){
        if (trial.lure.responsetext == values.responsekey_old){
            values.L5O +=1;
        } else if (trial.lure.responsetext == values.responsekey_similar){
            values.L5S +=1;
        } else if (trial.lure.responsetext == values.responsekey_new){
            values.L5N +=1;            
        } else if ( trial.lure.response == 0){
            values.L5_NR += 1;
        };
    };
]
/trialduration = (parameters.stimulusduration + parameters.ISI)
/recorddata = true
/branch = [return trial.part2;]
</trial>

Any help would be greatly appreciated!
By Dave - 7/4/2022

smo - 7/4/2022
smo - 7/4/2022
Hi,

Our team is hoping to add some EEG triggers to an Inquisit task (Behavioral Pattern Separation Task - Object Version - Set C - English). All stimulus and response triggers work, but we have an issue when the response time (RT) of one trial was too long that the response trigger of that trial was counted as a response trigger of the following trial. We found this issue because we saw some trials had a RT of less than or equal to 50 ms, which is not a propobale RT people could have. We also saw one trial with two response triggers, one of which is probably from the previous trial. Therefore, we wanted to disregard those trials that have a 50 ms response trigger, which is a response trigger of the previous trial but is counted as a response trigger of the following trial.

Another issue we have are with those trials that have a 2500 ms response trigger and have a 2500 ms RT in the behavioural data (2500 ms indicates the end of trial, so we want to disregard those too). The behavioural data generated by Inquisit 6 worked well as it counted trials that had a 2500 ms RT as no response, but the bdf file (i.e. the EEG data file) will show one trigger only, which is a combination of a response trigger from the previous trial and a stimulus trigger for the next trial.

We wonder:
1. Is there a 50 ms buffer we can add to our code that can prevent any response that is <50 ms to send out a reposne trigger?
2. Is there a way to disregard a 2500 ms response trigger and make sure there is always a stimulus trigger sent out when there is an overalp between stimulus and response trigger?

The following is our trigger code.

Stimulus trigger
//20 for Targetsignal
<port targetsignal>
/ port = LPT1
/ subport = data
/ items = ("00010100")
</port>

//30 for luresignal
<port luresignal>
/ port = LPT1
/ subport = data
/ items = ("00011110")
</port>

//40 for foilsignal
<port foilsignal>
/ port = LPT1
/ subport = data
/ items = ("00101000")
</port>


Response Trigger
// 55
<port oldsignal>
/ port = LPT1
/ subport = data
/ items = ("00110111")
</port>

//66 for similar trials
<port similarsignal>
/ port = LPT1
/ subport = data
/ items = ("01000010")
</port>

//77 for new trials
<port newsignal>
/ port = LPT1
/ subport = data
/ items = ("01001101")
</port>[code]Stimulus trigger
//20 for Targetsignal
<port targetsignal>
/ port = LPT1
/ subport = data
/ items = ("00010100")
</port>

//30 for luresignal
<port luresignal>
/ port = LPT1
/ subport = data
/ items = ("00011110")
</port>

//40 for foilsignal
<port foilsignal>
/ port = LPT1
/ subport = data
/ items = ("00101000")
</port>


Response Trigger
// 55
<port oldsignal>
/ port = LPT1
/ subport = data
/ items = ("00110111")
</port>

//66 for similar trials
<port similarsignal>
/ port = LPT1
/ subport = data
/ items = ("01000010")
</port>

//77 for new trials
<port newsignal>
/ port = LPT1
/ subport = data
/ items = ("01001101")
</port>

<trial target>
/ontrialbegin = [
    values.stimulusselect = list.targets.nextvalue;
    trial.target.insertstimulusframe(picture.target, 1);
    trial.target.insertstimulustime(clearscreen, parameters.stimulusduration);
    trial.target.insertstimulustime(port.targetsignal, 50)
]

/stimulusframes = [1 = responsekeys_part2, targetsignal]
/validresponse = (values.responsekey_old, values.responsekey_similar, values.responsekey_new)
/ correctresponse = (values.responsekey_old)
/ responsemessage = (values.responsekey_old, oldsignal, 0)
/ responsemessage = (values.responsekey_similar, similarsignal, 0)
/ responsemessage = (values.responsekey_new, newsignal, 0)

/beginresponseframe = 1
/responseinterrupt = frames

/ontrialend = [
    trial.target.resetstimulusframes();
    if (trial.target.responsetext == values.responsekey_old) {
        values.responseCategory = "old";    
    } else if (trial.target.responsetext == values.responsekey_new) {
        values.responseCategory = "new";    
    } else if (trial.target.responsetext == values.responsekey_similar) {
        values.responseCategory = "similar";    
    } else if (trial.target.response == 0) {
        values.responseCategory = "";
        values.count_noresponses += 1;
    };

    values.stimulus = picture.target.currentitem;
    
    values.count_targets += 1;
    if (trial.target.response != 0) {
        values.count_targets_corr += 1;
        if (trial.target.correct) {
            values.count_oldtargets += 1;
        } else if (trial.target.responsetext == values.responsekey_similar) {
            values.count_simtargets += 1;    
        } else if (trial.target.responsetext == values.responsekey_new) {
            values.count_newtargets += 1        
        };    
    };

]
/trialduration = (parameters.stimulusduration + parameters.ISI)
/recorddata = true
/branch = [return trial.part2;]
</trial>

Note:
* presents a foil for parameters.stimulusduration
* collects response during that time
* updates summary variables
* calls trial.part2
<trial foil>
/ontrialbegin = [
    values.stimulusselect = list.foils.nextvalue;
    trial.foil.insertstimulusframe(picture.foil, 1);             
    trial.foil.insertstimulustime(clearscreen, parameters.stimulusduration);
    trial.target.insertstimulustime(port.foilsignal, 50)
]

/stimulusframes = [1 = responsekeys_part2, foilsignal]
/validresponse = (values.responsekey_old, values.responsekey_similar, values.responsekey_new)
/ correctresponse = (values.responsekey_new)
/ responsemessage = (values.responsekey_old, oldsignal, 0)
/ responsemessage = (values.responsekey_similar, similarsignal, 0)
/ responsemessage = (values.responsekey_new, newsignal, 0)
/beginresponseframe = 1
/responseinterrupt = frames
/ontrialend = [
    trial.foil.resetstimulusframes();
    
    if (trial.foil.responsetext == values.responsekey_old) {
        values.responseCategory = "old";        
    } else if (trial.foil.responsetext == values.responsekey_new) {
        values.responseCategory = "new";    
    } else if (trial.foil.responsetext == values.responsekey_similar) {
        values.responseCategory = "similar";    
    } else if (trial.foil.response == 0) {
        values.responseCategory = "";
        values.count_noresponses += 1;
    };
    
    values.stimulus = picture.foil.currentitem;
    
    values.count_foils += 1;
    if (trial.foil.response != 0) {
        values.count_foils_corr += 1;
        if (trial.foil.correct) {
            values.count_newfoils += 1;
        } else if (trial.foil.responsetext == values.responsekey_old) {
            values.count_oldfoils += 1            
        } else if (trial.foil.responsetext == values.responsekey_similar) {
            values.count_simfoils += 1;                
        };        
    };
]
/trialduration = (parameters.stimulusduration + parameters.ISI)
/recorddata = true
/branch = [return trial.part2;]
</trial>

Note:
* presents a lure for parameters.stimulusduration
* collects response during that time
* updates summary variables
* calls trial.part2
<trial lure>
/ontrialbegin = [
    values.stimulusselect = list.lures.nextvalue;    
    values.lurebin = item.lurebins.item(values.stimulusselect);    
    
    if (values.lurebin == 1) {
        values.L1 += 1;        
    } else if (values.lurebin == 2) {
        values.L2 += 1;        
    } else if (values.lurebin == 3) {
        values.L3 += 1;        
    } else if (values.lurebin == 4) {
        values.L4 += 1;        
    } else if (values.lurebin == 5) {
        values.L5 += 1;        
    } else {
        values.lurebin = "NA";        
    };

    trial.lure.insertstimulusframe(picture.lure, 1);        
    trial.lure.insertstimulustime(clearscreen, parameters.stimulusduration);
    trial.target.insertstimulustime(port.luresignal, 50)
]

/stimulusframes = [1 = responsekeys_part2, luresignal]
/validresponse = (values.responsekey_old, values.responsekey_similar, values.responsekey_new)
/beginresponseframe = 1
/ correctresponse = (values.responsekey_similar)
/ responsemessage = (values.responsekey_similar, similarsignal, 0)
/ responsemessage = (values.responsekey_old, oldsignal, 0)
/ responsemessage = (values.responsekey_new, newsignal, 0)
/responseinterrupt = frames

/ontrialend = [
    trial.lure.resetstimulusframes();
    
    if (trial.lure.responsetext == values.responsekey_old) {
        values.responseCategory = "old";        
    } else if (trial.lure.responsetext == values.responsekey_new) {
        values.responseCategory = "new";        
    } if (trial.lure.responsetext == values.responsekey_similar) {
        values.responseCategory = "similar";        
    } else if (trial.lure.response == 0) {
        values.responseCategory = "";
        values.count_noresponses += 1;
    };
    
    values.stimulus = picture.lure.currentitem;
    
    values.count_lures += 1;
    if (trial.lure.response != 0) {
        values.count_lures_corr += 1;
        if (trial.lure.correct) {
            values.count_simlures += 1;
        } else if (trial.lure.responsetext == values.responsekey_old) {
            values.count_oldlures += 1;            
        } else if (trial.lure.responsetext == values.responsekey_new) {
            values.count_newlures += 1;            
        };        
    };

    if (values.lurebin == "1"){
        if (trial.lure.responsetext == values.responsekey_old){
            values.L1O +=1;
        } else if (trial.lure.responsetext == values.responsekey_similar){
            values.L1S +=1;
        } else if (trial.lure.responsetext == values.responsekey_new){
            values.L1N +=1;            
        } else if ( trial.lure.response == 0){
            values.L1_NR += 1;
        };
    } else if (values.lurebin == "2"){
        if (trial.lure.responsetext == values.responsekey_old){
            values.L2O +=1;
        } else if (trial.lure.responsetext == values.responsekey_similar){
            values.L2S +=1;
        } else if (trial.lure.responsetext == values.responsekey_new){
            values.L2N +=1;            
        } else if ( trial.lure.response == 0){
            values.L2_NR += 1;
        };
    } else if (values.lurebin == "3"){
        if (trial.lure.responsetext == values.responsekey_old){
            values.L3O +=1;
        } else if (trial.lure.responsetext == values.responsekey_similar){
            values.L3S +=1;
        } else if (trial.lure.responsetext == values.responsekey_new){
            values.L3N +=1;            
        } else if ( trial.lure.response == 0){
            values.L3_NR += 1;
        };
    } else if (values.lurebin == "4"){
        if (trial.lure.responsetext == values.responsekey_old){
            values.L4O +=1;
        } else if (trial.lure.responsetext == values.responsekey_similar){
            values.L4S +=1;
        } else if (trial.lure.responsetext == values.responsekey_new){
            values.L4N +=1;            
        } else if ( trial.lure.response == 0){
            values.L4_NR += 1;
        };
    } else if (values.lurebin == "5"){
        if (trial.lure.responsetext == values.responsekey_old){
            values.L5O +=1;
        } else if (trial.lure.responsetext == values.responsekey_similar){
            values.L5S +=1;
        } else if (trial.lure.responsetext == values.responsekey_new){
            values.L5N +=1;            
        } else if ( trial.lure.response == 0){
            values.L5_NR += 1;
        };
    };
]
/trialduration = (parameters.stimulusduration + parameters.ISI)
/recorddata = true
/branch = [return trial.part2;]
</trial>

Any help would be greatly appreciated!

> All stimulus and response triggers work, but we have an issue when the response time (RT) of one trial was too long that the response trigger of that trial was counted as a response trigger of the following trial. We found this issue because we saw some trials had a RT of less than or equal to 50 ms, which is not a propobale RT people could have. We also saw one trial with two response triggers, one of which is probably from the previous trial. Therefore, we wanted to disregard those trials that have a 50 ms response trigger, which is a response trigger of the previous trial but is counted as a response trigger of the following trial.

I'm sorry, but this description doesn't make sense to me. Please clarify and refer to the specific triggers you meam by their name and value.
By smo - 7/4/2022

Hi Dave,

My apologies for the confusion! Here is a revised description.

The main problem we have is in the test phase, where participants have to indicate whether the picture they see on the screen is an old, similar, or new picture compared to the exposure phase, where they only judge whether the picture shows an indoor or outdoor item. There are three stimulus triggers and three response triggers in total in the test phase.

Stimulus triggers (called target, lure, and foil, respectively) are as follows.
<port targetsignal>
/ port = LPT1
/ subport = data
/ items = ("00010100")
</port>

<port luresignal>
/ port = LPT1
/ subport = data
/ items = ("00011110")
</port>

<port foilsignal>
/ port = LPT1
/ subport = data
/ items = ("00101000")
</port>

Response triggers (called old, similar, and new, respectively) are as follows.
<port oldsignal>
/ port = LPT1
/ subport = data
/ items = ("00110111")
</port>

<port similarsignal>
/ port = LPT1
/ subport = data
/ items = ("01000010")
</port>

<port newsignal>
/ port = LPT1
/ subport = data
/ items = ("01001101")
</port>

Each trial lasts 2500 ms. When a picture shows up on the screen, Inquisit sends out a stimulus trigger that corresponds to the type of picture (i.e. target, lure, or foil). When a participant makes a response, Inquisit sends out a response trigger that corresponds to the type of response people make (i.e. old, similar, or new). When participants make a response by 2500 ms, all triggers work well as we can see one stimulus trigger and one response trigger in each trial. However, when the responses were made right at 2500 ms, we saw two issues.

1. When the RT of one trial is right at 2500 ms, the behavioural data we extracted showed "no response" for that particular trial, which is correct. But in the bdf (which is an EEG data file), we saw that in addition to no response trigger for that particular trial, the response trigger seemed to overlap with the following stimulus trigger of the next trial. So the order is: stimulus trigger A -> no response trigger -> A trigger that combines response trigger A and stimulus trigger B -> response trigger B.

2. We also saw some trials have a RT of 50 ms, which is not a probable RT people could have. We suspect these could due to the slow RT, where a response triggers was sent out so late that it was counted into the next trial. For this case, we would like to disregard the <50 ms response trigger from the previous trial and record the actual response for the current trial.

We wonder:
1. Is there a way to disregard a 2500 ms response trigger and make sure there is always a stimulus trigger sent out when there is an overlap between stimulus and response trigger?
2. Is there a 50 ms buffer we can add to our code that can prevent any response that is <50 ms from being recorded in both behaviour and EEG data?

The following are the three trials in which stimulus and response triggers were added.
<trial target>
/ontrialbegin = [
  values.stimulusselect = list.targets.nextvalue;
  trial.target.insertstimulusframe(picture.target, 1);
  trial.target.insertstimulustime(clearscreen, parameters.stimulusduration);
  trial.target.insertstimulustime(port.targetsignal, 50)
]

/stimulusframes = [1 = responsekeys_part2, targetsignal]
/validresponse = (values.responsekey_old, values.responsekey_similar, values.responsekey_new)
/ correctresponse = (values.responsekey_old)
/ responsemessage = (values.responsekey_old, oldsignal, 0)
/ responsemessage = (values.responsekey_similar, similarsignal, 0)
/ responsemessage = (values.responsekey_new, newsignal, 0)

/beginresponseframe = 1
/responseinterrupt = frames

/ontrialend = [
  trial.target.resetstimulusframes();
  if (trial.target.responsetext == values.responsekey_old) {
   values.responseCategory = "old"; 
  } else if (trial.target.responsetext == values.responsekey_new) {
   values.responseCategory = "new"; 
  } else if (trial.target.responsetext == values.responsekey_similar) {
   values.responseCategory = "similar"; 
  } else if (trial.target.response == 0) {
   values.responseCategory = "";
   values.count_noresponses += 1;
  };

  values.stimulus = picture.target.currentitem;
 
  values.count_targets += 1;
  if (trial.target.response != 0) {
   values.count_targets_corr += 1;
   if (trial.target.correct) {
    values.count_oldtargets += 1;
   } else if (trial.target.responsetext == values.responsekey_similar) {
    values.count_simtargets += 1; 
   } else if (trial.target.responsetext == values.responsekey_new) {
    values.count_newtargets += 1  
   }; 
  };

]
/trialduration = (parameters.stimulusduration + parameters.ISI)
/recorddata = true
/branch = [return trial.part2;]
</trial>

Note:
* presents a foil for parameters.stimulusduration
* collects response during that time
* updates summary variables
* calls trial.part2
<trial foil>
/ontrialbegin = [
  values.stimulusselect = list.foils.nextvalue;
  trial.foil.insertstimulusframe(picture.foil, 1);    
  trial.foil.insertstimulustime(clearscreen, parameters.stimulusduration);
  trial.target.insertstimulustime(port.foilsignal, 50)
]

/stimulusframes = [1 = responsekeys_part2, foilsignal]
/validresponse = (values.responsekey_old, values.responsekey_similar, values.responsekey_new)
/ correctresponse = (values.responsekey_new)
/ responsemessage = (values.responsekey_old, oldsignal, 0)
/ responsemessage = (values.responsekey_similar, similarsignal, 0)
/ responsemessage = (values.responsekey_new, newsignal, 0)
/beginresponseframe = 1
/responseinterrupt = frames
/ontrialend = [
  trial.foil.resetstimulusframes();
 
  if (trial.foil.responsetext == values.responsekey_old) {
   values.responseCategory = "old";  
  } else if (trial.foil.responsetext == values.responsekey_new) {
   values.responseCategory = "new"; 
  } else if (trial.foil.responsetext == values.responsekey_similar) {
   values.responseCategory = "similar"; 
  } else if (trial.foil.response == 0) {
   values.responseCategory = "";
   values.count_noresponses += 1;
  };
 
  values.stimulus = picture.foil.currentitem;
 
  values.count_foils += 1;
  if (trial.foil.response != 0) {
   values.count_foils_corr += 1;
   if (trial.foil.correct) {
    values.count_newfoils += 1;
   } else if (trial.foil.responsetext == values.responsekey_old) {
    values.count_oldfoils += 1    
   } else if (trial.foil.responsetext == values.responsekey_similar) {
    values.count_simfoils += 1;     
   };  
  };
]
/trialduration = (parameters.stimulusduration + parameters.ISI)
/recorddata = true
/branch = [return trial.part2;]
</trial>

Note:
* presents a lure for parameters.stimulusduration
* collects response during that time
* updates summary variables
* calls trial.part2
<trial lure>
/ontrialbegin = [
  values.stimulusselect = list.lures.nextvalue; 
  values.lurebin = item.lurebins.item(values.stimulusselect); 
 
  if (values.lurebin == 1) {
   values.L1 += 1;  
  } else if (values.lurebin == 2) {
   values.L2 += 1;  
  } else if (values.lurebin == 3) {
   values.L3 += 1;  
  } else if (values.lurebin == 4) {
   values.L4 += 1;  
  } else if (values.lurebin == 5) {
   values.L5 += 1;  
  } else {
   values.lurebin = "NA";  
  };

  trial.lure.insertstimulusframe(picture.lure, 1);  
  trial.lure.insertstimulustime(clearscreen, parameters.stimulusduration);
  trial.target.insertstimulustime(port.luresignal, 50)
]

/stimulusframes = [1 = responsekeys_part2, luresignal]
/validresponse = (values.responsekey_old, values.responsekey_similar, values.responsekey_new)
/beginresponseframe = 1
/ correctresponse = (values.responsekey_similar)
/ responsemessage = (values.responsekey_similar, similarsignal, 0)
/ responsemessage = (values.responsekey_old, oldsignal, 0)
/ responsemessage = (values.responsekey_new, newsignal, 0)
/responseinterrupt = frames

/ontrialend = [
  trial.lure.resetstimulusframes();
 
  if (trial.lure.responsetext == values.responsekey_old) {
   values.responseCategory = "old";  
  } else if (trial.lure.responsetext == values.responsekey_new) {
   values.responseCategory = "new";  
  } if (trial.lure.responsetext == values.responsekey_similar) {
   values.responseCategory = "similar";  
  } else if (trial.lure.response == 0) {
   values.responseCategory = "";
   values.count_noresponses += 1;
  };
 
  values.stimulus = picture.lure.currentitem;
 
  values.count_lures += 1;
  if (trial.lure.response != 0) {
   values.count_lures_corr += 1;
   if (trial.lure.correct) {
    values.count_simlures += 1;
   } else if (trial.lure.responsetext == values.responsekey_old) {
    values.count_oldlures += 1;    
   } else if (trial.lure.responsetext == values.responsekey_new) {
    values.count_newlures += 1;    
   };  
  };

  if (values.lurebin == "1"){
   if (trial.lure.responsetext == values.responsekey_old){
    values.L1O +=1;
   } else if (trial.lure.responsetext == values.responsekey_similar){
    values.L1S +=1;
   } else if (trial.lure.responsetext == values.responsekey_new){
    values.L1N +=1;    
   } else if ( trial.lure.response == 0){
    values.L1_NR += 1;
   };
  } else if (values.lurebin == "2"){
   if (trial.lure.responsetext == values.responsekey_old){
    values.L2O +=1;
   } else if (trial.lure.responsetext == values.responsekey_similar){
    values.L2S +=1;
   } else if (trial.lure.responsetext == values.responsekey_new){
    values.L2N +=1;    
   } else if ( trial.lure.response == 0){
    values.L2_NR += 1;
   };
  } else if (values.lurebin == "3"){
   if (trial.lure.responsetext == values.responsekey_old){
    values.L3O +=1;
   } else if (trial.lure.responsetext == values.responsekey_similar){
    values.L3S +=1;
   } else if (trial.lure.responsetext == values.responsekey_new){
    values.L3N +=1;    
   } else if ( trial.lure.response == 0){
    values.L3_NR += 1;
   };
  } else if (values.lurebin == "4"){
   if (trial.lure.responsetext == values.responsekey_old){
    values.L4O +=1;
   } else if (trial.lure.responsetext == values.responsekey_similar){
    values.L4S +=1;
   } else if (trial.lure.responsetext == values.responsekey_new){
    values.L4N +=1;    
   } else if ( trial.lure.response == 0){
    values.L4_NR += 1;
   };
  } else if (values.lurebin == "5"){
   if (trial.lure.responsetext == values.responsekey_old){
    values.L5O +=1;
   } else if (trial.lure.responsetext == values.responsekey_similar){
    values.L5S +=1;
   } else if (trial.lure.responsetext == values.responsekey_new){
    values.L5N +=1;    
   } else if ( trial.lure.response == 0){
    values.L5_NR += 1;
   };
  };
]
/trialduration = (parameters.stimulusduration + parameters.ISI)
/recorddata = true
/branch = [return trial.part2;]
</trial>

Thanks for the help!



By Dave - 7/4/2022

smo - 7/4/2022
Hi Dave,

My apologies for the confusion! Here is a revised description.

The main problem we have is in the test phase, where participants have to indicate whether the picture they see on the screen is an old, similar, or new picture compared to the exposure phase, where they only judge whether the picture shows an indoor or outdoor item. There are three stimulus triggers and three response triggers in total in the test phase.

Stimulus triggers (called target, lure, and foil, respectively) are as follows.
<port targetsignal>
/ port = LPT1
/ subport = data
/ items = ("00010100")
</port>

<port luresignal>
/ port = LPT1
/ subport = data
/ items = ("00011110")
</port>

<port foilsignal>
/ port = LPT1
/ subport = data
/ items = ("00101000")
</port>

Response triggers (called old, similar, and new, respectively) are as follows.
<port oldsignal>
/ port = LPT1
/ subport = data
/ items = ("00110111")
</port>

<port similarsignal>
/ port = LPT1
/ subport = data
/ items = ("01000010")
</port>

<port newsignal>
/ port = LPT1
/ subport = data
/ items = ("01001101")
</port>

Each trial lasts 2500 ms. When a picture shows up on the screen, Inquisit sends out a stimulus trigger that corresponds to the type of picture (i.e. target, lure, or foil). When a participant makes a response, Inquisit sends out a response trigger that corresponds to the type of response people make (i.e. old, similar, or new). When participants make a response by 2500 ms, all triggers work well as we can see one stimulus trigger and one response trigger in each trial. However, when the responses were made right at 2500 ms, we saw two issues.

1. When the RT of one trial is right at 2500 ms, the behavioural data we extracted showed "no response" for that particular trial, which is correct. But in the bdf (which is an EEG data file), we saw that in addition to no response trigger for that particular trial, the response trigger seemed to overlap with the following stimulus trigger of the next trial. So the order is: stimulus trigger A -> no response trigger -> A trigger that combines response trigger A and stimulus trigger B -> response trigger B.

2. We also saw some trials have a RT of 50 ms, which is not a probable RT people could have. We suspect these could due to the slow RT, where a response triggers was sent out so late that it was counted into the next trial. For this case, we would like to disregard the <50 ms response trigger from the previous trial and record the actual response for the current trial.

We wonder:
1. Is there a way to disregard a 2500 ms response trigger and make sure there is always a stimulus trigger sent out when there is an overlap between stimulus and response trigger?
2. Is there a 50 ms buffer we can add to our code that can prevent any response that is <50 ms from being recorded in both behaviour and EEG data?

The following are the three trials in which stimulus and response triggers were added.
<trial target>
/ontrialbegin = [
  values.stimulusselect = list.targets.nextvalue;
  trial.target.insertstimulusframe(picture.target, 1);
  trial.target.insertstimulustime(clearscreen, parameters.stimulusduration);
  trial.target.insertstimulustime(port.targetsignal, 50)
]

/stimulusframes = [1 = responsekeys_part2, targetsignal]
/validresponse = (values.responsekey_old, values.responsekey_similar, values.responsekey_new)
/ correctresponse = (values.responsekey_old)
/ responsemessage = (values.responsekey_old, oldsignal, 0)
/ responsemessage = (values.responsekey_similar, similarsignal, 0)
/ responsemessage = (values.responsekey_new, newsignal, 0)

/beginresponseframe = 1
/responseinterrupt = frames

/ontrialend = [
  trial.target.resetstimulusframes();
  if (trial.target.responsetext == values.responsekey_old) {
   values.responseCategory = "old"; 
  } else if (trial.target.responsetext == values.responsekey_new) {
   values.responseCategory = "new"; 
  } else if (trial.target.responsetext == values.responsekey_similar) {
   values.responseCategory = "similar"; 
  } else if (trial.target.response == 0) {
   values.responseCategory = "";
   values.count_noresponses += 1;
  };

  values.stimulus = picture.target.currentitem;
 
  values.count_targets += 1;
  if (trial.target.response != 0) {
   values.count_targets_corr += 1;
   if (trial.target.correct) {
    values.count_oldtargets += 1;
   } else if (trial.target.responsetext == values.responsekey_similar) {
    values.count_simtargets += 1; 
   } else if (trial.target.responsetext == values.responsekey_new) {
    values.count_newtargets += 1  
   }; 
  };

]
/trialduration = (parameters.stimulusduration + parameters.ISI)
/recorddata = true
/branch = [return trial.part2;]
</trial>

Note:
* presents a foil for parameters.stimulusduration
* collects response during that time
* updates summary variables
* calls trial.part2
<trial foil>
/ontrialbegin = [
  values.stimulusselect = list.foils.nextvalue;
  trial.foil.insertstimulusframe(picture.foil, 1);    
  trial.foil.insertstimulustime(clearscreen, parameters.stimulusduration);
  trial.target.insertstimulustime(port.foilsignal, 50)
]

/stimulusframes = [1 = responsekeys_part2, foilsignal]
/validresponse = (values.responsekey_old, values.responsekey_similar, values.responsekey_new)
/ correctresponse = (values.responsekey_new)
/ responsemessage = (values.responsekey_old, oldsignal, 0)
/ responsemessage = (values.responsekey_similar, similarsignal, 0)
/ responsemessage = (values.responsekey_new, newsignal, 0)
/beginresponseframe = 1
/responseinterrupt = frames
/ontrialend = [
  trial.foil.resetstimulusframes();
 
  if (trial.foil.responsetext == values.responsekey_old) {
   values.responseCategory = "old";  
  } else if (trial.foil.responsetext == values.responsekey_new) {
   values.responseCategory = "new"; 
  } else if (trial.foil.responsetext == values.responsekey_similar) {
   values.responseCategory = "similar"; 
  } else if (trial.foil.response == 0) {
   values.responseCategory = "";
   values.count_noresponses += 1;
  };
 
  values.stimulus = picture.foil.currentitem;
 
  values.count_foils += 1;
  if (trial.foil.response != 0) {
   values.count_foils_corr += 1;
   if (trial.foil.correct) {
    values.count_newfoils += 1;
   } else if (trial.foil.responsetext == values.responsekey_old) {
    values.count_oldfoils += 1    
   } else if (trial.foil.responsetext == values.responsekey_similar) {
    values.count_simfoils += 1;     
   };  
  };
]
/trialduration = (parameters.stimulusduration + parameters.ISI)
/recorddata = true
/branch = [return trial.part2;]
</trial>

Note:
* presents a lure for parameters.stimulusduration
* collects response during that time
* updates summary variables
* calls trial.part2
<trial lure>
/ontrialbegin = [
  values.stimulusselect = list.lures.nextvalue; 
  values.lurebin = item.lurebins.item(values.stimulusselect); 
 
  if (values.lurebin == 1) {
   values.L1 += 1;  
  } else if (values.lurebin == 2) {
   values.L2 += 1;  
  } else if (values.lurebin == 3) {
   values.L3 += 1;  
  } else if (values.lurebin == 4) {
   values.L4 += 1;  
  } else if (values.lurebin == 5) {
   values.L5 += 1;  
  } else {
   values.lurebin = "NA";  
  };

  trial.lure.insertstimulusframe(picture.lure, 1);  
  trial.lure.insertstimulustime(clearscreen, parameters.stimulusduration);
  trial.target.insertstimulustime(port.luresignal, 50)
]

/stimulusframes = [1 = responsekeys_part2, luresignal]
/validresponse = (values.responsekey_old, values.responsekey_similar, values.responsekey_new)
/beginresponseframe = 1
/ correctresponse = (values.responsekey_similar)
/ responsemessage = (values.responsekey_similar, similarsignal, 0)
/ responsemessage = (values.responsekey_old, oldsignal, 0)
/ responsemessage = (values.responsekey_new, newsignal, 0)
/responseinterrupt = frames

/ontrialend = [
  trial.lure.resetstimulusframes();
 
  if (trial.lure.responsetext == values.responsekey_old) {
   values.responseCategory = "old";  
  } else if (trial.lure.responsetext == values.responsekey_new) {
   values.responseCategory = "new";  
  } if (trial.lure.responsetext == values.responsekey_similar) {
   values.responseCategory = "similar";  
  } else if (trial.lure.response == 0) {
   values.responseCategory = "";
   values.count_noresponses += 1;
  };
 
  values.stimulus = picture.lure.currentitem;
 
  values.count_lures += 1;
  if (trial.lure.response != 0) {
   values.count_lures_corr += 1;
   if (trial.lure.correct) {
    values.count_simlures += 1;
   } else if (trial.lure.responsetext == values.responsekey_old) {
    values.count_oldlures += 1;    
   } else if (trial.lure.responsetext == values.responsekey_new) {
    values.count_newlures += 1;    
   };  
  };

  if (values.lurebin == "1"){
   if (trial.lure.responsetext == values.responsekey_old){
    values.L1O +=1;
   } else if (trial.lure.responsetext == values.responsekey_similar){
    values.L1S +=1;
   } else if (trial.lure.responsetext == values.responsekey_new){
    values.L1N +=1;    
   } else if ( trial.lure.response == 0){
    values.L1_NR += 1;
   };
  } else if (values.lurebin == "2"){
   if (trial.lure.responsetext == values.responsekey_old){
    values.L2O +=1;
   } else if (trial.lure.responsetext == values.responsekey_similar){
    values.L2S +=1;
   } else if (trial.lure.responsetext == values.responsekey_new){
    values.L2N +=1;    
   } else if ( trial.lure.response == 0){
    values.L2_NR += 1;
   };
  } else if (values.lurebin == "3"){
   if (trial.lure.responsetext == values.responsekey_old){
    values.L3O +=1;
   } else if (trial.lure.responsetext == values.responsekey_similar){
    values.L3S +=1;
   } else if (trial.lure.responsetext == values.responsekey_new){
    values.L3N +=1;    
   } else if ( trial.lure.response == 0){
    values.L3_NR += 1;
   };
  } else if (values.lurebin == "4"){
   if (trial.lure.responsetext == values.responsekey_old){
    values.L4O +=1;
   } else if (trial.lure.responsetext == values.responsekey_similar){
    values.L4S +=1;
   } else if (trial.lure.responsetext == values.responsekey_new){
    values.L4N +=1;    
   } else if ( trial.lure.response == 0){
    values.L4_NR += 1;
   };
  } else if (values.lurebin == "5"){
   if (trial.lure.responsetext == values.responsekey_old){
    values.L5O +=1;
   } else if (trial.lure.responsetext == values.responsekey_similar){
    values.L5S +=1;
   } else if (trial.lure.responsetext == values.responsekey_new){
    values.L5N +=1;    
   } else if ( trial.lure.response == 0){
    values.L5_NR += 1;
   };
  };
]
/trialduration = (parameters.stimulusduration + parameters.ISI)
/recorddata = true
/branch = [return trial.part2;]
</trial>

Thanks for the help!




> 1. When the RT of one trial is right at 2500 ms, the behavioural data we extracted showed "no response" for that particular trial, which is correct. But in the bdf (which is an EEG data file), we saw that in addition to no response trigger for that particular trial, the response trigger seemed to overlap with the following stimulus trigger of the next trial. So the order is: stimulus trigger A -> no response trigger -> A trigger that combines response trigger A and stimulus trigger B -> response trigger B.

There is no response trigger in trials where there is no response. If anything, what you are seeing must be an overlap of trial A's stimulus trigger (target-, lure-, or foilsignal) with trial B's stimulustrigger. While the stimulustrigger is erased at the end of a trial, that status change may be just too short for your equipment to pick up.

The solution here, is to actually send a trigger in case of no response per responsemessage, even if that trigger merely serves to lower any signal for a sufficiently long amount of time.

/ responsemessage = (0, allbitstolow, 50)

with

<port allbitstolow>
/ port = LPT1
/ subport = data
/ items = ("00000000")
/ erase = false
</port>

> 1. Is there a 50 ms buffer we can add to our code that can prevent any response that is <50 ms to send out a response trigger?

No. Moreover, it is doubtful that there actually was any trial with a response time < 50 ms. Do you have any Inquisit (not BDF) data file that actually shows such an RT?

By Dave - 7/4/2022

Dave - 7/4/2022
smo - 7/4/2022
Hi Dave,

My apologies for the confusion! Here is a revised description.

The main problem we have is in the test phase, where participants have to indicate whether the picture they see on the screen is an old, similar, or new picture compared to the exposure phase, where they only judge whether the picture shows an indoor or outdoor item. There are three stimulus triggers and three response triggers in total in the test phase.

Stimulus triggers (called target, lure, and foil, respectively) are as follows.
<port targetsignal>
/ port = LPT1
/ subport = data
/ items = ("00010100")
</port>

<port luresignal>
/ port = LPT1
/ subport = data
/ items = ("00011110")
</port>

<port foilsignal>
/ port = LPT1
/ subport = data
/ items = ("00101000")
</port>

Response triggers (called old, similar, and new, respectively) are as follows.
<port oldsignal>
/ port = LPT1
/ subport = data
/ items = ("00110111")
</port>

<port similarsignal>
/ port = LPT1
/ subport = data
/ items = ("01000010")
</port>

<port newsignal>
/ port = LPT1
/ subport = data
/ items = ("01001101")
</port>

Each trial lasts 2500 ms. When a picture shows up on the screen, Inquisit sends out a stimulus trigger that corresponds to the type of picture (i.e. target, lure, or foil). When a participant makes a response, Inquisit sends out a response trigger that corresponds to the type of response people make (i.e. old, similar, or new). When participants make a response by 2500 ms, all triggers work well as we can see one stimulus trigger and one response trigger in each trial. However, when the responses were made right at 2500 ms, we saw two issues.

1. When the RT of one trial is right at 2500 ms, the behavioural data we extracted showed "no response" for that particular trial, which is correct. But in the bdf (which is an EEG data file), we saw that in addition to no response trigger for that particular trial, the response trigger seemed to overlap with the following stimulus trigger of the next trial. So the order is: stimulus trigger A -> no response trigger -> A trigger that combines response trigger A and stimulus trigger B -> response trigger B.

2. We also saw some trials have a RT of 50 ms, which is not a probable RT people could have. We suspect these could due to the slow RT, where a response triggers was sent out so late that it was counted into the next trial. For this case, we would like to disregard the <50 ms response trigger from the previous trial and record the actual response for the current trial.

We wonder:
1. Is there a way to disregard a 2500 ms response trigger and make sure there is always a stimulus trigger sent out when there is an overlap between stimulus and response trigger?
2. Is there a 50 ms buffer we can add to our code that can prevent any response that is <50 ms from being recorded in both behaviour and EEG data?

The following are the three trials in which stimulus and response triggers were added.
<trial target>
/ontrialbegin = [
  values.stimulusselect = list.targets.nextvalue;
  trial.target.insertstimulusframe(picture.target, 1);
  trial.target.insertstimulustime(clearscreen, parameters.stimulusduration);
  trial.target.insertstimulustime(port.targetsignal, 50)
]

/stimulusframes = [1 = responsekeys_part2, targetsignal]
/validresponse = (values.responsekey_old, values.responsekey_similar, values.responsekey_new)
/ correctresponse = (values.responsekey_old)
/ responsemessage = (values.responsekey_old, oldsignal, 0)
/ responsemessage = (values.responsekey_similar, similarsignal, 0)
/ responsemessage = (values.responsekey_new, newsignal, 0)

/beginresponseframe = 1
/responseinterrupt = frames

/ontrialend = [
  trial.target.resetstimulusframes();
  if (trial.target.responsetext == values.responsekey_old) {
   values.responseCategory = "old"; 
  } else if (trial.target.responsetext == values.responsekey_new) {
   values.responseCategory = "new"; 
  } else if (trial.target.responsetext == values.responsekey_similar) {
   values.responseCategory = "similar"; 
  } else if (trial.target.response == 0) {
   values.responseCategory = "";
   values.count_noresponses += 1;
  };

  values.stimulus = picture.target.currentitem;
 
  values.count_targets += 1;
  if (trial.target.response != 0) {
   values.count_targets_corr += 1;
   if (trial.target.correct) {
    values.count_oldtargets += 1;
   } else if (trial.target.responsetext == values.responsekey_similar) {
    values.count_simtargets += 1; 
   } else if (trial.target.responsetext == values.responsekey_new) {
    values.count_newtargets += 1  
   }; 
  };

]
/trialduration = (parameters.stimulusduration + parameters.ISI)
/recorddata = true
/branch = [return trial.part2;]
</trial>

Note:
* presents a foil for parameters.stimulusduration
* collects response during that time
* updates summary variables
* calls trial.part2
<trial foil>
/ontrialbegin = [
  values.stimulusselect = list.foils.nextvalue;
  trial.foil.insertstimulusframe(picture.foil, 1);    
  trial.foil.insertstimulustime(clearscreen, parameters.stimulusduration);
  trial.target.insertstimulustime(port.foilsignal, 50)
]

/stimulusframes = [1 = responsekeys_part2, foilsignal]
/validresponse = (values.responsekey_old, values.responsekey_similar, values.responsekey_new)
/ correctresponse = (values.responsekey_new)
/ responsemessage = (values.responsekey_old, oldsignal, 0)
/ responsemessage = (values.responsekey_similar, similarsignal, 0)
/ responsemessage = (values.responsekey_new, newsignal, 0)
/beginresponseframe = 1
/responseinterrupt = frames
/ontrialend = [
  trial.foil.resetstimulusframes();
 
  if (trial.foil.responsetext == values.responsekey_old) {
   values.responseCategory = "old";  
  } else if (trial.foil.responsetext == values.responsekey_new) {
   values.responseCategory = "new"; 
  } else if (trial.foil.responsetext == values.responsekey_similar) {
   values.responseCategory = "similar"; 
  } else if (trial.foil.response == 0) {
   values.responseCategory = "";
   values.count_noresponses += 1;
  };
 
  values.stimulus = picture.foil.currentitem;
 
  values.count_foils += 1;
  if (trial.foil.response != 0) {
   values.count_foils_corr += 1;
   if (trial.foil.correct) {
    values.count_newfoils += 1;
   } else if (trial.foil.responsetext == values.responsekey_old) {
    values.count_oldfoils += 1    
   } else if (trial.foil.responsetext == values.responsekey_similar) {
    values.count_simfoils += 1;     
   };  
  };
]
/trialduration = (parameters.stimulusduration + parameters.ISI)
/recorddata = true
/branch = [return trial.part2;]
</trial>

Note:
* presents a lure for parameters.stimulusduration
* collects response during that time
* updates summary variables
* calls trial.part2
<trial lure>
/ontrialbegin = [
  values.stimulusselect = list.lures.nextvalue; 
  values.lurebin = item.lurebins.item(values.stimulusselect); 
 
  if (values.lurebin == 1) {
   values.L1 += 1;  
  } else if (values.lurebin == 2) {
   values.L2 += 1;  
  } else if (values.lurebin == 3) {
   values.L3 += 1;  
  } else if (values.lurebin == 4) {
   values.L4 += 1;  
  } else if (values.lurebin == 5) {
   values.L5 += 1;  
  } else {
   values.lurebin = "NA";  
  };

  trial.lure.insertstimulusframe(picture.lure, 1);  
  trial.lure.insertstimulustime(clearscreen, parameters.stimulusduration);
  trial.target.insertstimulustime(port.luresignal, 50)
]

/stimulusframes = [1 = responsekeys_part2, luresignal]
/validresponse = (values.responsekey_old, values.responsekey_similar, values.responsekey_new)
/beginresponseframe = 1
/ correctresponse = (values.responsekey_similar)
/ responsemessage = (values.responsekey_similar, similarsignal, 0)
/ responsemessage = (values.responsekey_old, oldsignal, 0)
/ responsemessage = (values.responsekey_new, newsignal, 0)
/responseinterrupt = frames

/ontrialend = [
  trial.lure.resetstimulusframes();
 
  if (trial.lure.responsetext == values.responsekey_old) {
   values.responseCategory = "old";  
  } else if (trial.lure.responsetext == values.responsekey_new) {
   values.responseCategory = "new";  
  } if (trial.lure.responsetext == values.responsekey_similar) {
   values.responseCategory = "similar";  
  } else if (trial.lure.response == 0) {
   values.responseCategory = "";
   values.count_noresponses += 1;
  };
 
  values.stimulus = picture.lure.currentitem;
 
  values.count_lures += 1;
  if (trial.lure.response != 0) {
   values.count_lures_corr += 1;
   if (trial.lure.correct) {
    values.count_simlures += 1;
   } else if (trial.lure.responsetext == values.responsekey_old) {
    values.count_oldlures += 1;    
   } else if (trial.lure.responsetext == values.responsekey_new) {
    values.count_newlures += 1;    
   };  
  };

  if (values.lurebin == "1"){
   if (trial.lure.responsetext == values.responsekey_old){
    values.L1O +=1;
   } else if (trial.lure.responsetext == values.responsekey_similar){
    values.L1S +=1;
   } else if (trial.lure.responsetext == values.responsekey_new){
    values.L1N +=1;    
   } else if ( trial.lure.response == 0){
    values.L1_NR += 1;
   };
  } else if (values.lurebin == "2"){
   if (trial.lure.responsetext == values.responsekey_old){
    values.L2O +=1;
   } else if (trial.lure.responsetext == values.responsekey_similar){
    values.L2S +=1;
   } else if (trial.lure.responsetext == values.responsekey_new){
    values.L2N +=1;    
   } else if ( trial.lure.response == 0){
    values.L2_NR += 1;
   };
  } else if (values.lurebin == "3"){
   if (trial.lure.responsetext == values.responsekey_old){
    values.L3O +=1;
   } else if (trial.lure.responsetext == values.responsekey_similar){
    values.L3S +=1;
   } else if (trial.lure.responsetext == values.responsekey_new){
    values.L3N +=1;    
   } else if ( trial.lure.response == 0){
    values.L3_NR += 1;
   };
  } else if (values.lurebin == "4"){
   if (trial.lure.responsetext == values.responsekey_old){
    values.L4O +=1;
   } else if (trial.lure.responsetext == values.responsekey_similar){
    values.L4S +=1;
   } else if (trial.lure.responsetext == values.responsekey_new){
    values.L4N +=1;    
   } else if ( trial.lure.response == 0){
    values.L4_NR += 1;
   };
  } else if (values.lurebin == "5"){
   if (trial.lure.responsetext == values.responsekey_old){
    values.L5O +=1;
   } else if (trial.lure.responsetext == values.responsekey_similar){
    values.L5S +=1;
   } else if (trial.lure.responsetext == values.responsekey_new){
    values.L5N +=1;    
   } else if ( trial.lure.response == 0){
    values.L5_NR += 1;
   };
  };
]
/trialduration = (parameters.stimulusduration + parameters.ISI)
/recorddata = true
/branch = [return trial.part2;]
</trial>

Thanks for the help!




> 1. When the RT of one trial is right at 2500 ms, the behavioural data we extracted showed "no response" for that particular trial, which is correct. But in the bdf (which is an EEG data file), we saw that in addition to no response trigger for that particular trial, the response trigger seemed to overlap with the following stimulus trigger of the next trial. So the order is: stimulus trigger A -> no response trigger -> A trigger that combines response trigger A and stimulus trigger B -> response trigger B.

There is no response trigger in trials where there is no response. If anything, what you are seeing must be an overlap of trial A's stimulus trigger (target-, lure-, or foilsignal) with trial B's stimulustrigger. While the stimulustrigger is erased at the end of a trial, that status change may be just too short for your equipment to pick up.

The solution here, is to actually send a trigger in case of no response per responsemessage, even if that trigger merely serves to lower any signal for a sufficiently long amount of time.

/ responsemessage = (0, allbitstolow, 50)

with

<port allbitstolow>
/ port = LPT1
/ subport = data
/ items = ("00000000")
/ erase = false
</port>

> 1. Is there a 50 ms buffer we can add to our code that can prevent any response that is <50 ms to send out a response trigger?

No. Moreover, it is doubtful that there actually was any trial with a response time < 50 ms. Do you have any Inquisit (not BDF) data file that actually shows such an RT?


To get clear separattion between triggers, I would try the following.

First, set all ports to not erase automatically at the end of a trial, we'll take care of manually lowering the lines when we want to. This is to prevent automatic status changes which may be too short to be effectively registered.

Stimulus trigger
//20 for Targetsignal
<port targetsignal>
/ port = LPT1
/ subport = data
/ items = ("00010100")
/ erase = false
</port>

//30 for luresignal
<port luresignal>
/ port = LPT1
/ subport = data
/ items = ("00011110")
/ erase = false
</port>

//40 for foilsignal
<port foilsignal>
/ port = LPT1
/ subport = data
/ items = ("00101000")
/ erase = false
</port>

Response Trigger
// 55
<port oldsignal>
/ port = LPT1
/ subport = data
/ items = ("00110111")
/ erase = false
</port>

//66 for similar trials
<port similarsignal>
/ port = LPT1
/ subport = data
/ items = ("01000010")
/ erase = false
</port>

//77 for new trials
<port newsignal>
/ port = LPT1
/ subport = data
/ items = ("01001101")
/ erase = false
</port>

// to set all lines to low
<port allbitstolow>
/ port = ("00000000")
/ port = LPT1
/ subport = data
/ erase = false
</port>


Now, in the trial elements, raise the stimulus trigger and then manually lower it after a short, but sufficiently long period of time. This is to minimize the risk of potential overlap with the response triggers. Something like

<trial target>
/ontrialbegin = [
values.stimulusselect = list.targets.nextvalue;
trial.target.insertstimulusframe(picture.target, 1);
trial.target.insertstimulustime(clearscreen, parameters.stimulusduration);
trial.target.insertstimulustime(port.targetsignal, 50);
    trial.target.insertstimulustime(port.allbitstolow, 100); // lower stimulus trigger after 50 ms
]

/stimulusframes = [1 = responsekeys_part2, targetsignal]
...
</trial>


Side note: In your code, I'm not sure why you are raising the target signal in the first frame per

/stimulusframes = [1 = responsekeys_part2, targetsignal]

and then inserting it again at a later point (50 ms) per insertstimulustime() here

/ontrialbegin = [
...
  trial.target.insertstimulustime(port.targetsignal, 50);
...
]

Doing either one or the other should be sufficient. There should be no reason to do both.

Now, if you want to prevent participants from submitting premature, extremely short responses you can for example add

/ isvalidresponse = [
    trial.target.latency >= 100;
]


With that in place, the trial simply will not accept any responses with latency below 100ms and no response trigger will go out if somebody manages to produce such a fast response (by mashing the response keys on the keyboard or the like).

Moving on. For the response triggers, I would recommend specifying a duration > 0 to ensure those triggers remain raised for a sufficiently long time, even if a response occurs very late in the trial, shortly before it times out.

/ responsemessage = (values.responsekey_old, oldsignal, 50)
/ responsemessage = (values.responsekey_similar, similarsignal, 50)
/ responsemessage = (values.responsekey_new, newsignal, 50)
/ responsemessage = (0, allbitstolow, 50)


As indicated before, defining a response trigger for "no response" is an option, though should not be strictly necessary in light of the next step. All trials move on to <trial part2> per a /branch, so in I would use <trial part2> to lower all lines to guarantee a clean slate before the next target, lure or foil trial begins. Something like

<trial Part2>
/ontrialbegin = [
    values.count_trials += 1;
    values.trialtype = list.part2.nextvalue;
    values.lurebin = 0;
]
/ stimulusframes = [1=allbitstolow]
/branch = [
    if (values.trialtype == 1 && parameters.selfpaced == false){
        return trial.target;
    } else if (values.trialtype == 2 && parameters.selfpaced == false){
        return trial.foil;
    } else if (values.trialtype == 3 && parameters.selfpaced == false){
        return trial.lure;
    } else if (values.trialtype == 1 && parameters.selfpaced == true){
        return trial.target_selfpaced;
    } else if (values.trialtype == 2 && parameters.selfpaced == true){
        return trial.foil_selfpaced;
    } else if (values.trialtype == 3 && parameters.selfpaced == true){
        return trial.lure_selfpaced;
    };
]
/trialduration = 50
/recorddata = false
</trial>


That should rule out most if not all scenarios where any cross-talk or overlap of triggers might occur.
By smo - 7/12/2022

Dave - 7/4/2022
Dave - 7/4/2022
smo - 7/4/2022
Hi Dave,

My apologies for the confusion! Here is a revised description.

The main problem we have is in the test phase, where participants have to indicate whether the picture they see on the screen is an old, similar, or new picture compared to the exposure phase, where they only judge whether the picture shows an indoor or outdoor item. There are three stimulus triggers and three response triggers in total in the test phase.

Stimulus triggers (called target, lure, and foil, respectively) are as follows.
<port targetsignal>
/ port = LPT1
/ subport = data
/ items = ("00010100")
</port>

<port luresignal>
/ port = LPT1
/ subport = data
/ items = ("00011110")
</port>

<port foilsignal>
/ port = LPT1
/ subport = data
/ items = ("00101000")
</port>

Response triggers (called old, similar, and new, respectively) are as follows.
<port oldsignal>
/ port = LPT1
/ subport = data
/ items = ("00110111")
</port>

<port similarsignal>
/ port = LPT1
/ subport = data
/ items = ("01000010")
</port>

<port newsignal>
/ port = LPT1
/ subport = data
/ items = ("01001101")
</port>

Each trial lasts 2500 ms. When a picture shows up on the screen, Inquisit sends out a stimulus trigger that corresponds to the type of picture (i.e. target, lure, or foil). When a participant makes a response, Inquisit sends out a response trigger that corresponds to the type of response people make (i.e. old, similar, or new). When participants make a response by 2500 ms, all triggers work well as we can see one stimulus trigger and one response trigger in each trial. However, when the responses were made right at 2500 ms, we saw two issues.

1. When the RT of one trial is right at 2500 ms, the behavioural data we extracted showed "no response" for that particular trial, which is correct. But in the bdf (which is an EEG data file), we saw that in addition to no response trigger for that particular trial, the response trigger seemed to overlap with the following stimulus trigger of the next trial. So the order is: stimulus trigger A -> no response trigger -> A trigger that combines response trigger A and stimulus trigger B -> response trigger B.

2. We also saw some trials have a RT of 50 ms, which is not a probable RT people could have. We suspect these could due to the slow RT, where a response triggers was sent out so late that it was counted into the next trial. For this case, we would like to disregard the <50 ms response trigger from the previous trial and record the actual response for the current trial.

We wonder:
1. Is there a way to disregard a 2500 ms response trigger and make sure there is always a stimulus trigger sent out when there is an overlap between stimulus and response trigger?
2. Is there a 50 ms buffer we can add to our code that can prevent any response that is <50 ms from being recorded in both behaviour and EEG data?

The following are the three trials in which stimulus and response triggers were added.
<trial target>
/ontrialbegin = [
  values.stimulusselect = list.targets.nextvalue;
  trial.target.insertstimulusframe(picture.target, 1);
  trial.target.insertstimulustime(clearscreen, parameters.stimulusduration);
  trial.target.insertstimulustime(port.targetsignal, 50)
]

/stimulusframes = [1 = responsekeys_part2, targetsignal]
/validresponse = (values.responsekey_old, values.responsekey_similar, values.responsekey_new)
/ correctresponse = (values.responsekey_old)
/ responsemessage = (values.responsekey_old, oldsignal, 0)
/ responsemessage = (values.responsekey_similar, similarsignal, 0)
/ responsemessage = (values.responsekey_new, newsignal, 0)

/beginresponseframe = 1
/responseinterrupt = frames

/ontrialend = [
  trial.target.resetstimulusframes();
  if (trial.target.responsetext == values.responsekey_old) {
   values.responseCategory = "old"; 
  } else if (trial.target.responsetext == values.responsekey_new) {
   values.responseCategory = "new"; 
  } else if (trial.target.responsetext == values.responsekey_similar) {
   values.responseCategory = "similar"; 
  } else if (trial.target.response == 0) {
   values.responseCategory = "";
   values.count_noresponses += 1;
  };

  values.stimulus = picture.target.currentitem;
 
  values.count_targets += 1;
  if (trial.target.response != 0) {
   values.count_targets_corr += 1;
   if (trial.target.correct) {
    values.count_oldtargets += 1;
   } else if (trial.target.responsetext == values.responsekey_similar) {
    values.count_simtargets += 1; 
   } else if (trial.target.responsetext == values.responsekey_new) {
    values.count_newtargets += 1  
   }; 
  };

]
/trialduration = (parameters.stimulusduration + parameters.ISI)
/recorddata = true
/branch = [return trial.part2;]
</trial>

Note:
* presents a foil for parameters.stimulusduration
* collects response during that time
* updates summary variables
* calls trial.part2
<trial foil>
/ontrialbegin = [
  values.stimulusselect = list.foils.nextvalue;
  trial.foil.insertstimulusframe(picture.foil, 1);    
  trial.foil.insertstimulustime(clearscreen, parameters.stimulusduration);
  trial.target.insertstimulustime(port.foilsignal, 50)
]

/stimulusframes = [1 = responsekeys_part2, foilsignal]
/validresponse = (values.responsekey_old, values.responsekey_similar, values.responsekey_new)
/ correctresponse = (values.responsekey_new)
/ responsemessage = (values.responsekey_old, oldsignal, 0)
/ responsemessage = (values.responsekey_similar, similarsignal, 0)
/ responsemessage = (values.responsekey_new, newsignal, 0)
/beginresponseframe = 1
/responseinterrupt = frames
/ontrialend = [
  trial.foil.resetstimulusframes();
 
  if (trial.foil.responsetext == values.responsekey_old) {
   values.responseCategory = "old";  
  } else if (trial.foil.responsetext == values.responsekey_new) {
   values.responseCategory = "new"; 
  } else if (trial.foil.responsetext == values.responsekey_similar) {
   values.responseCategory = "similar"; 
  } else if (trial.foil.response == 0) {
   values.responseCategory = "";
   values.count_noresponses += 1;
  };
 
  values.stimulus = picture.foil.currentitem;
 
  values.count_foils += 1;
  if (trial.foil.response != 0) {
   values.count_foils_corr += 1;
   if (trial.foil.correct) {
    values.count_newfoils += 1;
   } else if (trial.foil.responsetext == values.responsekey_old) {
    values.count_oldfoils += 1    
   } else if (trial.foil.responsetext == values.responsekey_similar) {
    values.count_simfoils += 1;     
   };  
  };
]
/trialduration = (parameters.stimulusduration + parameters.ISI)
/recorddata = true
/branch = [return trial.part2;]
</trial>

Note:
* presents a lure for parameters.stimulusduration
* collects response during that time
* updates summary variables
* calls trial.part2
<trial lure>
/ontrialbegin = [
  values.stimulusselect = list.lures.nextvalue; 
  values.lurebin = item.lurebins.item(values.stimulusselect); 
 
  if (values.lurebin == 1) {
   values.L1 += 1;  
  } else if (values.lurebin == 2) {
   values.L2 += 1;  
  } else if (values.lurebin == 3) {
   values.L3 += 1;  
  } else if (values.lurebin == 4) {
   values.L4 += 1;  
  } else if (values.lurebin == 5) {
   values.L5 += 1;  
  } else {
   values.lurebin = "NA";  
  };

  trial.lure.insertstimulusframe(picture.lure, 1);  
  trial.lure.insertstimulustime(clearscreen, parameters.stimulusduration);
  trial.target.insertstimulustime(port.luresignal, 50)
]

/stimulusframes = [1 = responsekeys_part2, luresignal]
/validresponse = (values.responsekey_old, values.responsekey_similar, values.responsekey_new)
/beginresponseframe = 1
/ correctresponse = (values.responsekey_similar)
/ responsemessage = (values.responsekey_similar, similarsignal, 0)
/ responsemessage = (values.responsekey_old, oldsignal, 0)
/ responsemessage = (values.responsekey_new, newsignal, 0)
/responseinterrupt = frames

/ontrialend = [
  trial.lure.resetstimulusframes();
 
  if (trial.lure.responsetext == values.responsekey_old) {
   values.responseCategory = "old";  
  } else if (trial.lure.responsetext == values.responsekey_new) {
   values.responseCategory = "new";  
  } if (trial.lure.responsetext == values.responsekey_similar) {
   values.responseCategory = "similar";  
  } else if (trial.lure.response == 0) {
   values.responseCategory = "";
   values.count_noresponses += 1;
  };
 
  values.stimulus = picture.lure.currentitem;
 
  values.count_lures += 1;
  if (trial.lure.response != 0) {
   values.count_lures_corr += 1;
   if (trial.lure.correct) {
    values.count_simlures += 1;
   } else if (trial.lure.responsetext == values.responsekey_old) {
    values.count_oldlures += 1;    
   } else if (trial.lure.responsetext == values.responsekey_new) {
    values.count_newlures += 1;    
   };  
  };

  if (values.lurebin == "1"){
   if (trial.lure.responsetext == values.responsekey_old){
    values.L1O +=1;
   } else if (trial.lure.responsetext == values.responsekey_similar){
    values.L1S +=1;
   } else if (trial.lure.responsetext == values.responsekey_new){
    values.L1N +=1;    
   } else if ( trial.lure.response == 0){
    values.L1_NR += 1;
   };
  } else if (values.lurebin == "2"){
   if (trial.lure.responsetext == values.responsekey_old){
    values.L2O +=1;
   } else if (trial.lure.responsetext == values.responsekey_similar){
    values.L2S +=1;
   } else if (trial.lure.responsetext == values.responsekey_new){
    values.L2N +=1;    
   } else if ( trial.lure.response == 0){
    values.L2_NR += 1;
   };
  } else if (values.lurebin == "3"){
   if (trial.lure.responsetext == values.responsekey_old){
    values.L3O +=1;
   } else if (trial.lure.responsetext == values.responsekey_similar){
    values.L3S +=1;
   } else if (trial.lure.responsetext == values.responsekey_new){
    values.L3N +=1;    
   } else if ( trial.lure.response == 0){
    values.L3_NR += 1;
   };
  } else if (values.lurebin == "4"){
   if (trial.lure.responsetext == values.responsekey_old){
    values.L4O +=1;
   } else if (trial.lure.responsetext == values.responsekey_similar){
    values.L4S +=1;
   } else if (trial.lure.responsetext == values.responsekey_new){
    values.L4N +=1;    
   } else if ( trial.lure.response == 0){
    values.L4_NR += 1;
   };
  } else if (values.lurebin == "5"){
   if (trial.lure.responsetext == values.responsekey_old){
    values.L5O +=1;
   } else if (trial.lure.responsetext == values.responsekey_similar){
    values.L5S +=1;
   } else if (trial.lure.responsetext == values.responsekey_new){
    values.L5N +=1;    
   } else if ( trial.lure.response == 0){
    values.L5_NR += 1;
   };
  };
]
/trialduration = (parameters.stimulusduration + parameters.ISI)
/recorddata = true
/branch = [return trial.part2;]
</trial>

Thanks for the help!




> 1. When the RT of one trial is right at 2500 ms, the behavioural data we extracted showed "no response" for that particular trial, which is correct. But in the bdf (which is an EEG data file), we saw that in addition to no response trigger for that particular trial, the response trigger seemed to overlap with the following stimulus trigger of the next trial. So the order is: stimulus trigger A -> no response trigger -> A trigger that combines response trigger A and stimulus trigger B -> response trigger B.

There is no response trigger in trials where there is no response. If anything, what you are seeing must be an overlap of trial A's stimulus trigger (target-, lure-, or foilsignal) with trial B's stimulustrigger. While the stimulustrigger is erased at the end of a trial, that status change may be just too short for your equipment to pick up.

The solution here, is to actually send a trigger in case of no response per responsemessage, even if that trigger merely serves to lower any signal for a sufficiently long amount of time.

/ responsemessage = (0, allbitstolow, 50)

with

<port allbitstolow>
/ port = LPT1
/ subport = data
/ items = ("00000000")
/ erase = false
</port>

> 1. Is there a 50 ms buffer we can add to our code that can prevent any response that is <50 ms to send out a response trigger?

No. Moreover, it is doubtful that there actually was any trial with a response time < 50 ms. Do you have any Inquisit (not BDF) data file that actually shows such an RT?


To get clear separattion between triggers, I would try the following.

First, set all ports to not erase automatically at the end of a trial, we'll take care of manually lowering the lines when we want to. This is to prevent automatic status changes which may be too short to be effectively registered.

Stimulus trigger
//20 for Targetsignal
<port targetsignal>
/ port = LPT1
/ subport = data
/ items = ("00010100")
/ erase = false
</port>

//30 for luresignal
<port luresignal>
/ port = LPT1
/ subport = data
/ items = ("00011110")
/ erase = false
</port>

//40 for foilsignal
<port foilsignal>
/ port = LPT1
/ subport = data
/ items = ("00101000")
/ erase = false
</port>

Response Trigger
// 55
<port oldsignal>
/ port = LPT1
/ subport = data
/ items = ("00110111")
/ erase = false
</port>

//66 for similar trials
<port similarsignal>
/ port = LPT1
/ subport = data
/ items = ("01000010")
/ erase = false
</port>

//77 for new trials
<port newsignal>
/ port = LPT1
/ subport = data
/ items = ("01001101")
/ erase = false
</port>

// to set all lines to low
<port allbitstolow>
/ port = ("00000000")
/ port = LPT1
/ subport = data
/ erase = false
</port>


Now, in the trial elements, raise the stimulus trigger and then manually lower it after a short, but sufficiently long period of time. This is to minimize the risk of potential overlap with the response triggers. Something like

<trial target>
/ontrialbegin = [
values.stimulusselect = list.targets.nextvalue;
trial.target.insertstimulusframe(picture.target, 1);
trial.target.insertstimulustime(clearscreen, parameters.stimulusduration);
trial.target.insertstimulustime(port.targetsignal, 50);
    trial.target.insertstimulustime(port.allbitstolow, 100); // lower stimulus trigger after 50 ms
]

/stimulusframes = [1 = responsekeys_part2, targetsignal]
...
</trial>


Side note: In your code, I'm not sure why you are raising the target signal in the first frame per

/stimulusframes = [1 = responsekeys_part2, targetsignal]

and then inserting it again at a later point (50 ms) per insertstimulustime() here

/ontrialbegin = [
...
  trial.target.insertstimulustime(port.targetsignal, 50);
...
]

Doing either one or the other should be sufficient. There should be no reason to do both.

Now, if you want to prevent participants from submitting premature, extremely short responses you can for example add

/ isvalidresponse = [
    trial.target.latency >= 100;
]


With that in place, the trial simply will not accept any responses with latency below 100ms and no response trigger will go out if somebody manages to produce such a fast response (by mashing the response keys on the keyboard or the like).

Moving on. For the response triggers, I would recommend specifying a duration > 0 to ensure those triggers remain raised for a sufficiently long time, even if a response occurs very late in the trial, shortly before it times out.

/ responsemessage = (values.responsekey_old, oldsignal, 50)
/ responsemessage = (values.responsekey_similar, similarsignal, 50)
/ responsemessage = (values.responsekey_new, newsignal, 50)
/ responsemessage = (0, allbitstolow, 50)


As indicated before, defining a response trigger for "no response" is an option, though should not be strictly necessary in light of the next step. All trials move on to <trial part2> per a /branch, so in I would use <trial part2> to lower all lines to guarantee a clean slate before the next target, lure or foil trial begins. Something like

<trial Part2>
/ontrialbegin = [
    values.count_trials += 1;
    values.trialtype = list.part2.nextvalue;
    values.lurebin = 0;
]
/ stimulusframes = [1=allbitstolow]
/branch = [
    if (values.trialtype == 1 && parameters.selfpaced == false){
        return trial.target;
    } else if (values.trialtype == 2 && parameters.selfpaced == false){
        return trial.foil;
    } else if (values.trialtype == 3 && parameters.selfpaced == false){
        return trial.lure;
    } else if (values.trialtype == 1 && parameters.selfpaced == true){
        return trial.target_selfpaced;
    } else if (values.trialtype == 2 && parameters.selfpaced == true){
        return trial.foil_selfpaced;
    } else if (values.trialtype == 3 && parameters.selfpaced == true){
        return trial.lure_selfpaced;
    };
]
/trialduration = 50
/recorddata = false
</trial>


That should rule out most if not all scenarios where any cross-talk or overlap of triggers might occur.

Thank you so much, Dave. This is very helpful!