Libet Clock


Author
Message
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: 104K
WARNING: A proper implementation should look something along the following lines. BUT: Since I don't have your stimuli, etc. I cannot test this.

<values>
/completed = 0
/intervalestimation = 0
/currentlistnumber = 0
</values>

<values>
/onset = 0
</values>

<values>
/sound = 0
</values>

<values>
/keep_rotating_for_n_trials = 0
/rotationcount = 0
/beep = 5
</values>

<list targetduration>
/items = (100, 200, 300, 400, 500, 600, 700, 800, 900)
/replace = false
</list>

<list targetdurationh>
/items = (100, 400, 700)
/poolsize = 42
/replace = false
</list>

<list targetdurations>
/items = (100, 400, 700)
/poolsize = 42
/replace = false
</list>

<list libetframes>
/selectionmode = sequence
/ selectionrate = always
/poolsize = 24
</list>

*******************************************************************************************************************
*******************************************************************************************************************
STIMULI
*******************************************************************************************************************
*******************************************************************************************************************

**********
Clock
**********

<item libetclock>
/1 = "Libet_clock1.jpg"
/2 = "Libet_clock2.jpg"
/3 = "Libet_clock3.jpg"
/4 = "Libet_clock4.jpg"
/5 = "Libet_clock5.jpg"
/6 = "Libet_clock6.jpg"
/7 = "Libet_clock7.jpg"
/8 = "Libet_clock8.jpg"
/9 = "Libet_clock9.jpg"
/10 = "Libet_clock10.jpg"
/11 = "Libet_clock11.jpg"
/12 = "Libet_clock12.jpg"
/13 = "Libet_clock13.jpg"
/14 = "Libet_clock14.jpg"
/15 = "Libet_clock15.jpg"
/16 = "Libet_clock16.jpg"
/17 = "Libet_clock17.jpg"
/18 = "Libet_clock18.jpg"
/19 = "Libet_clock19.jpg"
/20 = "Libet_clock20.jpg"
/21 = "Libet_clock21.jpg"
/22 = "Libet_clock22.jpg"
/23 = "Libet_clock23.jpg"
/24 = "Libet_clock24.jpg"
</item>

<picture libetclock>
/items = libetclock
/position = (50, 50)
/select = values.c1item
/erase = false
</picture>

**********
Sounds
**********

<item possounds>
/1 = "FemCheer.wav"
/2 = "FemLaugh.wav"
/3 = "MaleCheer.wav"
/4 = "MaleLaugh.wav"
</item>

<sound possounds>
/items = possounds
/playthrough = true
</sound>

**********
Extra stimuli:
**********

<text cross>
/items = ("+")
/color = (0,0,0)
</text>

*******************************************************************************************************************
*******************************************************************************************************************
TRIALS
*******************************************************************************************************************
*******************************************************************************************************************
<values>
/c1item = 1
/c2item = 1
/c3item = 1
/c4item = 1
/c5item = 1
</values>

<picture clock1>
/ items = libetclock
/ select = values.c1item
/ erase = false
</picture>

<picture clock2>
/ items = libetclock
/ select = values.c2item
/ erase = false
</picture>

<picture clock3>
/ items = libetclock
/ select = values.c3item
/ erase = false
</picture>

<picture clock4>
/ items = libetclock
/ select = values.c4item
/ erase = false
</picture>

<picture clock5>
/ items = libetclock
/ select = values.c5item
/ erase = false
</picture>

*********
Libet trials - Positive sounds
*********
<trial positive>
/ontrialbegin = [{values.c1item = list.libetframes.nextindex}]
/ontrialbegin = [values.keep_rotating_for_n_trials = round(rand(20,50)); values.rotationcount = 0]
/stimulustimes = [0 = cross; 500 = libetclock]
/correctresponse = (" ")
/pretrialpause = 500
/trialduration = 1050
/branch = [trial.LibetP]
/recorddata = false
</trial>

<trial LibetP>
/ontrialbegin = [values.c1item = list.libetframes.nextindex]
/stimulustimes = [1 = libetclock]
/correctresponse = (57)
/trialduration = 50
/branch = [if (trial.LibetP.response == 57) {trial.rotateP} else {trial.LibetP}]
/recorddata = false
/ontrialend = [values.sound = sound.possounds.currentitem]
/ontrialend = [values.onset = values.c1item]
</trial>

