Millisecond Forums

if statements for multiple ERP markers

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

By avtobin - 10/28/2015

Within a parametric n-back task, I'm trying to code an 'if' statement to send out a marker to the parallel port specific to the current level of n-back on trial begin (so I can record ERPs and differentiate later between n-back loads). So, I think I need the program to evaluate an if statement each trial to select markers 1, 2 or 3 for a correct response under conditions 1, 2, or 3-back, and similarly select makers 4, 5, or 6 for incorrect responses under conditions 1, 2 or 3-back. Within the script there are 3 types of trials: start responses, non-target responses and target responses. I've copied and pasted the script below - currently its only programmed to send out a marker '1' for incorrect responses and '2' for correct responses. New to coding and any help would be appreciated :)

DEFAULTS

requires Inquisit 4.0.0.0 or higher

<defaults>
/ lptaddresses = (lpt3 = 0xE800)
/minimumversion = "4.0.0.0"
/ screencolor = black
</defaults>
/canvasaspectratio = (4,3)

************************************************************************************************************************************************************************

************************************************************************************************************************************************************************
CUSTOM VALUES

*********************
editable parameters
*********************
/StartN = 2the starting N
!!!Note: if the starting N changes other changes may need to be made, e.g. instructions
/LastN = 4the last N run
!!!Note: if the last N changes, other changes may need to be made
/RepetitionPractice = 1Number of repretitions per level N during pactice (default for practice is 1)
/RepetitionTest = 3Number of repetitions per level N during testing (default for test is 3)
/debugmode = 0debugmode = 1: targetalerts are shown on screen, debugmode = 0, no targetalerts are shown (default)

<values>
/StartN = 1
/LastN = 3

/RepetitionTest = 3
/debugmode = 0
</values>

*********************
updated at runtime
*********************

/completed:0 = script was not completed (script was prematurely aborted); 1 = script was completed (all conditions run)

minus1:contains the stimulusitemnumber of the stimulus in the trial preceding the current one
minus2:contains the stimulusitemnumber of the stimulus shown 2 trials before the current one
minus3:contains the stimulusitemnumber of the stimulus shown 3 trials before the current one
minus4:contains the stimulusitemnumber of the stimulus shown 4 trials before the current one
stim:contains the current stimulusitem
stimnumber:contains the current stimulusitemnumber
N:the lag between a target and the stimulus it repeats
currenttarget:contains the stimulusnumber of the current target
(a target in N = 0 trials is a stimulus with the same stimulus number as stored in target0)
Hits:codes the number of correctly identifiying a target
FalseA:codes the number of times a participant identifies a non-target as a target
Misses:codes the number of times a participant misses to identify a target
CorrReject:codes the number of times a participant correctly identifies a non-target (and does nothing)
values.TotalHits:the number of total hits across all experimental blocks
values.TotalFA:the number of total false alarms across all experimental blocks
values.TotalBlocks:the total number of experimental blocks run
values.DV:dependent variable (DV) in Jaeggi et al (2010): the proportion of (TotalHits - TotalFA)/number of total blocks
starttrialcounter:keeps track of how many start trials have been run
repetitioncounter:keeps track of how many times an experimental block has been run

<values >
/completed = 0
/minus1 = 0
/minus2 = 0
/minus3 = 0

/N = 0
/currenttarget = 0
/Hits = 0
/FalseA = 0
/Misses = 0
/CorrReject = 0
/TotalHits = 0
/TotalFA = 0
/DV = 0
/TotalBlocks = 0
/starttrialcounter = 0
/repetitioncounter = 0
</values>

**************************ADDITIONAL N-LEVELS*************************************
* if additional N-levels are needed, create and add further "minusN" values and set them to 0,
Example: N = 5
/minus5 = 0

************************************************************************************************************************************************************************

************************************************************************************************************************************************************************
EXPRESSIONS

expressions.selectinstruct helps to select the adequate instructions for adaptive n-back testing

<expressions>
/selectinstruct = values.N + 1
</expressions>
************************************************************************************************************************************************************************

************************************************************************************************************************************************************************
DATA COLLECTION

