Millisecond Forums

Creating list or vector with numerical values & getting n-th element out of this list

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

By Olga Kunina - 11/26/2009


Hi everyone,


I am trying
to expand the source code for the IOWA-Gambling task available at the Inquisit
website. In this version the loss-values are selected randomly as follows:


 <expressions>


/ getlossdeck1
= noreplace(0, 0, 0, 0, 0, 150, 200, 250, 300, 350) 


</expressions>


By contrast,
I want to define a fixed sequence of loss values for loss values for each trail.
I want to choose the current value depending on how many cards were already
taken from the deck. Speaking more technically - I want to get the nth element
out of an array, vector or list with numerical values.


Therefore I
am trying to define something like a list or a vector with loss values (integer
values) for each trail.


 / loss_deck1
= (0, 0, 0, 0, 0, 150, 200, 250, 300, 350) 


 Since that
did not work I have defined a counter


 <counter
deck1_loss>


/ items = (0,
0, 0, 0, 0, 150, 200, 250, 300, 350)


/ select = sequence(1-10)


</counter>


 Additionally,
I have introduced a variable "values.cards_deck1" that counts how
often deck1 was chosen. This counter is updated in each trial.


In the last
step I try to define the loss value for the current trial as:


/ getlossdeck1
= getitem(counter.deck1_loss.items, values.cards_deck1)


But each
time I get the error message "Expression is not valid. Item not found".


Does
someone have an idea whether it is possible to create a list or vector with
numerical values & get back a specific element out of this list?


Thanks a
lot for your help in advance.


Best regards, 


Olga Kunina

By Dave - 11/26/2009

Hmm, glancing over the code you posted, I think


/ getlossdeck1
= getitem(counter.deck1_loss.items, values.cards_deck1)


should be changed to a /ontrialend or /ontrialbegin expression:


<values>
/ getlossdeck1 = 0
[...]
</values>


and then


<trial sometrial>
/ ontrialbegin = [values.getlossdeck1=getitem(counter.deck1_loss, values.cards_deck1]
[...]
</trial>


If that doesn't do the trick, you might want to attach your script to this thread (-> see 'Options' tab when posting a reply).


~Dave

By Olga Kunina - 11/26/2009

Hi Dave,


 thank you
very much for your quick answer.  I have
followed your suggestions and changed my code as follows:


 <trial
igtfeedback>


   / ontrialbegin
= [ if (trial.igt.response == "deck1") { [..]


    values.loss
= getitem(counter.deck1_loss, values.cards_deck1); [..] }]


 </trial>


 Unfortunately
it does not work. It seems to be a problem with the expression "getitem(counter.deck1_loss,
values.cards_deck1)".


 I have
uploaded the script. Thanks a lot for taking time to answer the questions,


Best regards,


Olga

By Dave - 11/26/2009

 Unfortunately
it does not work. It seems to be a problem with the expression "getitem(counter.deck1_loss,
values.cards_deck1)".


What exactly isn't working?

By Dave - 11/26/2009

Okay, I had a quick look at your script and compared it to the original IGT script available from millisecond.com. Well, if all you want is a fixed sequence of losses for each deck, there's a much easier way to pull this off. In the original script, losses are randomly determined by the following expressions:


<expressions>
/ getlossdeck1 = noreplace(0, 0, 0, 0, 0, 0, 0, 0, 0, 1250)
/ getlossdeck2 = noreplace(0, 0, 0, 0, 0, 150, 200, 250, 300, 350)
/ getlossdeck3 = noreplace(0, 0, 0, 0, 0, 0, 50, 50, 50, 50)
/ getlossdeck4 = noreplace(0, 0, 0, 0, 0, 0, 0, 0, 0, 250)
</expressions>


Each time the subject selects e.g. deck1, a random value is returned from expressions.getlossdeck1 (without replacement). Now, if you want to switch that behavior to a predictable, fixed sequence in which certain amounts of losses should occur, you may simply define:


<expressions>
/ getlossdeck1 = sequence(0, 0, 0, 0, 0, 0, 0, 0, 0, 1250)
/ getlossdeck2 = sequence(0, 0, 0, 0, 0, 150, 200, 250, 300, 350)
/ getlossdeck3 = sequence(0, 0, 0, 0, 0, 0, 50, 50, 50, 50)
/ getlossdeck4 = sequence(0, 0, 0, 0, 0, 0, 0, 0, 0, 250)
</expressions>


I.e.only when the subject selects deck1 for the tenth time, a loss of 1250 will occur. No further changes are necessary as you can see from the attached script.


Let me know if that helps,


~Dave

By Olga Kunina - 11/26/2009

Dear Dave,


thank you so much for your help. That is indeed a very simple soultion for this probelm. [:D]


