Forum
Register Calendar Latest Topics
 
 
 


Reply
  Author   Comment  
neo3dot1415

Junior Member
Registered:
Posts: 29
Reply with quote  #1 
Hi,

There is a variable in .bhv file called ObjectStatusRecord. It has 3 columns, Status, Time, and Data. 

I assume the 2nd column, Time, is relative to the toggleobject function and it shows the TaskObject onset time (please, correct me if I am wrong).

If this is the case, why there is always 2-3 msec difference between the values in this column and their relative values in CodeTimes variable? 

* I'm using EventMarker inside the toggleobject function each time.

Thanks.
0
Jaewon

Administrator
Registered:
Posts: 380
Reply with quote  #2 
Your understanding about ObjectStatusRecord is right. The difference of the recorded times between ObjectStatusRecord and CodeTimes is inevitable though, because eventmarker reads the timer separately. Both in the old ML and NIMH ML, the sequence of toggling object is the same like this.

1) Flip the screen
2) Read the timer (this is the time recorded in ObjectStatusRecord)
3) Call eventmarker (eventmarker reads the timer again and it goes to CodeTimes)

It is surprising that there is always a 2-3 ms difference in your system. In my computer, the difference is 0 or 1. There is not so much you can do about it except using a faster computer, I think, because the above 3 steps are just 3 lines of code. That is probably the maximum speed that your MATLAB can process with.
0
neo3dot1415

Junior Member
Registered:
Posts: 29
Reply with quote  #3 
Thanks Jaewon. I have core i7 6700K + 32 GB of DDR4 RAM + SSD hard drive.  

Another question [smile]

I'm doing close-loop experiment with ML and neural recording on Intan/OpenEphys. 

In order to synchronize the ML results with neural data, am using CodeTimes. Each value in CodeTimes is in millisecond. Let's say the first 9 (event marker) in the first trial has a relative value in CodeTimes equal to 5 msec. 

If I synchronize the two devices based on the first 9 of the first trial, the new zero would be at -5msec of the first 9. After first trial, I can't hold the synchronization because there is an offset. The offset is ranging from hundreds of microseconds to ~3 milliseconds (cumulative offset from first trial to last trial).

I was thinking the source is that ML time stamps the eventmarker in milliseconds rather microseconds. In the above example we have the first 9 at t = 5 msec, but we are not sure if it was 5.001 msec, 5.5 msec or 5.999 msec. So, this uncertainty and choosing 5 msec rather than the true value will cause the cumulative offset.


Thanks for the support.
0
Jaewon

Administrator
Registered:
Posts: 380
Reply with quote  #4 
It is not clear to me what you mean by synchronizing two devices. Are you talking about syncing them during the experiment or aligning two data files? How did you calculate the offset?
0
neo3dot1415

Junior Member
Registered:
Posts: 29
Reply with quote  #5 
Sorry if I did not explain well. 

I meant aligning two data sets. 

Getting back to my example. I extracted the time relative to the first 9 of the first trial from .bhv file (Codetimes). It was at t = 5 msec.

Digital input of OpenEphys continuously recorded the behavioral codes for the entire of experiment. 