this implementation suggests to collect the following information:
date:Date of Experiment
time:Time of Day
subject:Subjectnumber
values.N:the type of N-back trial
blockcode:the name of the current block
values.TotalBlocks:the total number of experimental blocks run
trialcode:the name of the current trial
stimulusitem:the file of the stimulus shown during a trial
stimulusnumber:the item number of the stimulus shown during a trial
values.currenttarget:the item number of the current target
response:the response of the participant
correct:the correctness of the response
latency:how fast a participant responded within the 3000ms timeframe, if at all
values.Hits:the sum of Hits in a block
values.FalseA:the sum of False Alarms in a block
values. Misses:the sum of Misses in a block
values.CorrReject:the sum of Correct Rejections in a block
values.TotalHits:the sum of total hits across all experimental blocks
values.TotalFA:the number of total false alarms across all experimental blocks
values.DV:the proportion of (TotalHits - TotalFA)/number of experimental blocks


*****************
raw data
*****************

<data>
/file = "SingleTaskNback_rawdata.iqdat"
/columns = [date, time, subject, values.N, blockcode, values.TotalBlocks, trialcode, trialnum, stimulusitem, stimulusnumber,
values.currenttarget, response, correct, latency,
values.Hits, values.FalseA, values.Misses, values.CorrReject,
values.TotalHits, values.TotalFA, values.DV]
/ separatefiles = true
</data>

*****************
summary data
*****************
script.startdate:date script was run
script.starttime:time script was started
script.subjectid:subject id number
script.groupid:group id number
script.elapsedtime:time it took to run script (in ms)
/completed:0 = script was not completed (script was prematurely aborted); 1 = script was completed (all conditions run)

values.TotalHits:the sum of total hits across all experimental blocks
values.TotalFA:the number of total false alarms across all experimental blocks
values.DV:the proportion of (TotalHits - TotalFA)/number of experimental blocks


<summarydata >
/file = "SingleTaskNback_summary.iqdat"
/columns = [script.startdate, script.starttime, script.subjectid, script.groupid, script.elapsedtime, values.completed,
values.TotalHits, values.TotalFA, values.DV]
</summarydata>


************************************************************************************************************************************************************************

************************************************************************************************************************************************************************
INSTRUCTIONS

***********INSTRUCTION SLIDES*****************************
*******CODE CHANGES:
If you would like to run different levels of N in practice/experimental trials, change/add the necessary instruction slides
as well as pay attention to the changes necessary under "Instruction Blocks"


* Slides 1-5 are ORIGINAL* instructions for N=2-4, kindly provided by Jaeggi et al. (*one minor change: use of SPACEBAR instead of anykey to advance)
<item Nback_startinstructions>
/1 = "SingleNbackInstructions_start alice.gif"
/2 = "SingleNbackInstructions_N1 alice.gif"
/3 = "SingleNbackInstructions_N2 alice.gif"
/4 = "SingleNbackInstructions_N3 alice.gif"

</item>

NOTE:
*the remaining items/instructions provided (for N=0, N=1) were modelled after them
-> "SingleNbackInstructions_N1 alice.gif"
-> "SingleNbackInstructions_practice012.gif"
-> "SingleNbackInstructions_practice123.gif"
-> "SingleNbackInstructions_practice0123.gif"


*original slide

</item>
NOTE:
*the remaining items/instructions provided (for N=0, N=1) were modelled after them:
-> "SingleNbackInstructions_practiceend0123.gif",
-> "SingleNbackInstructions_practiceend012.gif",
-> "SingleNbackInstructions_practiceend123.gif"


*slides to start experimental trials/end experiment
<item startendslides>
/1 = "StartExpt.gif"
/2 = "ThankYouSlide.gif"
</item>

*Instructions for individual experimental N-levels (not original)
<item expinstructions>
/1 = "SingleNbackInstructionsN1exp alice.gif"
/2 = "SingleNbackInstructionsN2exp alice.gif"
/3 = "SingleNbackInstructionsN3exp alice.gif"
/4 = "SingleNbackInstructionsN4exp alice.gif"
</item>




***********INSTRUCTION IMAGE SELECTION******************************************
<picture SingleNbackinstructions_start>
/ items = Nback_startinstructions
/ select = sequence
/ size = (100%, 100%)
</picture>


<picture StartExp_slide>
/ items = startendslides
/ select = 1
/ size = (100%, 100%)
</picture>

