Millisecond Forums

Dynamic Index based selection from a list

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

By Athanasia - 11/12/2020

Hello Dave!

According to a value (PSE number), which will be defined in the beginning of each experiment, I want to present only 6 out of 100 images, creating a unique set of 6 trials for each participant. The steps should be -15, -9, -3, +3, +9, and +15 from the PSE number. For example, if PSE is number 50, then the stimuli (pictures) presented to this participant will be Disgust_Fear_35/41/47/53/59/65.

Each picture Disgust_Fear_xx has two items (“a_Disgust_Fear_xx.bmp”, “b_Disgust_Fear_xx.bmp”). When picture Disgust_Fear_xx is presented as stimulus on a trial, the choice between a_Disgust_Fear_xx.bmp and b_Disgust_Fear_xx.bmp should be random.

I have tried to put all the picture elements in a list and select based on index, similar to what is proposed here  https://www.millisecond.com/forums/Topic13785.aspx

These are the relevant code parts:

<values>
/ primerPSE = 50
/ selectedImageNumber = 0
</values>

<picture Disgust_Fear_1>
/ items = ("28_Disgust_Fear_1.BMP","33_Disgust_Fear_1.BMP")
/ size = (100%,100%)
/ position = (50,50)
/ select = noreplace
</picture>

<picture Disgust_Fear_99>
/ items = ("28_Disgust_Fear_99.BMP","33_Disgust_Fear_99.BMP")
/ size = (100%,100%)
/ position = (50,50)
/ select = noreplace
</picture>

<list allPictures>
/items = ( picture.Disgust_Fear_1, picture.Disgust_Fear_2, picture.Disgust_Fear_3,… picture.Disgust_Fear_98, picture.Disgust_Fear_99)
</list>

<picture pic>
/ items = allPictures **
/ select = values.selectedImageNumber
</picture>

<trial minus15>
/ ontrialbegin = [
    trial.minus15.resetstimulusframes();
    values.selectedImageNumber = values.primerPSE - 15;
    ]
/ stimulustimes = [0 = Fixation; 1800 = pic; 2050 = Square; 2050 = Answer;]
/ pretrialpause = noreplace(750,1050,1350,1650,1950,2250,2550,2850)
/ beginresponsetime = 1800
/ response = timeout(2750)
/ validresponse = ("a", "l")
/ responseinterrupt = immediate
</trial>

The problem (denoted with ** above) is that I can’t put a list, or a picture element, as item of the picture pic.
I also tried to replace the list with an item element which will include the picture elements as items:

<item allPictures>
/ 1 = picture.Disgust_Fear_1

/ 99 = picture.Disgust_Fear_99
</item>

But I understand that this is also invalid syntax.

My very first approach was
/ stimulustimes = [0 = Fixation; 1800 = list.allPictures.item(values.selectedImageNumber); 2050 = Square; 2050 = Answer;],
but again, stimulustimes attribute does not work like that.

Another idea based on this topic https://www.millisecond.com/forums/Topic18863.aspx , is to create an item element with 200 items and then two lists of 100 like this:

<item allPictures>
/ 1 = "28_Disgust_Fear_1.BMP"                
...        
/ 99 = "28_Disgust_Fear_99.BMP"            
/ 100 = "33_Disgust_Fear_1.BMP"            
...
/ 198 = "33_Disgust_Fear_99.BMP"            
</item>        
    
<list PicSelectorallPictures_1>
/ items = (1,2,...,98,99)
/ select = values.selectedImageNumber
</list>

<list PicSelectorPictures_2>
/ items = (100,101,...197,198)
/ select = values.selectedImageNumber
</list>

<picture pic>
/ items = allPictures
/ select = noreplace(list.PicSelectorallPictures_1.item(values.selectedImageNumber),
       list.PicSelectorPictures_2.item(values.selectedImageNumber))
</picture>

<trial minus15>
/ ontrialbegin = [trial.minus15.resetstimulusframes();
    values.selectedImageNumber = values.primerPSE - 15;]
/ stimulustimes = [0 = Fixation; 1800 = pic; 2050 = Square; 2050 = Answer;]
/ pretrialpause = noreplace(750,1050,1350,1650,1950,2250,2550,2850)
/ beginresponsetime = 1800
/ response = timeout(2750)
/ validresponse = ("a", "l")
/ responseinterrupt = immediate
</trial>

but again, while the script is working, I don't have the picture I want.

Any other suggestions?

Thanks in advance for your help
By Dave - 11/12/2020

Athanasia - 11/12/2020
Hello Dave!

