I have been struggling to find a precise way to produce accurate time events to synchronize the data from an EEG system I have been building to visual stimuli. Being able to read precise time measures is great, but reliably reproducing accurate intervals of time has proven to be a daunting task that many researchers have struggled with.
Eprime is expensive and somewhat medieval, flash is unreliable (for time), and although python can access microseconds, its graphical capabilities are confusing. Thankfully, the newer versions of Java allow for nanosecond sampling from the CPU clock (and I’ve read rumors that picoseconds will soon be possible in the next Java version, although I am somewhat skeptical…3.3 psec is how long it takes light to travel 1 mm!). With nanosecond capability, it is possible to create a timer that produces accurate time interval events to display stimuli on the computer screen for very specific amounts of time while recording brain waves. Using the Processing environment (processing.org), I was able to write a simple program that produces an accurate 1ms time interval, based on and verified by the nanosecond resolution system timer.
To test the accuracy and precision of the intervals produced, three trials were run where the precise nanosecond timing of 700 one-millisecond intervals were recorded. Simple descriptive analysis of the 2100 samples revealed that the mean interval lasted 0.001099731 seconds, having a standard deviation of 0.000465145 seconds (N=2100, M= 0.001099731, SD=0.000465145). I should note here that a MacBook Air with an Intel Core Duo 1.6GHz and 2GB of RAM was used to preform the test.
On a better system, I’m sure one could push for microsecond intervals, but thats unnecessary for EEG research as microseconds are beyond the speed of any known cognitive and neural processes (at least those I’m aware of).
Here is my code with an example N400 task:
//NanoTimer 10-1-2010
//By: Dave Deriso, dderiso@ucsd.edu
//Creative Commons, Non-Commercial License
//http://creativecommons.org/licenses/by-nc-sa/3.0/
long startNano = System.nanoTime();
long now;
float delta;
int t=0;
float w,h;
void setup() {
size(300, 300);
background(255, 255, 255);
frameRate(1E11); //boosts program speed, improves accuracy
smooth();
// Set "ink" color, font, and alignment for rendering text.
fill(0); // Black
// setup the font (system default sans serif)
textFont(createFont("SansSerif",18));
textAlign(CENTER);
w = width/2;
h = height/2;
}
void draw()
{
now = System.nanoTime() - startNano;
delta = now*1E-9;
if (delta > .001) //vary this btwn 1sec to 1ms (.001)
{
println(delta);
//trigger your event here
t++;
present();
startNano = System.nanoTime();
}
//delay(1/10); //reduce process demand by duty cycling
}
void present()
{
if (t==1){text("Billy likes to", w, h);}
if (t==2000){clearSc(); text("kick", w, h);}
if (t==3000){clearSc(); text("the big red", w, h);}
if (t==3500){clearSc(); text("walrus", w, h);}
if (t==3515){clearSc();}
}
void clearSc()
{
background(255, 255, 255);
}
If all goes well, your output should resemble the following (in seconds):
0.001017
0.001002
0.001002
0.001006
0.001003
0.001006
0.001009
0.001019
0.001034
0.001026
0.001022
0.001028
Note that the .001 sec should come up each time and that the microsecond variability shouldn’t affect the intended purpose.