<picture EndExp_slide>
/ items = startendslides
/select = 2
/ size = (100%, 100%)
</picture>

*instructions for individual experimental trials are selected depending on level of N
<picture expinstructionslide>
/items = expinstructions
/select = expressions.selectinstruct
/size = (100%, 100%)
</picture>



***********INSTRUCTION TRIALS*******************************************
<trial Nbackinstruct_starttrial>
/ stimulusframes = [1 = SingleNbackinstructions_start]
/ validresponse = (57)
/ recorddata = false
</trial>


<trial StartExp_trial>
/ stimulusframes = [1 = StartExp_slide]
/ validresponse = (57)
/ recorddata = false
</trial>

<trial expinstructiontrial>
/ stimulusframes = [1 = expinstructionslide]
/ validresponse = (57)
/ recorddata = false
</trial>


*****stores TotalHits, TotalFA, and DV into datafile
<trial EndExp_trial>
/ stimulusframes = [1 = EndExp_slide]
/ validresponse = (57)
/ recorddata = false
</trial>

*************INSTRUCTION BLOCKS*************************************************************************************

ATTENTION: PRACTICE BLOCKS
(1) This block sets the beginning N value for practice trials (here: values.N = values.StartN)
(2) runs original instructions 1-5, for N=2-4, if more/fewer than three N examples are given adjust /trials = [1-X.....]
<block Nbackinstruct_start>
/ trials = [1-5 = Nbackinstruct_starttrial]
/ recorddata = false
/ onblockbegin = [values.N = values.StartN]
</block>


EXPERIMENTAL BLOCKS
(1) This block sets the starting value of N (here: values.N = values.StartN)
<block StartExp>
/ trials = [1 = StartExp_trial]
/ recorddata = false
/ onblockbegin = [
values.N = values.StartN;
values.TotalHits = 0;
values.TotalFA = 0;
values.TotalBlocks = 0;
values.DV = 0
]
</block>

<port EEGsignal>
/ port = lpt3
/ subport = data
/ items = ("00000001")
</port>

<port EEGsignal2>
/ port = lpt3
/ subport = data
/ items = ("00000010")
</port>

<port EEGsignaloff>
/ port = lpt3
/ subport = data
/ items = ("00000000")
</port>

<block EndExp>
/ trials = [1 = EndExp_trial]
</block>


************************************************************************************************************************************************************************

************************************************************************************************************************************************************************
SUMMARY PAGES

*A feedback page that is presented at the end of each practice block

<instruct >
/ fontstyle = ("Arial", 2.67%, false, false, false, false, 5, 0)
/ txcolor = (255, 255, 255)
/ screencolor = (0, 0, 0)
/ windowsize = (70%, 60%)
</instruct>


<page BlockSummary>
^^               FEEDBACK
^^
^^CORRECT: <% ((values.Hits + values.CorrReject) /20) * 100 %>% of the times
</page>


************************************************************************************************************************************************************************

************************************************************************************************************************************************************************
SHAPES
*yellow on black background
*original shapes, kindly provided by Jaeggi et al (2010)

<item shapes>
/ 1 = "no.1 alice.gif"
/ 2 = "no.2 alice.gif"
/ 3 = "no.3 alice.gif"
/ 4 = "no.4 alice.gif"
/ 5 = "no.5 alice.gif"
/ 6 = "no.6 alice.gif"
/ 7 = "no.7 alice.gif"
/ 8 = "no.8 alice.gif"

</item>
************************************************************************************************************************************************************************

************************************************************************************************************************************************************************
STIMULI-SELECTION

****List Variable to select current index of notargetvalue picture

*list.notargetvalue selects any of the 9 numbers but the one selected for targetvalue
<list notargetvalue>
/items = (1, 2, 3, 4, 5, 6, 7, 8)
/ not = (values.currenttarget)
/ replace = true
</list>

***randomly selects one of the shapes
<picture startshape>
/ items = shapes
/select = replace
/size = (40%, 40%)
</picture>

***selects any shape but the established target
<picture nontargetshape>
/ items = shapes
/ select = notargetvalue
/size = (40%, 40%)
</picture>

***selects the item with the same item number as the established target
<picture targetshape>
/items = shapes
/select = values.currenttarget
/size = (40%, 40%)
</picture>

************************************************************************************************************************************************************************