According to a value (PSE number), which will be defined in the beginning of each experiment, I want to present only 6 out of 100 images, creating a unique set of 6 trials for each participant. The steps should be -15, -9, -3, +3, +9, and +15 from the PSE number. For example, if PSE is number 50, then the stimuli (pictures) presented to this participant will be Disgust_Fear_35/41/47/53/59/65.

Each picture Disgust_Fear_xx has two items (“a_Disgust_Fear_xx.bmp”, “b_Disgust_Fear_xx.bmp”). When picture Disgust_Fear_xx is presented as stimulus on a trial, the choice between a_Disgust_Fear_xx.bmp and b_Disgust_Fear_xx.bmp should be random.

I have tried to put all the picture elements in a list and select based on index, similar to what is proposed here  https://www.millisecond.com/forums/Topic13785.aspx

These are the relevant code parts:

<values>
/ primerPSE = 50
/ selectedImageNumber = 0
</values>

<picture Disgust_Fear_1>
/ items = ("28_Disgust_Fear_1.BMP","33_Disgust_Fear_1.BMP")
/ size = (100%,100%)
/ position = (50,50)
/ select = noreplace
</picture>

<picture Disgust_Fear_99>
/ items = ("28_Disgust_Fear_99.BMP","33_Disgust_Fear_99.BMP")
/ size = (100%,100%)
/ position = (50,50)
/ select = noreplace
</picture>

<list allPictures>
/items = ( picture.Disgust_Fear_1, picture.Disgust_Fear_2, picture.Disgust_Fear_3,… picture.Disgust_Fear_98, picture.Disgust_Fear_99)
</list>

<picture pic>
/ items = allPictures **
/ select = values.selectedImageNumber
</picture>

<trial minus15>
/ ontrialbegin = [
    trial.minus15.resetstimulusframes();
    values.selectedImageNumber = values.primerPSE - 15;
    ]
/ stimulustimes = [0 = Fixation; 1800 = pic; 2050 = Square; 2050 = Answer;]
/ pretrialpause = noreplace(750,1050,1350,1650,1950,2250,2550,2850)
/ beginresponsetime = 1800
/ response = timeout(2750)
/ validresponse = ("a", "l")
/ responseinterrupt = immediate
</trial>

The problem (denoted with ** above) is that I can’t put a list, or a picture element, as item of the picture pic.
I also tried to replace the list with an item element which will include the picture elements as items:

<item allPictures>
/ 1 = picture.Disgust_Fear_1

/ 99 = picture.Disgust_Fear_99
</item>

But I understand that this is also invalid syntax.

My very first approach was
/ stimulustimes = [0 = Fixation; 1800 = list.allPictures.item(values.selectedImageNumber); 2050 = Square; 2050 = Answer;],
but again, stimulustimes attribute does not work like that.

Another idea based on this topic https://www.millisecond.com/forums/Topic18863.aspx , is to create an item element with 200 items and then two lists of 100 like this:

<item allPictures>
/ 1 = "28_Disgust_Fear_1.BMP"                
...        
/ 99 = "28_Disgust_Fear_99.BMP"            
/ 100 = "33_Disgust_Fear_1.BMP"            
...
/ 198 = "33_Disgust_Fear_99.BMP"            
</item>        
    
<list PicSelectorallPictures_1>
/ items = (1,2,...,98,99)
/ select = values.selectedImageNumber
</list>

<list PicSelectorPictures_2>
/ items = (100,101,...197,198)
/ select = values.selectedImageNumber
</list>

<picture pic>
/ items = allPictures
/ select = noreplace(list.PicSelectorallPictures_1.item(values.selectedImageNumber),
       list.PicSelectorPictures_2.item(values.selectedImageNumber))
</picture>

<trial minus15>
/ ontrialbegin = [trial.minus15.resetstimulusframes();
    values.selectedImageNumber = values.primerPSE - 15;]
/ stimulustimes = [0 = Fixation; 1800 = pic; 2050 = Square; 2050 = Answer;]
/ pretrialpause = noreplace(750,1050,1350,1650,1950,2250,2550,2850)
/ beginresponsetime = 1800
/ response = timeout(2750)
/ validresponse = ("a", "l")
/ responseinterrupt = immediate
</trial>

but again, while the script is working, I don't have the picture I want.

Any other suggestions?

Thanks in advance for your help

<list allPictures>
/items = ( picture.Disgust_Fear_1, picture.Disgust_Fear_2, picture.Disgust_Fear_3,… picture.Disgust_Fear_98, picture.Disgust_Fear_99)
/ selectionmode = values.selecteditemnumber
</list>

with

