Placing images randomly without collision and retrieving the position of one image dynamically


Placing images randomly without collision and retrieving the position...
Author
Message
patruvius
patruvius
Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)
Group: Forum Members
Posts: 57, Visits: 1

I have tried to modify a script posted by Dave on this topic and despite using the list element and the counter element have not been able to find a solution.


Using the counter I get overlap of images despite my use of the not operator so possibly some simple error on my behalf - script below.


Using the list element I can get flawless displays, but cannot find out how to determine where the X image is placed on each iteration, so that I can use that to attach a target image in the second phase of the trial.


Counter Script:


<defaults>
/ screencolor = (0,0,0)
/ fontstyle = ("Arial", 20pt)
</defaults>

<block myblock>
/ trials = [1=mytrial]
</block>

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 Trial presents one type 1 stimulus and four type 2 stimuli
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

<trial mytrial>
/ stimulustimes = [1= fixation,pic1,pic2,pic3,pic4,xpos]
/ validresponse = (anyresponse)
/ ontrialend = [reset(counter.type1xpos,counter.type1ypos,counter.type2xpos,counter.type2ypos,counter.type3xpos,counter.type3ypos,counter.type4xpos,counter.type4ypos)]
</trial>

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 There will 16 possible displays for a 2x2 matric with 4 different images
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
<text fixation>
/ items = ("+")
/ color = white
/ txbgcolor = (0,0,0)
/ fontstyle = ("Arial", 30pt)
/ erase = false
</text>
<picture pic1>
/items= ("letter X.png")
/ vposition = counter.type1xpos.selectedvalue
/ hposition = counter.type1ypos.selectedvalue
</picture>
<picture pic2>
/items= ("letter H.png")
/ vposition = counter.type2xpos.selectedvalue
/ hposition = counter.type2ypos.selectedvalue
</picture>
<picture pic3>
/items= ("letter I.png")
/ vposition = counter.type3xpos.selectedvalue
/ hposition = counter.type3ypos.selectedvalue
</picture>
<picture pic4>
/items= ("letter T.png")
/ vposition = counter.type4xpos.selectedvalue
/ hposition = counter.type4ypos.selectedvalue
</picture>


+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 Four candidate positions for pic1 stimulus (25% & 75%)

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

<counter type1xpos>
/ items = (25%,25%,75%,75%)
/ select = noreplace
</counter>
<counter type1ypos>
/ items = (25%,25%,75%,75%)
/ select = noreplace
</counter>

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 Candidate positions for pic2 stimuli (all positions but *not* the
 one already chosen for pic1  stimulus)
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

<counter type2xpos>
/ items = (25%,25%,75%,75%)
/ not = (type1xpos)
/ select = noreplace
/ selectionrate = always
</counter>
<counter type2ypos>
/ items = (25%,25%,75%,75%)
/ not = (type1ypos)
/ select = noreplace
/ selectionrate = always
</counter>
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 Candidate positions for pic3 stimuli (all positions but *not* the
 ones already chosen for pic1 or pic2 stimulus)
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

<counter type3xpos>
/ items = (25%,25%,75%,75%)
/ not = (type1xpos,type2xpos)
/ select = noreplace
/ selectionrate = always
</counter>
<counter type3ypos>
/ items = (25%,25%,75%,75%)
/ not = (type1ypos,type2ypos)
/ select = noreplace
/ selectionrate = always
</counter>
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 Candidate positions for pic3 stimuli (all positions but *not* the
 ones already chosen for pic1, pic2 or pic3 stimulus)
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

<counter type4xpos>
/ items = (25%,25%,75%,75%)
/ not = (type1xpos,type2xpos,type3xpos)
/ select = noreplace
/ selectionrate = always
</counter>
<counter type4ypos>
/ items = (25%,25%,75%,75%)
/ not = (type1ypos,type2ypos,type3ypos)
/ select = noreplace
/ selectionrate = always
</counter>
***********************
debug message
*************************

<text xpos>
/ items= (" X hposition = <% picture.pic1.hposition %> and vpos is <% picture.pic1.vposition %>")

</text>