<trial RotateP>
/ontrialbegin = [values.rotationcount += 1; values.c1item = list.libetframes.nextindex]
/stimulustimes = [1 = libetclock]
/validresponse = (0)
/trialduration = 50
/ branch = [if (values.rotatecount == values.beep) trial.AudioP]
/branch = [if (values.rotationcount < values.keep_rotating_for_n_trials) trial.rotateP else trial.postlibetp]
/recorddata = false
</trial>

<trial AudioP>
/ ontrialbegin = [values.c1item = list.libetframes.nextindex; values.c2item = list.libetframes.nextindex; values.c3item = list.libetframes.nextindex; values.c4item = list.libetframes.nextindex; values.c5item = list.libetframes.nextindex; values.c5item = list.libetframes.nextindex; ]
/ ontrialend = [values.rotationcount += 6]
/ stimulustimes = [0 = possounds, clock1; 50 = clock2; 100 = clock3; 150 = clock4; 200 = clock5]
/ validresponse = (0)
/ trialduration = 250
/ branch = [if (values.rotationcount < values.keep_rotating_for_n_trials) trial.rotateP else trial.postlibetP]
</trial>

<trial postLibetP>
/stimulustimes = [1 = cross]
/trialduration = 500
/branch = [surveypage.tep]
/recorddata = false
</trial>

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: 104K
NOTE: I accidentally deleted your last post. Sorry about that. My response to that now missing post is below:

> 1 - The trial stops around half-way through sound, instead.

Then your trial is not long enough. You've set it to 250ms. If your sounds are longer than that, you need to extend it.

> 2 - Multiple sounds (or trials) are now played in succession, randomly between 4-7, before the whole sequence transitions to
> postLibetP.

The 2nd /branch is wrong

<trial RotateP>
/ontrialbegin = [values.rotationcount += 1; values.c1item = list.libetframes.nextindex]
/stimulustimes = [1 = libetclock]
/validresponse = (0)
/trialduration = 50
/branch = [if (values.rotationcount == values.beep) trial.AudioP]
/branch = [if (values.rotationcount < values.keep_rotating_for_n_trials) {trial.AudioP} else {trial.RotateP}]
/recorddata = false
</trial>

and will invoke <trial AudioP> repeatedly. Note that in the example I gave you, the /branch reads differently:

<trial RotateP>
/ontrialbegin = [values.rotationcount += 1; values.c1item = list.libetframes.nextindex]
/stimulustimes = [1 = libetclock]
/validresponse = (0)
/trialduration = 50
/ branch = [if (values.rotatecount == values.beep) trial.AudioP]
/branch = [if (values.rotationcount < values.keep_rotating_for_n_trials) trial.rotateP else trial.postlibetp]
/recorddata = false
</trial>                               

Psych_Josh
Psych_Josh
Guru (11K reputation)Guru (11K reputation)Guru (11K reputation)Guru (11K reputation)Guru (11K reputation)Guru (11K reputation)Guru (11K reputation)Guru (11K reputation)Guru (11K reputation)
Group: Forum Members
Posts: 85, Visits: 397
Hi Dave,

No worries. I apologise - I actually meant to say the dot, not the trial, stops half-way through the sound. The sound will play, the dot continues briefly, but stops before the sound ends.

On noticing the second error, I tried that exact same fix myself, but alas this didn't fix either of the errors I mentioned previously.

Sorry for taking up so much of your time on this!
Josh
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: 104K
> I actually meant to say the dot, not the trial, stops half-way through the sound.

Comes down to not quite the same, but a similar thing:
- The trial is too short. Make it as long as your sound lasts plus a little bit.
- Increase the number of clock faces you display during the trial. If your sound lasts, say, 400ms, you need to set up additional clock face stimuli and display them via /stimulustimes just like the ones that are already there.

> On noticing the second error, I tried that exact same fix myself, but alas this didn't fix either of the errors I mentioned previously.

I'm having trouble believing that (no offense intended).

<trial RotateP>
/ontrialbegin = [values.rotationcount += 1; values.c1item = list.libetframes.nextindex]
/stimulustimes = [1 = libetclock]
/validresponse = (0)
/trialduration = 50
/ branch = [if (values.rotatecount == values.beep) trial.AudioP]
/branch = [if (values.rotationcount < values.keep_rotating_for_n_trials) trial.rotateP else trial.postlibetp]
/recorddata = false
</trial> 