<trial minus15>
/ ontrialbegin = [
  trial.minus15.resetstimulusframes();
  values.selectedImageNumber = values.primerPSE - 15;
  trial.minus15.insertstimulustime(list.allPictures.nextvalue, 1800);
  ]
/ stimulustimes = [0 = Fixation; 1800 = pic; 2050 = Square; 2050 = Answer;]
/ pretrialpause = noreplace(750,1050,1350,1650,1950,2250,2550,2850)
/ beginresponsetime = 1800
/ response = timeout(2750)
/ validresponse = ("a", "l")
/ responseinterrupt = immediate
</trial>
By Dave - 11/12/2020

Dave - 11/12/2020
Athanasia - 11/12/2020
Hello Dave!

According to a value (PSE number), which will be defined in the beginning of each experiment, I want to present only 6 out of 100 images, creating a unique set of 6 trials for each participant. The steps should be -15, -9, -3, +3, +9, and +15 from the PSE number. For example, if PSE is number 50, then the stimuli (pictures) presented to this participant will be Disgust_Fear_35/41/47/53/59/65.

Each picture Disgust_Fear_xx has two items (“a_Disgust_Fear_xx.bmp”, “b_Disgust_Fear_xx.bmp”). When picture Disgust_Fear_xx is presented as stimulus on a trial, the choice between a_Disgust_Fear_xx.bmp and b_Disgust_Fear_xx.bmp should be random.

I have tried to put all the picture elements in a list and select based on index, similar to what is proposed here  https://www.millisecond.com/forums/Topic13785.aspx

These are the relevant code parts:

<values>
/ primerPSE = 50
/ selectedImageNumber = 0
</values>

<picture Disgust_Fear_1>
/ items = ("28_Disgust_Fear_1.BMP","33_Disgust_Fear_1.BMP")
/ size = (100%,100%)
/ position = (50,50)
/ select = noreplace
</picture>

<picture Disgust_Fear_99>
/ items = ("28_Disgust_Fear_99.BMP","33_Disgust_Fear_99.BMP")
/ size = (100%,100%)
/ position = (50,50)
/ select = noreplace
</picture>

<list allPictures>
/items = ( picture.Disgust_Fear_1, picture.Disgust_Fear_2, picture.Disgust_Fear_3,… picture.Disgust_Fear_98, picture.Disgust_Fear_99)
</list>

<picture pic>
/ items = allPictures **
/ select = values.selectedImageNumber
</picture>

<trial minus15>
/ ontrialbegin = [
    trial.minus15.resetstimulusframes();
    values.selectedImageNumber = values.primerPSE - 15;
    ]
/ stimulustimes = [0 = Fixation; 1800 = pic; 2050 = Square; 2050 = Answer;]
/ pretrialpause = noreplace(750,1050,1350,1650,1950,2250,2550,2850)
/ beginresponsetime = 1800
/ response = timeout(2750)
/ validresponse = ("a", "l")
/ responseinterrupt = immediate
</trial>

The problem (denoted with ** above) is that I can’t put a list, or a picture element, as item of the picture pic.
I also tried to replace the list with an item element which will include the picture elements as items:

<item allPictures>
/ 1 = picture.Disgust_Fear_1

/ 99 = picture.Disgust_Fear_99
</item>

But I understand that this is also invalid syntax.

My very first approach was
/ stimulustimes = [0 = Fixation; 1800 = list.allPictures.item(values.selectedImageNumber); 2050 = Square; 2050 = Answer;],
but again, stimulustimes attribute does not work like that.

Another idea based on this topic https://www.millisecond.com/forums/Topic18863.aspx , is to create an item element with 200 items and then two lists of 100 like this:

<item allPictures>
/ 1 = "28_Disgust_Fear_1.BMP"                
...        
/ 99 = "28_Disgust_Fear_99.BMP"            
/ 100 = "33_Disgust_Fear_1.BMP"            
...
/ 198 = "33_Disgust_Fear_99.BMP"            
</item>        
    
<list PicSelectorallPictures_1>
/ items = (1,2,...,98,99)
/ select = values.selectedImageNumber
</list>

<list PicSelectorPictures_2>
/ items = (100,101,...197,198)
/ select = values.selectedImageNumber
</list>

<picture pic>
/ items = allPictures
/ select = noreplace(list.PicSelectorallPictures_1.item(values.selectedImageNumber),
       list.PicSelectorPictures_2.item(values.selectedImageNumber))
</picture>

<trial minus15>
/ ontrialbegin = [trial.minus15.resetstimulusframes();
    values.selectedImageNumber = values.primerPSE - 15;]