List controlled counter


<defaults>
/ screencolor = (0, 0, 0)
/ fontstyle = ("Arial", 20pt)
</defaults>
***************************
Display Items
****************************
<text fixation>
/ items = ("+")
/ color = white
/ txbgcolor = (0,0,0)
/ fontstyle = ("Arial", 30pt)
/ erase = false
</text>

<item fourdistractors >
/1 = "letter X.png"
/1 = "letter H.png"
/2 = "letter I.png"
/3 = "letter T.png"
</item>
<picture fourd01>
/items = fourdistractors
/select = fourd01counter
/position = (25%,25%)
/erase = true(black)
/transparentcolor = (black)
</picture>

<picture fourd02>
/items = fourdistractors
/select = fourd02counter
/position = (25%,75%)
/erase = true(black)
/transparentcolor = (black)
</picture>

<picture fourd03>
/items = fourdistractors
/select = fourd03counter
/position = (75%,25%)
/erase = true(black)
/transparentcolor = (black)
</picture>

<picture fourd04>
/items = fourdistractors
/select = fourd04counter
/position = (75%,75%)
/erase = true(black)
/transparentcolor = (black)
</picture> 

***********************
Counters for 4 distractors
***********************
<list fourd01counter>
/items = (1,2,3,4)
</list>

<list fourd02counter>
/items = (1,2,3,4)
/not = (fourd01counter)
</list>

<list fourd03counter>
/items = (1,2,3,4)
/not = (list.fourd01counter.nextvalue, list.fourd02counter.nextvalue)
</list>

<list fourd04counter>
/items = (1,2,3,4)
/not = (list.fourd01counter.nextvalue, list.fourd02counter.nextvalue,list.fourd03counter.nextvalue)
/ selectionrate = trial
</list>

*************************
Trials
****************************
<trial displayone>
/ stimulustimes = [0=fixation; 500=fourd01,fourd02,fourd03,fourd04]
/ timeout= 3500
</trial>


*******************************
Blocks
********************************
<block jayblockone>
/ trials = [1=displayone]
/ bgstim = (fixation)
</block>




****************************
Experiment
****************************

<expt>

/ blocks = [1=jayblockone]

</expt>
********************************
debugging messages
********************************


With thanks,


Patrick


patruvius
patruvius
Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)
Group: Forum Members
Posts: 57, Visits: 1

Actually, belatedly, I  think I understand, why the not operation fails.


It is operating on the  x,y co-ordinates separately, hence not pic1 x coordinate if it was 25% will only allow 75% in the grid and so on. I suppose the x,y combined coordinate is what must be unique for each picture, but I still cannot work out how that can be done.


Perhaps use the position parameter with an enclosed expression. I'll try that ,,,,


Dave
Dave
Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)
Group: Administrators
Posts: 13K, Visits: 103K

It is operating on the  x,y co-ordinates separately, hence not pic1 x coordinate if it was 25% will only allow 75% in the grid and so on. I suppose the x,y combined coordinate is what must be unique for each pictur


Yes.


but I still cannot work out how that can be done


You'll want to define a dependency between the respective x and y counters *and* make the values unique:


<counter type1xpos>
/ items = (25.0000%,25.0001%,75.0000%,75.0001%)
/ select = noreplace
</counter>


<counter type1ypos>
/ items = (25.0000%,75.0000%,25.0000%,75.0000%)
/ select = current(type1xpos)
</counter>


etc.


patruvius
patruvius
Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)
Group: Forum Members
Posts: 57, Visits: 1

Thank you for this Dave, but I am going to need a bit more guidance if  you have the time.


I have tried to implement your suggestion here but still get clashes so I am obviously not making the selection unique.


I have tried to understand the select current (countername) but the documented example of presidents and vice-presidents did not help as I cannot see how that works without seeing the item list.


In my case if the current x coordinate selected is 25.001 then a choice of any of the others seems possible.


Reading the documentation on the /not property has not helped me either.


Your comment of defining dependency and making unique values seemed clear and a guiding light for me, but implementing seemed as difficult as understanding recursion.


Any other tips gratefully received.


