<<TableOfContents: execution failed [list index out of range] (see also the log)>>
Documentation for Version 1.3.7. Documentation last updated 27/7/2007
Rhodri Cusack 2000-2007.
' Changed 17/5/00 by Rhodri
' Added version command
' Added "Class_Terminate"
' Added SetPretendMode and associated code
' 25/5/00 - Added CheckPulseSynchronyUntilTimeout
' 06/06/00 - Add pretend mode to response routines
' 19/07/00 - Changed Checkpulsesynchrony so that it works in pretend mode
' 5/09/00 Made it work with new DriverLinx drivers
' 1/12/00 Changed WaitForPulse_Interruptable so that it doesn't erroneously return 0 when time out occurs in pretend mode
' For move back to Cambridge, added local mode
' Modified to look for low-going pulse
' New image - not much different
' 11/4/02 - Added SetDevice command
' 27/1/03 - Added option to scan for second driver when first not found, to make compatible with PCMCIA Keithly card
' 12/5/03 - Added SetPretendModeExtended
' 18/5/03 - Added GetResponseExtended
' 29/4/03 - Changed calculation of interval to cope with initial over estimates of TR
' 9/11/04 - Modify StartExperiment so that it returns error code properly
' Add error trapping for board problems
' 23/11/04 - Added SetMSPerSample option which allows reduction of sample rate
' in StartExperiment routine to tackle Matlab misbehaviour.
' 12/7/06 - Added support for new button boxes with GetResponseLeft and 'GetResponseRight
' 24/7/06 - Added SSGetTimer command as difficult to read from perfpres dll from matlab
Notes Apr 2003
Some notes on how to calculate your stimulus timings for SPM:
Beware that the "pulse number" is a zero-based index: pulse "0" is the first one, collected by the objSS.StartExperiment command. Pulse "1" is the second, usually collected by your first dummy scan objSS.SynchroniseExperiment command. I set it up like this because this is how SPM likes its timings: time "0" is the first scan.
- At the current date with "Christian's EPI sequences" the pulse starts 50ms before the start of the first scan. If you wish to be precise, subtract 50ms from your timings.
- The old Bruker sequences had the pulse at the end, and so you had to subtract one TA from the timings. This is no longer the case.
These routines should provide a flexible way of synchronising with the scanner. They allow for a range of designs, and are hopefully easy to integrate with many experimental designs.
The main way this is achieved is by allowing you to measure the scanner pulse whenever you want. The only restriction is that you check for the pulse at least once every minute.
It doesn't matter when you call the pulse measurement routines - you can do this once every 30 seconds, or when the experiment determines (e.g., in a timing where the subject's responses determine progress, this might end up at 24, 75 and 82 seconds). The only restrictions are that you do it at least once a minute, and don't mind waiting for up to the TR time for a pulse to come in (although you can use the routines in a slightly different way to get around this last restriction).
You can choose to synchronise your experiment flow (trial presentation) to the scanner pulses at the same time as you actually measure a pulse, or at a different time, in which case the routines will calculate when the pulse occurred. This has an advantage if you wish the routines to synchronise to a certain delay after a pulse. For example, if you want you trial to start 2.5 seconds after a pulse, and there was a pulse 2 seconds ago, then you can start in 0.5 seconds. If you had actually waited for a pulse to arrive, then you would have had to wait a second for the pulse to come in, and then another 2.5 seconds, which would take 5.5 seconds. This might not always be acceptable.
The reason it is not necessary to count every pulse is that although the scanner doesn't quite give us the time we ask for, it is pretty accurate - say within 1%. Hence, if we've asked for a TR of 3s, and we happen to listen out for a pulse after 32s, and find one at 33.33, then we know this is the 11th pulse, and that the actual TR is 3.03s. To do this, we didn't have to know a priori that we were measuring the 11th pulse- the routines can calculate this if they are told the rough TR. They then use the measurements to improve their estimate of the actual TR. For this to work, there is one restriction: that the drift time is smaller than half a TR. If p is the drift in percent, T is the TR time, and N the number of trials between pulse measurement, we have
N*TR*p/100 < TR/2
Rearranging N < 50/p
Now, putting in p=1 this gives N<50. So the absolute limit is that N=50; for a TR of 3, this is once every 150s. If you want to be on the (very) safe side, then 30s would seem a good compromise.
In practice, even if you measure the first pulse (worst case) the routines will know the TR to within a a millisecond, and as soon as you've synchronised once the experimental timings will be accurate to within 1 ms. Matt Davis suggested that, as he does with DMDX, you could use the dummy scans at the start of each experiment to measure the TR.
Using the routines
Download latest version from ScannerSync
In VB, go to Project > References. Find MRISync and tick the box.
At the top of the code in which you want to use the synchronisation routine, put
Dim objSS as New ScannerSync
This will make the ActiveX object through which you'll access all the commands. At the end of your code, or in an escape routine, call Terminate (see notes under this below).
A note about timing: the scanner synchronisation routines use the high performance counter clock in the perfpres.dll, and will be very upset if you reset it. You can read the time with GetTimer, but don't reset the clock with StartTimer. If you wish to measure an interval, then use relative code:
Dim dblMyTempTime as Double dblMyTempTime=GetTimer() .... thing to be timed.... Debug.Print "The interval was " & GetTimer() - dblMyTempTime