/ stimulustimes = [0 = Fixation; 1800 = pic; 2050 = Square; 2050 = Answer;]
/ pretrialpause = noreplace(750,1050,1350,1650,1950,2250,2550,2850)
/ beginresponsetime = 1800
/ response = timeout(2750)
/ validresponse = ("a", "l")
/ responseinterrupt = immediate
</trial>

but again, while the script is working, I don't have the picture I want.

Any other suggestions?

Thanks in advance for your help

<list allPictures>
/items = ( picture.Disgust_Fear_1, picture.Disgust_Fear_2, picture.Disgust_Fear_3,… picture.Disgust_Fear_98, picture.Disgust_Fear_99)
/ selectionmode = values.selecteditemnumber
</list>

with

<trial minus15>
/ ontrialbegin = [
  trial.minus15.resetstimulusframes();
  values.selectedImageNumber = values.primerPSE - 15;
  trial.minus15.insertstimulustime(list.allPictures.nextvalue, 1800);
  ]
/ stimulustimes = [0 = Fixation; 1800 = pic; 2050 = Square; 2050 = Answer;]
/ pretrialpause = noreplace(750,1050,1350,1650,1950,2250,2550,2850)
/ beginresponsetime = 1800
/ response = timeout(2750)
/ validresponse = ("a", "l")
/ responseinterrupt = immediate
</trial>

Here's a simplified, self-contained example:

<values>
/ pse = 5
/ selectedtext = 0
</values>

<list alltexts>
/ items = (text.01, text.02, text.03, text.04, text.05, text.06, text.07, text.08, text.09, text.10)
/ selectionmode = values.selectedtext
</list>

<text 01>
/ items = ("01A", "01B")
</text>
<text 02>
/ items = ("02A", "02B")
</text>
<text 03>
/ items = ("03A", "03B")
</text>
<text 04>
/ items = ("04A", "04B")
</text>
<text 05>
/ items = ("05A", "05B")
</text>
<text 06>
/ items = ("06A", "06B")
</text>
<text 07>
/ items = ("07A", "07B")
</text>
<text 08>
/ items = ("08A", "08B")
</text>
<text 09>
/ items = ("09A", "09B")
</text>
<text 10>
/ items = ("10A", "101B")
</text>

<text fixation>
/ items = ("+")
</text>

// will yield text #3 with pse = 5
<trial minus2>
/ ontrialbegin = [
    trial.minus2.resetstimulusframes();
    values.selectedtext = values.pse - 2;
    trial.minus2.insertstimulustime(list.alltexts.nextvalue, 2000);
]
/ stimulusframes = [1=fixation]
/ validresponse = (57)
</trial>

// will yield text #8 with pse = 5
<trial plus3>
/ ontrialbegin = [
    trial.plus3.resetstimulusframes();
    values.selectedtext = values.pse + 3;
    trial.plus3.insertstimulustime(list.alltexts.nextvalue, 2000);
]
/ stimulusframes = [1=fixation]
/ validresponse = (57)
</trial>

<block example>
/ trials = [1-2 = noreplace(trial.minus2, trial.plus3)]
</block>


and

<values>
/ pse = 5
/ selectedtext = 0
</values>

<list alltexts>
/ items = (text.01, text.02, text.03, text.04, text.05, text.06, text.07, text.08, text.09, text.10)
/ selectionmode = values.selectedtext
</list>


<text 01>
/ items = ("01A", "01B")
</text>
<text 02>
/ items = ("02A", "02B")
</text>
<text 03>
/ items = ("03A", "03B")
</text>
<text 04>
/ items = ("04A", "04B")
</text>
<text 05>
/ items = ("05A", "05B")
</text>
<text 06>
/ items = ("06A", "06B")
</text>
<text 07>
/ items = ("07A", "07B")
</text>
<text 08>
/ items = ("08A", "08B")
</text>
<text 09>
/ items = ("09A", "09B")
</text>
<text 10>
/ items = ("10A", "101B")
</text>

<text fixation>
/ items = ("+")
</text>

<trial minus2>
/ ontrialbegin = [
    trial.minus2.resetstimulusframes();
    values.selectedtext = values.pse - 2;
]
/ stimulustimes = [0=fixation; 2000 = list.alltexts]
/ validresponse = (57)
</trial>

<trial plus3>
/ ontrialbegin = [
    trial.plus3.resetstimulusframes();
    values.selectedtext = values.pse + 3;
]
/ stimulustimes = [0=fixation; 2000 = list.alltexts]
/ validresponse = (57)
</trial>

<block example>
/ trials = [1-2 = noreplace(trial.minus2, trial.plus3)]
</block>