Latest relevant code:


+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 Candidate positions for pic2 stimuli (all positions but *not* the
 one already chosen for pic1  stimulus)
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

<counter type2xpos>
/ items = (25.0000%,25.0001%,25.0002,75.0000%,75.0001%,75.0002%)
/ not = (type1xpos,type1ypos)
/ select = noreplace
/ selectionrate = always
</counter>
<counter type2ypos>
/ items = (25.0000%,75.0000%,25.0000%,75.0000%,25.0000%,75.0000%)
/ not = (type1ypos,type1xpos)
/ select = current(type2xpos)
/ selectionrate = always
</counter>


BTW when the display of the current position of X is created, sometimes the x co-ordinate may be something like 25.00000000000000097344445555.


How does that work?



With great appreciation for your help as always.



Patrick


Dave
Dave
Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)
Group: Administrators
Posts: 13K, Visits: 103K

<counter type2xpos>
/ items = (25.0000%,25.0001%,25.0002,75.0000%,75.0001%,75.0002%)
/ not = (type1xpos,type1ypos)
/ select = noreplace
/ selectionrate = always
</counter>
<counter type2ypos>
/ items = (25.0000%,75.0000%,25.0000%,75.0000%,25.0000%,75.0000%)
/ not = (type1ypos,type1xpos)
/ select = current(type2xpos)
/ selectionrate = always
</count


Patrick,


note the differences between your previous example and your current code. The above counters effectively contain the same position multiple times, so of course things will clash.



BTW when the display of the current position of X is created, sometimes the x co-ordinate may be something like 25.00000000000000097344445555.


How does that work?



Computers have no concept of real (in the mathematical sense) numbers. They deal in binary. Floating point representations of reals are thus subject to rounding error and imprecision.


patruvius
patruvius
Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)
Group: Forum Members
Posts: 57, Visits: 1

Thanks again Dave.


I feel you are teaching the village idiot how to fish rather than throwing him a fish and I appreciate this.


I assume you indicate with the red text that these are the redundant entries.  I just don't see what you mean by the same position multiple times.


If I give my narrative of how I understand it to work, you may see where my thinking is awry.


Using your hints, my current code runs correctly over ten tests for just two of the images, however as soon as I extend it to three pictures collisions abound.


<counter type1xpos>
/ items = (25.0000%,25.0001%,75.0000%,75.0001%)
/ select = noreplace
</counter>
<counter type1ypos>
/ items = (25.0000%,75.0000%,25.0000%,75.0000%)
/ select = current(type1xpos)
</counter>

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 Candidate positions for pic2 stimuli (all positions but *not* the
 one already chosen for pic1  stimulus)
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

<counter type2xpos>
/ items = (25.0001%,25.0001%,75.0001%,75.0001%)
/ not = (type1xpos,type1ypos)
/ select = noreplace
/ selectionrate = always
</counter>
<counter type2ypos>
/ items = (75.0000%,75.0000%,25.0000%,25.0000%)
/ not = (type1ypos,type1xpos)
/ select = current(type2xpos)
/ selectionrate = always
</counter>


CORRECTION: Testing again, there were collisions.


If I just leave the items  in red, not understanding why they don't create the same position  multiple times, I get collisions even more frequently.


I am wandering blind and just throwing my line in without really knowing how to bait the hook as I am simply not getting this basic concept of creating unique positions.


 I have tried introducing new positions to strive for 'different' positions, eg 25.0003 and 25.0004 etc., but this doesn't appear to work either.


Also I am not getting how the select = current(type2xpos) works.


When I look at the example in the documentation,


<text vicepresidents>
/ items =
vicepresidentitems
/ select = current(presidents)
</text>


The following first selects Jefferson, then Adams, and then Washington:


<text presidents>
/ items = ("George Washington",
"John Adams", "Thomas Jefferson")
/ select = sequence(3, 2,
1)
</text>


my understanding is that the vicepresidentitems would look something like:


<text vicepresidents>


<items = ( "Adams", "Jefferson","Burr")


</text>


Hence at first choice, current(presidents) returns 3, this then is the selection from vicepresidentlist, #3 -  Burr ?