In order to align the two signals, I had to find the new zero point on my recorded strobe signal (the time difference between ML start time and OpenEphys start time), which I took 5msec prior to the first initiation of strobe word and defined it as my new zero point for the strobe signal (Let's call the new signal; aligned_strobe_signal).

Then, I drew the aligned_strobe_signal (recorded by OpenEphys) on the EyeSignal (recorded by ML). It was fine for the first trail, because I assumed the first 9 happened at t = 5 msec. For the second trial, I've considered the relative AbsoluteTrialStartTime (from bhv file) of the 2nd trial and extracted the aligned_strobe_signal at time = AbsoluteTrialStartTime(2,1). Then again drew the two signals. In the 2nd trial, the first 9 happened at t = 4 msec (reading from CodeTimes), but in my plots strobe signal is located at ~t = 4.155 msec (0.155 msec would be the offset). As we going forward to trial 100th, this offset accumulated and reached to ~3msec!

What I am thinking is:

Let's say, if in the first trial, the first 9 happened at 5.999 msec, ML would write 5 instead of 5.999 (please, correct me if I'm wrong). The msec precision is only happing for CodeTimes not for example for AbsoluteTrialTimes (is in microsec). This may lead us to cut the strobe signal from the wrong place (instead of cutting 5.999 msec prior to first strobe we're cutting at 5 msec prior to it). That's why for the second trial, the first strobe is not sitting on its right position.    
0
Jaewon

Administrator
Registered:
Posts: 380
Reply with quote  #6 
Now I understand how you did it. I think your aligning method is fine. However, I don't think rounding off is the source of the problem. The starting point of AbsoluteTrialStartTime is never reset and the CodeTimes of each trial uses the AbsoluteTrialStartTime of that trial as 0 and counts from there. Each timestamp may have an offset of ~1 ms between the devices, but it cannot add up. I think we need to consider the possibility that the clock speeds of two devices are different. Do you know what is the sampling rate of your recording device?

One thing I am curious about is that you said you extracted the aligned_strobe_signal at time = AbsoluteTrialStartTIme(2,1). I assumed that the aligned_strobe_signal is just a long array that contains all data from trial 1 to trial 100, but do you extract the aligned_strobe_signal every time for each trial? Do you have a function to do it? If so, it can that function that calculates the time displacement incorrectly.
0
neo3dot1415

Junior Member
Registered:
Posts: 29
Reply with quote  #7 
I had Fs = 20KHz on my recording device.

Yes, the raw_strobe_signal is a long array (dose not have any chunks).

I'm extracting the aligned_strobe_signal from the raw_strobe_signal based on the first 9 of the first trial.

Then for the 2nd trial to the end, each time I'm extracting from t = AbsoluteTrialStartTime(i) to the length_EyeSignal(i) from the aligned_strobe_signal.

i = current trial.


* Trial_duration(1) = 12288 msec
* AbsoluteTrialStartTime(1) = 0
* First 9 of the first trial happened @ t = 5 msec (imagine it was actually at t = 5.150 msec): 
* Last 18 of the first trial happened somewhere @ t = 12285 msec 

* We cut the 5 msec prior to the first detected strobe word of the raw_strobe_signal (instead of first 5.150 msec).

Now on the aligned_strobe_signal, 1st 9 would be at 5 msec rather than sitting on its actual time.

The first trial ends at t = 12288 msec, which is shifted by 0.150 msec from its actual location.

** Trial_duration(2) = 3518 msec 
** AbsoluteTrialStartTime(2) = 12992.3414718396 msec

** calling the signal from t = AbsoluteTrialStartTime(2)  

* First 9 of this trial happened @ t = 4 msec but now it is @ t = 4.150 msec (say if it was actually @ t = 4.805 msec )
* Last 18 of this trial @ t = 3516 msec 

So far we added 0.150 msec offset from the first trial + 0.805 msec from the second trial = 0.955 msec. Thus, 3rd trial will begin from X+0.955 msec instead of X. 

Note! Values in green are real.

This timing is crucial for me as am doing close loop, and I have to be sure if specific event happened during my close lope or even X microsecond after that.

    
0
Jaewon

Administrator
Registered:
Posts: 380
Reply with quote  #8 
I understand what you are saying, but it is not a correct presumption.

If the timestamp of the first 9 of the first trial is 5 when it is in fact 5.150, it is right that there is a 0.150 offset. But then the rest of the timestamps all get the same 0.150 offset. It doesn't add up. The timestamps are the numbers rounded off, so the fact that the first 9 of the second trial occurred at 4 means that its actual time is somewhere between 3.5 and 4.49. If it were 4.805 as you imagined, the timestamp should be 5, not 4.

Now you said you saw up to a 3-ms difference after 100 trials. If this is a result of some accumulation, the obvious suspect is the clock difference. Let's say your recording device was actually sampling at 19999 Hz, instead of 20000 Hz. Then what you think as 1 sec is in fact 1 sec and 50 usec to the device. After 1000 sec (10 sec x 100 trials), this difference results in a 50-ms difference.

To see if this is the case, you need to extract the timestamp of the first 9 from every trial and compare the difference of the displacement from the 9 of the first trial. If the difference is getting bigger as you move to the later trials, it is the clock problem. If so, you should align each trial separately to their own first 9, not to the 9 of the first trial.
0
neo3dot1415

Junior Member
Registered:
Posts: 29
Reply with quote  #9 
Sorry, it was mistake to round off 4.805 to 4 instead of 5! 

I agree that it could be the clock problem, thanks for the suggestion. 

But, lemme explain my thoughts in another way. 

IMG_2017-02-10 01:37:38.jpg 

Let's say a subject is fixating at a dot 15 degrees horizontally apart form the screen centre (showing by Eye Signal X at 15 degrees). I'm asking the software to switch a specific stimulus to another stimulus whenever the subject makes 3 degree saccade (Blue Line). It's gonna be the ideal case if toggleobject happens exactly at 12 degree, but usually it occurs a bit after 12 degree (I think it would be variable based on the software latency). In such experiment, it would be crucial to see if eventmarker happens somewhere around Green line (before the saccade offset) or Red line (after saccade offset, sorry if it's not the best sketch [smile] ). I think even if I overcome the clock issue, it would be very useful to have the microsecond precision for eventmarkers for two reasons. First, rounding off the value may drop the eventmarker to either side of the saccade offset (which may lead us to wrong interpretation). Second, by having the precise location, we can double check the software/hardware delay during such kind of close loop experiments.


Sorry Jaewon that this conversation takes a long time. I really appreciate your time and consideration. [smile] 

0
Jaewon

Administrator
Registered:
Posts: 380
Reply with quote  #10 
I agree with you. Personally I don't understand why the original developers of ML rounded off the timer readings when the resolution was good enough in microseconds. But CodeTimes are saved in the integer format in BHV, so there is no way to recover the original precision.

I am rewriting everything from the scratch now and don't want to patch the old code any more, but let me see if I can fix this quickly. It will involve the change of the BHV format though.

0
neo3dot1415

Junior Member
Registered:
Posts: 29
Reply with quote  #11 
That would be great Jaewon. Thanks.
0
Jaewon

Administrator
Registered:
Posts: 380
Reply with quote  #12 
I already updated the package.

http://forums.monkeylogic.org/post/nimh-monkeylogic-8118700?trail=125#116
0
neo3dot1415

Junior Member
Registered:
Posts: 29
Reply with quote  #13 
Thank you so much for the non-stop support. 
0
Previous Topic | Next Topic
Print
Reply

Quick Navigation:

Easily create a Forum Website with Website Toolbox.