************************************************************************************************************************************************************************
FEEDBACK MESSAGES FOR PRACTICE TRIALS ONLY
<text ErrorFeedback>
/ items = ("ERROR")
/ fontstyle = ("Arial", 5.00%, true, false, false, false, 5, 0)
/ txcolor = (255, 0, 0)
/ txbgcolor = (0, 0, 0)
/ position = (50%, 70%)
</text>

<text CorrectFeedback>
/ items = ("CORRECT")
/ fontstyle = ("Arial", 5.00%, true, false, false, false, 5, 0)
/ txcolor = (0, 255, 0)
/ txbgcolor = (0, 0, 0)
/ position = (50%, 70%)
</text>

************************************************************************************************************************************************************************

************************************************************************************************************************************************************************
ASSISTANT STIMULI

*****acts as an eraser after showing the key stimuli for 500ms, staying on for the remainder of the 3000ms dedicated to each trial
<shape eraser>
/ shape = rectangle
/ size = (100%, 100%)
/ color = (0, 0, 0)
</shape>


*****Debug Code:
<text targetalert>
/items = ("target")
/position = (50%, 80%)
/txcolor = (black)
/txbgcolor = (black)
/ fontstyle = ("Arial", 3%, true, false, false, false, 5, 1)
</text>
************************************************************************************************************************************************************************

************************************************************************************************************************************************************************
TRIALS
*there are 3 types of trials
1. start: presented at beginning of block when number of trials too small for Target trials; they can present
any of the stimuli (N = 0, start trial presents the target shape)
2. nontarget:trials that present stimuli that do not repeat the stimulus of n-trials before
3. target:trials that present Target stimuli



*start trial runs N-times (unless N = 0, then it runs N = 1 time)
<trial start>
/ stimulustimes = [0 = startshape; 300 = eraser; 0 = EEGsignal; 20 = EEGsignaloff]
/ validresponse = (noresponse, 30)
/ correctresponse = (noresponse)
/ ontrialbegin = [
{if (values.N == 1) values.currenttarget = values.minus1};
{if (values.N == 2) values.currenttarget = values.minus2};
{if (values.N == 3) values.currenttarget = values.minus3};

values.starttrialcounter += 1;
]
/ ontrialend = [
{if (values.N == 0) values.currenttarget = picture.startshape.currentitemnumber};

values.minus3 = values.minus2;
values.minus2 = values.minus1;
values.minus1 = picture.startshape.currentitemnumber
]
/ responsetime = 0
/trialduration = 1750
/branch = [if (values.starttrialcounter < values.N) trial.start]
</trial>


<trial nontarget>
/ stimulustimes = [0 = nontargetshape; 300 = eraser; 0 = EEGsignal; 20 = EEGsignaloff]
/validresponse = (noresponse, 30)
/ correctresponse = (noresponse)
/ ontrialbegin = [
{if (values.N == 1) values.currenttarget = values.minus1};
{if (values.N == 2) values.currenttarget = values.minus2};
{if (values.N == 3) values.currenttarget = values.minus3};


]

/ ontrialend = [

values.minus3 = values.minus2;
values.minus2 = values.minus1;
values.minus1 = picture.nontargetshape.currentitemnumber;
values.CorrReject = values.CorrReject + trial.nontarget.correct;
values.FalseA = values.FalseA + trial.nontarget.error;
values.TotalFA = values.TotalFA + trial.nontarget.error;
values.DV = (values.TotalHits - values.TotalFA)/values.TotalBlocks;

]
/ responsetime = 0
/ trialduration = 1750
</trial>


**if target, press the letter "A" (code: 30)
<trial target>
/ stimulustimes = [0 = targetshape, targetalert; 300 = eraser; 0 = EEGsignal2; 20 = EEGsignaloff ]
/validresponse = (noresponse, 30)
/ correctresponse = (30)
/ ontrialbegin = [
{if (values.N == 1) values.currenttarget = values.minus1};
{if (values.N == 2) values.currenttarget = values.minus2};
{if (values.N == 3) values.currenttarget = values.minus3};

]