So extending this to picking a vposition after choosing a hposition, if say 25.001 was chosen at the second position, then


/select = current(type2xpos), looks for the second choice in the list, say 75% in the above example, ignoring for the moment the red text.


Is that correct?


I can't rationally proceed until I know if I am on the right track with this or totally lost at sea.


Any life lines handy Dave?


Patrick


(Thanks for the explanation on the floating  point representations, that made sense.)


patruvius
patruvius
Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)
Group: Forum Members
Posts: 57, Visits: 1

Late Press:


This code produced no collisions over 20 tests:


<counter type2xpos>
/ items = (25.0001%,25.0001%,75.0001%,75.0001%)
/ not = (type1xpos,type1ypos)
/ select = noreplace
/ selectionrate = always
</counter>
<counter type2ypos>
/ items = (75.0000%,25.0000%)
/ not = (type1ypos,type1xpos)
/ select = current(type2xpos)
/ selectionrate = always
</counter>


However, extending what I thought I had "seen" to the third image co-ordinates resulted in multiple collisions again. :-(


Dave
Dave
Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)
Group: Administrators
Posts: 13K, Visits: 103K

Here's a short, fully functional snippet that should hopefully be helpful. It's just a straightforward extension of the original example script to two dimensions (x and y coordinates instead of x coordinates only):


<block myblock>
/ trials = [1-4=mytrial]
</block>

<trial mytrial>
/ pretrialpause = 500
/ stimulusframes =  [1=type1,type2a,type2b,type2c]
/ validresponse = (57)
/ ontrialend = [reset(counter.type2xpos)]
</trial>

<text type1>
/ items = ("Type 1")
/ hposition = counter.type1xpos.selectedvalue
/ vposition = counter.type1ypos.selectedvalue
</text>

<text type2a>
/ items = ("Type 2a")
/ hposition = counter.type2xpos.selectedvalue
/ vposition = counter.type2ypos.selectedvalue
</text>

<text type2b>
/ items = ("Type 2b")
/ hposition = counter.type2xpos.selectedvalue
/ vposition = counter.type2ypos.selectedvalue
</text>

<text type2c>
/ items = ("Type 2c")
/ hposition = counter.type2xpos.selectedvalue
/ vposition = counter.type2ypos.selectedvalue
</text>

<counter type1xpos>
/ items = (25.0000%, 25.0001%, 75.0000%, 75.0001%)
/ select = noreplace
/ selectionrate = trial
</counter>

<counter type1ypos>
/ items = (25.0000%, 75.0000%, 25.0000%, 75.0000%)
/ select = current(type1xpos)
</counter>

<counter type2xpos>
/ items = (25.0000%, 25.0001%, 75.0000%, 75.0001%)
/ select = noreplace
/ not = (type1xpos)
/ selectionrate = always
</counter>

<counter type2ypos>
/ items = (25.0000%, 75.0000%, 25.0000%, 75.0000%)
/ select = current(type2xpos)
</counter>


patruvius
patruvius
Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)Guru (5K reputation)
Group: Forum Members
Posts: 57, Visits: 1

Thank you so much Dave. Of course it works perfectly for my situation. Sorry I was so  obtuse about getting to grips with the principles here. If you were British, I would recommend you for a knight hood.


Patrick


Dave
Dave
Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)
Group: Administrators
Posts: 13K, Visits: 103K

Sorry I was so  obtuse about getting to grips with the principles here.


Absolutely no need to be sorry. I wish I could have made what I meant clearer from the get-go, but I couldn't quite put my finger on where the actual problem / misunderstanding was (I'm still not sure, really). Anyway, if you need me to elaborate on anything, let me know.


If you were British, I would recommend you for a knight hood.


That would mean I'd have to rescue maidens and slay dragons in the process, wouldn't it? Thanks, but I'll give this a pass. I'm not good with swords... :-)


Cheers,


~Dave


GO

Merge Selected

Merge into selected topic...



Merge into merge target...



Merge into a specific topic ID...




Reading This Topic

Explore
Messages
Mentions
Search