will work just the same. The point is using the value computed from PSE as the index into the <list> of stimulus objects (<text>s in the case of the above examples, <picture>s in your case; it works the same with either).
By Athanasia - 11/17/2020


Thank you Dave for your answer! It worked perfectly!

Another, thing I am struggling with is that there will be four ports (with 4 different odors) and I want each one of them to be coupled to one of the six trials creating 24 unique trials per block  (6 trials x 4 odors).
I created the ports as separate elements and then I tried to follow the logic above, by creating a list of ports, but again, I am missing something.

<port FearAA>
/ port = COM1
/ items = ("10101010")
</port>

<port FearGAGG>
/ port = COM2
/ items = ("10101000")
</port>

<port NeutralAA>
/ port = COM3
/ items = ("11101010")
</port>

<port NeutralGAGG>
/ port = COM4
/ items = ("10101110")
</port>

<list AllPorts>
/ items = (port.FearAA, port.FearGAGG, port.NeutralAA, port.NeutralGAGG)
/ selectionrate = trial
/ selectionmode = list.AllPorts.nextvalue
</list>

<trial minus15>

/ stimulustimes = [0 = timer; 3000 = list.AllPorts; 3000 = INHALE;…]

</trial>

<block Disgust_L_Fear_R>

/ trials = [1-24 = noreplace(minus15,minus9,minus3,plus3,plus9,plus15)]

</block>

Thank you again for all your help and quick replies!
By Dave - 11/17/2020

Athanasia - 11/17/2020

Thank you Dave for your answer! It worked perfectly!

Another, thing I am struggling with is that there will be four ports (with 4 different odors) and I want each one of them to be coupled to one of the six trials creating 24 unique trials per block  (6 trials x 4 odors).
I created the ports as separate elements and then I tried to follow the logic above, by creating a list of ports, but again, I am missing something.

<port FearAA>
/ port = COM1
/ items = ("10101010")
</port>

<port FearGAGG>
/ port = COM2
/ items = ("10101000")
</port>

<port NeutralAA>
/ port = COM3
/ items = ("11101010")
</port>

<port NeutralGAGG>
/ port = COM4
/ items = ("10101110")
</port>

<list AllPorts>
/ items = (port.FearAA, port.FearGAGG, port.NeutralAA, port.NeutralGAGG)
/ selectionrate = trial
/ selectionmode = list.AllPorts.nextvalue
</list>

<trial minus15>

/ stimulustimes = [0 = timer; 3000 = list.AllPorts; 3000 = INHALE;…]

</trial>

<block Disgust_L_Fear_R>

/ trials = [1-24 = noreplace(minus15,minus9,minus3,plus3,plus9,plus15)]

</block>

Thank you again for all your help and quick replies!

<list AllPorts>
/ items = (port.FearAA, port.FearGAGG, port.NeutralAA, port.NeutralGAGG)
/ selectionrate = trial
/ selectionmode = list.AllPorts.nextvalue
</list>

This is circular. You cannot have the list perform its selection based on itself. Moreover, the nextvalue isn't an item index, it's a <port> object and hence unsuitable as an index.

What you want is one <list> per trial type

<list minus15_odors>
 / items = (port.FearAA, port.FearGAGG, port.NeutralAA, port.NeutralGAGG)
</list>

<list minus9_odors>
/ items = (port.FearAA, port.FearGAGG, port.NeutralAA, port.NeutralGAGG)
</list>

<list minus3_odors>
/ items = (port.FearAA, port.FearGAGG, port.NeutralAA, port.NeutralGAGG)
</list>

<list plus3_odors>
/ items = (port.FearAA, port.FearGAGG, port.NeutralAA, port.NeutralGAGG)
</list>

<list plus9_odors>
/ items = (port.FearAA, port.FearGAGG, port.NeutralAA, port.NeutralGAGG)
</list>

<list plus15_odors>
/ items = (port.FearAA, port.FearGAGG, port.NeutralAA, port.NeutralGAGG)
</list>

and then sample port objects from that list in the applicable trial:

<trial minus15>
/ ontrialbegin = [trial.minus15.resetstimulusframes();
trial.minus15.insertstimulustime(list.minus15_odors.nextvalue, 3000);
]
/ stimulustimes = [0 = timer; 3000 = INHALE;…]

</trial>

<trial minus9>
/ ontrialbegin = [trial.minus9.resetstimulusframes();
trial.minus15.insertstimulustime(list.minus9_odors.nextvalue, 3000);
]
/ stimulustimes = [0 = timer; 3000 = INHALE;…]

</trial>

...

By Athanasia - 11/17/2020


Thank you so much, for one more time! It works exactly as I want!