/ ontrialend = [

values.minus3 = values.minus2;
values.minus2 = values.minus1;
values.minus1 = picture.targetshape.currentitemnumber;
values.Hits = values.Hits+ trial.target.correct;
values.Misses = values.Misses + trial.target.error;
values.TotalHits = values.TotalHits + trial.target.correct;
values.DV = (values.TotalHits - values.TotalFA)/values.TotalBlocks;
]
/ responsetime = 0
/ trialduration = 1750
</trial>

********************************ADDITIONAL N-LEVELS*****************************************************

For each trial type:
(1) add {if (values.N == X) values.currenttarget = values.minusX};, e.g. N = 5
/ ontrialbegin = [
.....
{if (values.N == 1) values.currenttarget = values.minus1};
{if (values.N == 2) values.currenttarget = values.minus2};
{if (values.N == 3) values.currenttarget = values.minus3};
{if (values.N == 4) values.currenttarget = values.minus4};
=>{if (values.N == 5) values.currenttarget = values.minus5};
]
(2) add values.minusX = values.minus(X-1) e.g. N = 5 - largest N goes on top of the list
/ ontrialend = [
=>values.minus5 = values.minus4;
values.minus4 = values.minus3;
values.minus3 = values.minus2;
values.minus2 = values.minus1;
values.minus1 = picture.targetshape.currentitemnumber;
....
]

************************************************************************************************************************************************************************

************************************************************************************************************************************************************************

EXPERIMENTAL-BLOCKS

* Block starts with (a) Instructiontrial (b) N start-trials that cannot present Targets yet (no data collected) (c) 20 Experimental trials
* Experimental trials: ratio targets : nontargets = 6 : 14 = 3 : 7

<block s_ntask>
/ onblockbegin = [
values.currenttarget = 0; values.minus1 = 0; values.minus2 = 0; values.minus3 = 0;
values.Hits = 0; values.FalseA = 0; values.Misses = 0; values.CorrReject = 0;
values.TotalBlocks += 1;
values.starttrialcounter = 0;
values.repetitioncounter += 1;
]
/ trials = [1 = expinstructiontrial; 2 = start; 3 - 22 = noreplace(nontarget, nontarget, nontarget, nontarget, nontarget, nontarget, nontarget,
target, target, target)]
/ screencolor = (0, 0, 0)
/ branch = [if (values.N == values.LastN && values.repetitioncounter == values.RepetitionTest) {values.repetitioncounter = 0; block.EndExp}]
/ branch = [if (values.repetitioncounter < 3) block.s_ntask else { values.N += 1; values.repetitioncounter = 0; block.s_ntask}]
</block>

***********************************************ADDITIONAL N-LEVELS********************************************************
(1) add values.minusX = 0 to
/ onblockbegin = [
values.currenttarget = 0; values.minus1 = 0; values.minus2 = 0; values.minus3 = 0; values.minus4 = 0;
.....
]

Example: N = 5
/ onblockbegin = [
values.currenttarget = 0; values.minus1 = 0; values.minus2 = 0; values.minus3 = 0; values.minus4 = 0;
values.minus5 = 0;
.....
]

************************************************************************************************************************************************************************

************************************************************************************************************************************************************************
EXPERIMENT


*After running the initial instructions, participants work through practice blocks for N = 2 to N = 4
(initial N run can be altered under: INSTRUCTIONS -> INSTRUCTION BLOCKS)
* After practice, participants work through 3 blocks for each of the following level of N: N = 2, N = 3, N = 4
* if you want to run the Experiment with Target Alerts: use debug as your subject id
<expt>
/onexptbegin = [if (values.debugmode == 1) text.targetalert.textcolor = (red)]
/ blocks = [
1 = Nbackinstruct_start;
2 = StartExp;
3 = s_ntask
]
/onexptend = [values.completed = 1]
</expt>

************************************************************************************************************************************************************************
End of Script
************************************************************************************************************************************************************************
By Dave - 10/28/2015

Like any other stimulus element (<text>, <picture>, etc.), <port> elements can have multiple items. Simply enter the three items corresponding to your three N-levels and select the desired one according to the current N-level. There should be no need whatsoever for any additional conditional logic.

<port EEGsignal>
/ items = ("00000001", "00000010", "00000011")
/ select = values.N
...
</port>
By avtobin - 10/29/2015

Ok, thankyou for this suggestion. I did try something similar, and couldn't get the program to select the right signal according to the n-back level. I will
give this approach another try