The first /branch will invoke <trial AudioP> if -- and only if -- the rotationcount is equal to values.beep (i.e., the chosen delay).

<trial AudioP>
/ ontrialend = [values.rotationcount += 6]
...
/ branch = [if (values.rotationcount < values.keep_rotating_for_n_trials) trial.rotateP else trial.postlibetP]
</trial>

<trial AudioP> displays the sound and then goes back to trial.rotateP if -- and only if -- the randomly chosen amount of post-response-rotations has not been completed yet. Critically, <trial AudioP> increases the rotation count by the number of clock faces displayed during <trial AudioP>. That means when <trial rotateP> is invoked again

<trial RotateP>
/ontrialbegin = [values.rotationcount += 1; values.c1item = list.libetframes.nextindex]
/stimulustimes = [1 = libetclock]
/validresponse = (0)
/trialduration = 50
/ branch = [if (values.rotatecount == values.beep) trial.AudioP]
/branch = [if (values.rotationcount < values.keep_rotating_for_n_trials) trial.rotateP else trial.postlibetp]
/recorddata = false
</trial>

the 1st /branch *cannot* fire again. The rotation count is not equal to values.beep anymore. Instead the 2nd /branch applies, i.e., <trial rotateP> is looped until the selected amount of post-response-rotations is reached. Once it has been reached, <trial postlibetP> is invoked.

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: 104K
If you are still stuck, do the following: Put the current revision of your script as well as all the other files it requires (images, sound files) in a ZIP archive and attach it to this thread. I can then fix the remaining issues (there shouldn't be many) for you.

Psych_Josh
Psych_Josh
Guru (11K reputation)Guru (11K reputation)Guru (11K reputation)Guru (11K reputation)Guru (11K reputation)Guru (11K reputation)Guru (11K reputation)Guru (11K reputation)Guru (11K reputation)
Group: Forum Members
Posts: 85, Visits: 397
Hi Dave,

Sorry - I was mistaken, I thought you had put:
/branch = [if (values.rotationcount < values.keep_rotating_for_n_trials) {trial.AudioP} else {trial.RotateP}]

as the solution, not the issue causing the problem. The multiple sounds issue has been resolved, thank you!

I have doubled the amount of clockfaces as a test, their required values, and entered them as /stimulus times, but a strange effect occurs:
The sound is still played at the same point it was anyway before the additional clockfaces, and the dot rapidly moves to, and stops at, the top-most clockface point (where 0/60 would be), before reversing back to where it was previously when the sound was played, and then carrying on forward for the remaining time. 

I have attached the script - thanks a lot for your time - I confess this current task was, in hindsight, probably beyond my current Inquisit ability.
Thanks again,
Josh
Attachments
Study 3.zip (381 views, 2.00 MB)
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: 104K
> I have doubled the amount of clockfaces as a test, their required values, and entered them as /stimulus times

Yes, but you are not actually setting those values:

<trial AudioP>
/ ontrialbegin = [values.c1item = list.libetframes.nextindex; values.c2item = list.libetframes.nextindex; values.c3item = list.libetframes.nextindex; values.c4item = list.libetframes.nextindex; values.c5item = list.libetframes.nextindex]
/ ontrialend = [values.rotationcount += 6]
...
</trial>

You stop with values.c5item (i.e., the 5th clock face). You have forgotten to set values.c6item to values.c10item -- which are responsible for displaying the proper 6th to 10th clock face in the trial. You've also forgotten to adjust the rotationcount increase accordingly. To sum up:

<trial AudioP>
/ ontrialbegin = [values.c1item = list.libetframes.nextindex;
    values.c2item = list.libetframes.nextindex;
    values.c3item = list.libetframes.nextindex;
    values.c4item = list.libetframes.nextindex;
    values.c5item = list.libetframes.nextindex;
    values.c6item = list.libetframes.nextindex;
    values.c7item = list.libetframes.nextindex;
    values.c8item = list.libetframes.nextindex;
    values.c9item = list.libetframes.nextindex;
    values.c10item = list.libetframes.nextindex;
    ]
/ ontrialend = [values.rotationcount += 10]
/ stimulustimes = [0 = possounds, clock1; 50 = clock2; 100 = clock3; 150 = clock4; 200 = clock5; 250 = clock6; 300 = clock7; 350 = clock8; 400 = clock9; 450 = clock10]
/ validresponse = (0)
/ trialduration = 500
/ branch = [if (values.rotationcount < values.keep_rotating_for_n_trials) {trial.rotateP} else {trial.postlibetP}]
</trial>

is what the <trial> ought to look like.

Beyond that, the AudioP trial is *still* too short to accommodate some of your sounds: They are *longer* than 500ms (see e.g. "FemLaugh.wav" which lasts close to a second). You either need to extend the <trial> further or allow it to terminate the sound early by setting

<sound possounds>
/items = possounds
/playthrough = false
</sound>


Psych_Josh
Psych_Josh
Guru (11K reputation)Guru (11K reputation)Guru (11K reputation)Guru (11K reputation)Guru (11K reputation)Guru (11K reputation)Guru (11K reputation)Guru (11K reputation)Guru (11K reputation)
Group: Forum Members
Posts: 85, Visits: 397
Thanks Dave - I thought I'd doubled checked everything, but thanks for pointing that out.

Somehow, with the update, there is a still a minor pause when the sound and clockface of the first trial commence - when I say minor, it's very small, but I imagine would still be perceptible to participants.
Also, despite checking for errors within the /stimulustimes, there is an additional minor pause within the longer sounds. I've pasted the updated script beneath:

<values>
/c1item = 1
/c2item = 1
/c3item = 1
/c4item = 1
/c5item = 1
/c6item = 1
/c7item = 1
/c8item = 1
/c9item = 1
/c10item = 1
/c11item = 1
/c12item = 1
/c13item = 1
/c14item = 1
/c15item = 1
/c16item = 1
/c17item = 1
/c18item = 1
/c19item = 1
/c20item = 1
</values>

<picture clock1>
/items = libetclock
/select = values.c1item
/erase = false
</picture>

<picture clock2>
/items = libetclock
/select = values.c2item
/erase = false
</picture>

<picture clock3>
/items = libetclock
/select = values.c3item
/erase = false
</picture>

<picture clock4>
/items = libetclock
/select = values.c4item
/erase = false
</picture>

<picture clock5>
/items = libetclock
/select = values.c5item
/erase = false
</picture>

<picture clock6>
/items = libetclock
/select = values.c6item
/erase = false
</picture>

<picture clock7>
/items = libetclock
/select = values.c7item
/erase = false
</picture>

<picture clock8>
/items = libetclock
/select = values.c8item
/erase = false
</picture>

<picture clock9>
/items = libetclock
/select = values.c9item
/erase = false
</picture>

<picture clock10>
/items = libetclock
/select = values.c10item
/erase = false
</picture>

<picture clock11>
/items = libetclock
/select = values.c11item
/erase = false
</picture>

<picture clock12>
/items = libetclock
/select = values.c12item
/erase = false
</picture>

<picture clock13>
/items = libetclock
/select = values.c13item
/erase = false
</picture>

<picture clock14>
/items = libetclock
/select = values.c14item
/erase = false
</picture>

<picture clock15>
/items = libetclock
/select = values.c15item
/erase = false
</picture>

<picture clock16>
/items = libetclock
/select = values.c16item
/erase = false
</picture>

<picture clock17>
/items = libetclock
/select = values.c17item
/erase = false
</picture>

<picture clock18>
/items = libetclock
/select = values.c18item
/erase = false
</picture>

<picture clock19>
/items = libetclock
/select = values.c19item
/erase = false
</picture>

<picture clock20>
/items = libetclock
/select = values.c20item
/erase = false
</picture>

*********
Libet trials - Positive sounds
*********
<trial positive>
/ontrialbegin = [{values.c1item = list.libetframes.nextvalue}]
/ontrialbegin = [values.keep_rotating_for_n_trials = round(rand(35,70)); values.rotationcount = 0]
/stimulustimes = [0 = cross; 500 = libetclock]
/correctresponse = (" ")
/pretrialpause = 500
/trialduration = 1050
/branch = [trial.LibetP]
/recorddata = false
</trial>

<trial LibetP>
/ontrialbegin = [values.c1item = list.libetframes.nextindex]
/stimulustimes = [1 = libetclock]
/correctresponse = (57)
/trialduration = 50
/branch = [if (trial.LibetP.response == 57) {trial.rotateP} else {trial.LibetP}]
/recorddata = false
/ontrialend = [values.sound = sound.possounds.currentitem]
/ontrialend = [values.onset = values.c1item]
</trial>

<trial RotateP>
/ontrialbegin = [values.rotationcount += 1; values.c1item = list.libetframes.nextindex]
/stimulustimes = [1 = libetclock]
/validresponse = (0)
/trialduration = 50
/branch = [if (values.rotationcount == values.beep) trial.AudioP]
/branch = [if (values.rotationcount < values.keep_rotating_for_n_trials) {trial.rotateP} else {trial.postLibetP}]
/recorddata = false
</trial>

<trial AudioP>
/ontrialbegin = [values.c1item = list.libetframes.nextindex; values.c2item = list.libetframes.nextindex; values.c3item = list.libetframes.nextindex; values.c4item = list.libetframes.nextindex; values.c5item = list.libetframes.nextindex; values.c6item = list.libetframes.nextindex; values.c7item = list.libetframes.nextindex; values.c8item = list.libetframes.nextindex; values.c9item = list.libetframes.nextindex; values.c10item = list.libetframes.nextindex; values.c11item = list.libetframes.nextindex; values.c12item = list.libetframes.nextindex; values.c13item = list.libetframes.nextindex; values.c14item = list.libetframes.nextindex; values.c15item = list.libetframes.nextindex; values.c16item = list.libetframes.nextindex; values.c17item = list.libetframes.nextindex; values.c18item = list.libetframes.nextindex; values.c19item = list.libetframes.nextindex; values.c20item = list.libetframes.nextindex]
/ontrialend = [values.rotationcount += 20]
/stimulustimes = [0 = possounds, clock1; 50 = clock2; 100 = clock3; 150 = clock4; 200 = clock5; 250 = clock6; 300 = clock7; 350 = clock8; 400 = clock9; 450 = clock10; 500 = clock11; 550 = clock12; 600 = clock13; 650 = clock14; 700 = clock15; 750 = clock16; 800 = clock17; 850 = clock18; 900 = clock19; 950 = clock20]
/validresponse = (0)
/trialduration = 500
/branch = [if (values.rotationcount < values.keep_rotating_for_n_trials) {trial.rotateP} else {trial.postlibetP}]
</trial>

<trial postLibetP>
/stimulustimes = [1 = cross]
/trialduration = 500
/branch = [surveypage.tep]
/recorddata = false
</trial>

Again, thanks for your assistance.
Josh
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: 104K
> Somehow, with the update, there is a still a minor pause when the sound and clockface of the first trial commence - when I say minor, it's
> very small, but I imagine would still be perceptible to participants.

Your audio hardware has some level of startup latency; how much that is will vary from system to system. In addition, Inquisit must actually load the sound at the beginning of the trial before it can instruct your system to actually play it; that's a pretty quick process, but it's not instantaneous either. Both factors combined (hardware latency moreso than Inquisit) lead to the minor pause.

> Also, despite checking for errors within the /stimulustimes, there is an additional minor pause within the longer sounds.

Is perfectly in line with the above. Longer sounds take longer to load.

Usually one would define a sufficiently long /pretrialpause, which Inquisit would use to prepare stimuli *before* the actual stimulus presentation sequence starts. That, however, will not eliminate your audio hardware's startup latency.

/pretrialpause is also not an option within your script, because that would further interrupt the continuous display of clock faces -- Inquisit cannot display or change stimuli during a /pretrialpause (that would be antithetical to a /pretrialpause's purpose: prepare stimuli *before* displaying them).

Long story short: I unfortunately don't see a way to completely eliminate the pause. You can minimize it by keeping the sounds as short as possible and using fast audio hardware.

In addition, you should pay attention to your display's refresh rate. To be able to even reasonably achieve the timings you want, you'll probably want to run this using displays that support a 100Hz refresh rate (i.e., a 10ms display re-draw cycle).

Psych_Josh
Psych_Josh
Guru (11K reputation)Guru (11K reputation)Guru (11K reputation)Guru (11K reputation)Guru (11K reputation)Guru (11K reputation)Guru (11K reputation)Guru (11K reputation)Guru (11K reputation)
Group: Forum Members
Posts: 85, Visits: 397
Hi Dave,

Thanks for the information and your help - I'll take your advice on board and try to use a solution that doesn't inhibit the desired mechanics of the study.

Thanks again,
Josh
GO

Merge Selected

Merge into selected topic...



Merge into merge target...



Merge into a specific topic ID...




Reading This Topic

Explore
Messages
Mentions
Search