However, we are developing a new card risking task and there it would be helpful to be able to get the n-th element of a counter. Unfortunatelly there are not many examples for the usage of the function getitem in the documentation .




getitem(counter.deck, 1)

getitem(text.presenteditems, text.presenteditems.itemcount)

getitem(item.useritems, item.useritems.itemcount - 1)


Can you tell me how one would have to define "counter.deck", "text.presenteditems", or "item.useritems" so that this function is executed regularely?


Kind regards,


Olga



By Dave - 11/27/2009

Can you tell me how one would have to define "counter.deck", "text.presenteditems", or "item.useritems" so that this function is executed regularely?


Hmm, I don't think there's much more too it. Let's do this by way of an example. Suppose you have defined a counter element:


<counter fruit>
/ items = ("apple", "banana", "cherry", "damson", "elderberry")
[...]
</counter>


Now, suppose you want to retrieve the third item from the counter, i.e. "cherry", with the getitem function. You can use that function either by way of the <expressions> element


<expressions>
/ getcherry = getitem(counter.fruit, 3)
[...]
</expressions>


or by way of Inquisit's event attributes ('/ onexptbegin', '/ onexptend', '/ onblockbegin', '/ onblockend', '/ ontrialbegin', '/ ontrialend') available at the <expt>, <block> and <trial> level


<trial getcherry>
/ ontrialbegin = [text.favoritefruit.item.1 = getitem(counter.fruit, 3)]
/ stimulusframes = [favoritefruit]
[...]
</trial>

<text favoritefruit>
[...]
</text>


and do all sorts of things with it, e.g. write it to a <text> element or to a <values> entry. Note that the item index number, i.e. the second argument of the getitem function  ( 3 for "cherry") may also be a variable. So you might as well define another <values> entry (or use anything that returns a valid numerical value) and use it as the functions argument:


<values>
/ cherryindex = 3
[...]
</values>


<expressions>

/ getcherry = getitem(counter.fruit, values.cherryindex)

[...]

</expressions>


Best wishes from a fellow Inquisit user,


~Dave

By Olga Kunina - 11/27/2009

Dear Dave,


thanks for these examples and your answers. They were very helpfull. [:)]


Have a good weekend. With best wishes,


Olga

By Dave - 11/27/2009

You're welcome. BTW, if you're into risk-taking card tasks, definitely check out the Columbia Card Task script available from the Inquisit Task Library.


Cheers,


~Dave

By fasteddie9141 - 10/7/2014

Dave

I know I'm dredging this from the mists of time but I am also trying to do a linear sequence with the iowa gambling task from the web scripts.

I have used the sequence command to select a fixed loss value and modified other elements of the script so that it only shows one value for loss gain over the card

Its 90% there but I cannot get the getlossdeck sequence to step together so that it doesn't step back when users select a different response.

i.e if they keep hitting deck A the cards are in correct sequence but if they change from deck to deck it does the decks in order but not so the sixth card in A leads to the 7th in B etc

Is there a simple way of explaining your example of counters so that I can get the existing code to step in time so to speak 

I have some code you can look at to see the modifications I've made if it would help

J
By Dave - 10/8/2014

Assuming you did something like

<expressions>
/ getlossdeck1 = sequence(0, 0, 0, 0, 0, 0, 0, 0, 0, 1250)
/ getlossdeck2 = sequence(0, 0, 0, 0, 0, 150, 200, 250, 300, 350)
/ getlossdeck3 = sequence(0, 0, 0, 0, 0, 0, 50, 50, 50, 50)
/ getlossdeck4 = sequence(0, 0, 0, 0, 0, 0, 0, 0, 0, 250)
</expressions>

there is no reason why the decks should be "in sync". If e.g. "deck 1" is selected
<trial igt>
...
/ ontrialend = [ if (trial.igt.response == "deck1") {... ; values.loss=expressions.getlossdeck1; ...}]
...
</trial>

A single sample is retrieved from expressions.getlossdeck1. The remaining expressions are (supposed to be) wholly unaffected -- no samples are retrieved.

The quickest, but somewhat hack-ish, way to change that is to retrieve a sample from *every* expression regardless of the deck chosen:

<trial igt>
...
/ ontrialend = [ if (trial.igt.response == "deck1") {... ; values.loss=expressions.getlossdeck1; expressions.getlossdeck2; expressions.getlossdeck3; expressions.getlossdeck4;...}]
/ ontrialend = [ if (trial.igt.response == "deck2") {... ; values.loss=expressions.getlossdeck2; expressions.getlossdeck1; expressions.getlossdeck3; expressions.getlossdeck4;...}]
...
</trial>
By fasteddie9141 - 10/8/2014

Thanks for this I will give it a hack so to speak

Apologies for doubling up with PM
By Dave - 10/8/2014

No problem. Let me know how it goes!