Diff for "ScannerSyncCommandReference" - Methods
location: Diff for "ScannerSyncCommandReference"
Differences between revisions 5 and 7 (spanning 2 versions)
Revision 5 as of 2007-07-26 13:09:45
Size: 19307
Editor: RhodriCusack
Comment:
Revision 7 as of 2007-07-26 13:12:17
Size: 10485
Editor: RhodriCusack
Comment:
Deletions are marked like this. Additions are marked like this.
Line 7: Line 7:

---- /!\ '''Edit conflict - other version:''' ----
Line 13: Line 11:

---- /!\ '''Edit conflict - your version:''' ----
'' Parameters: '' [[BR]]
strConfig You no longer need this configuration file - just specify ""

'' Returns: '' [[BR]]

---- /!\ '''End of edit conflict''' ----
Line 29: Line 19:
{{{Example {{{Example [[BR]]
Line 34: Line 24:

---- /!\ '''Edit conflict - other version:''' ----
'Calling this routine is no longer necessary - the board communication is terminated when the ScannerSync object is destroyed.

---- /!\ '''Edit conflict - your version:''' ----
Line 40: Line 25:

---- /!\ '''End of edit conflict''' ----
Line 45: Line 28:

---- /!\ '''Edit conflict - other version:''' ----
'
Call this routine INSTEAD of calling Initialize command. The routines will give a warning, and wait for a keyboard press to start the experiment. They'll then pretend they are hearing pulses from the scanner at a rate a little below the TR, and ask for keyboard responses instead of using the response box. [[BR]]
Call this routine INSTEAD of calling Initialize command. The routines will give a warning, and wait for a keyboard press to start the experiment. They'll then pretend they are hearing pulses from the scanner at a rate a little below the TR, and ask for keyboard responses instead of using the response box. [[BR]]
Line 53: Line 34:

---- /!\ '''Edit conflict - your version:''' ----
Call this routine INSTEAD of calling Initialize command. The routines will give a warning, and wait for a keyboard press to start the experiment. They'll then pretend they are hearing pulses from the scanner at a rate a little below the TR, and ask for keyboard responses instead of using the response box. [[BR]]

{{{Example
Change...
If (objSS.Initialize("")<>0) Then End [[BR]]
to...

---- /!\ '''End of edit conflict''' ----
Line 67: Line 38:

---- /!\ '''Edit conflict - other version:''' ----
'
Similar to SetPretendMode, but allows you to separately choose whether the routines emulate pulses from the scanner and whether they emulate the response box. If you have either as false (e.g., not pretend mode) you'll need to keep the objSS.Initialize command. [[BR]]
Example [[BR]]

---- /!\ '''Edit conflict - your version:''' ----
Similar to SetPretendMode, but allows you to separately choose whether the routines emulate pulses from the scanner and whether they emulate the response box. If you have either as false (e.g., not pretend mode) you'll need to keep the objSS.Initialize command. [[BR]]
{
{{
Example   ---- /!\ '''End of edit conflict''' ----
Similar to SetPretendMode, but allows you to separately choose whether the routines emulate pulses from the scanner and whether they emulate the response box. If you have either as false (e.g., not pretend mode) you'll need to keep the objSS.Initialize command.
{{
Example
Line 83: Line 46:

---- /!\ '''Edit conflict - other version:''' ----
 Loop [[BR]]'
 Loop
}}
Line 87: Line 49:
'This routine returns the version of the ScannerSync installed, currently 1.0.2 [[BR]]
Example [[BR]]
This routine '' Returns: ''the version of the ScannerSync installed, currently 1.0.2 [[BR]]
{{
Example
Line 90: Line 53:


---- /!\ '''Edit conflict - your version:''' ----
 Loop
}}}
=== Function GetVersion() As String ===
This routine returns the version of the ScannerSync installed, currently 1.0.2 [[BR]]
{{{Example
 MsgBox "Current ScannerSync version is " & ObjSS.GetVersion
}}}

---- /!\ '''End of edit conflict''' ----
}}
Line 105: Line 57:

---- /!\ '''Edit conflict - other version:''' ----
'Waits for a pulse. It then measures its time precisely. From the previously supplied rough estimate of the TR, the routine works out the number of the pulse that has just arrived. It then uses the exact time to work out the true TR.

---- /!\ '''Edit conflict - your version:''' ----
Line 111: Line 58:

---- /!\ '''End of edit conflict''' ----
Line 117: Line 62:

---- /!\ '''Edit conflict - other version:''' ----
'This starts the clock. You should do this once per block (run of acquisitions). If no pulse is received within the timeout period (default 20s; set using SetTimeout command) then an error is returned. [[BR]]
For accuracy, this command should be executed at a high thread priority (see example).

Parameters [[BR]]
TR The time between pulses that you've asked for in milliseconds.

Returns [[BR]]

---- /!\ '''Edit conflict - your version:''' ----
Line 131: Line 65:
'' Parameters: '' '' Parameters: ''[[BR]]
Line 134: Line 68:
'' Returns: ''

---- /!\ '''End of edit conflict''' ----
'' Returns: ''[[BR]]
Line 140: Line 72:

---- /!\ '''Edit conflict - other version:''' ----
Line 146: Line 76:
'Sychronises the execution of your program (trial presentation) with the scanner. You can choose whether you actually wish to wait for a pulse or not. [[BR]]
Parameters [[BR]]
Sychronises the execution of your program (trial presentation) with the scanner. You can choose whether you actually wish to wait for a pulse or not. [[BR]]
'' Parameters: ''[[BR]]
Line 150: Line 80:

---- /!\ '''Edit conflict - your version:''' ----
{{{Example
objSS.StartExperiment 2000
}}}
=== Function SynchroniseExperiment(booActuallyWaitForPulse As Boolean, dblDelay As Double) ===
'Sychronises the execution of your program (trial presentation) with the scanner. You can choose whether you actually wish to wait for a pulse or not. [[BR]]
Parameters [[BR]]
dblDelay Time in ms after the pulse that you wish the routine to return. [[BR]]
booActuallyWaitForPulse If True, then actually wait for a scanner pulse to come in. If False, then allow use of calculated scanner pulse time. The advantage of the latter is that if a pulse has just happened (say 0.5 s ago) and you want a delay of 2s, then the routine will return in 1.5s. If you insist on waiting for a pulse, then at TR=3 it will be 2.5s before this comes in, and then you'll have to wait for 2s giving a total delay of 4.5s. [[BR]]

---- /!\ '''End of edit conflict''' ----
Returns [[BR]]
'' Returns: ''[[BR]]
Line 166: Line 84:

---- /!\ '''Edit conflict - other version:''' ----
'As SynchroniseExperiment, but waits for a particular pulse number. If the pulse has already occurred then: [[BR]]

---- /!\ '''Edit conflict - your version:''' ----
'As SynchroniseExperiment, but waits for a particular pulse number. If the pulse has already occurred then: [[BR]]

---- /!\ '''End of edit conflict''' ----
As SynchroniseExperiment, but waits for a particular pulse number. If the pulse has already occurred then: [[BR]]
Line 179: Line 90:

---- /!\ '''Edit conflict - other version:''' ----
'
Waits for dblTimeToWait and records any scanner pulse(s). It will not return before this time has expired even if a pulse is found earlier. It will return at this time, even if a pulse has not been found. [[BR]]

---- /!\ '''Edit conflict - your version:''' ----
'Waits for dblTimeToWait and records any scanner pulse(s). It will not return before this time has expired even if a pulse is found earlier. It will return at this time, even if a pulse has not been found. [[BR]]

---- /!\ '''End of edit conflict''' ----
Waits for dblTimeToWait and records any scanner pulse(s). It will not return before this time has expired even if a pulse is found earlier. It will return at this time, even if a pulse has not been found. [[BR]]
Line 192: Line 96:

---- /!\ '''Edit conflict - other version:''' ----
Line 197: Line 99:

---- /!\ '''Edit conflict - your version:''' ----
'Expert only!

Multi-tasking versions of all of the routines are implemented. These are identical to StartExperiment, SynchroniseExperiment etc., but can safely be interrupted. A quality control system ensures that only truely reliable measurements of scanner pulse are accounted for. The commands are the same as their non-interruptable counterparts described above, but have an additional sngRequiredConfidence parameter. This parameter describes the accuracy, in ms, that a measurement must have to be taken as a reliable timing measurement. If the routines are interrupted, and cannot guarantee their timing to this accuracy, then an error value (-1) is returned, and the measurement does not contribute to estimates of the TR etc. [[BR]]

---- /!\ '''End of edit conflict''' ----
Line 209: Line 104:

---- /!\ '''Edit conflict - other version:''' ----
Line 212: Line 105:

---- /!\ '''Edit conflict - your version:''' ----
'This program runs in the background with a very low thread priority, listening to scanner pulses when it can and recording information about them. It uses the multi-tasking routines mentioned above, and can safely be interrupted, with poor timing measurements being discarded.

---- /!\ '''End of edit conflict''' ----
Line 220: Line 108:

---- /!\ '''Edit conflict - other version:''' ----
'
Get the TR as estimated from all of the actual pulses measured in the experiment.
Get the TR as estimated from all of the actual pulses measured in the experiment.
Line 225: Line 111:
'If booLastActualMeasurement=True then the routine returns the time in ms of the last pulse to be actually measured. However, this routine does not actually wait for a pulse whatever the flag settings. If it is False, then the routine returns the calculated last pulse time. If booLastActualMeasurement=True then the routine '' Returns: ''the time in ms of the last pulse to be actually measured. However, this routine does not actually wait for a pulse whatever the flag settings. If it is False, then the routine '' Returns: ''the calculated last pulse time.
Line 228: Line 114:
'If booLastActualMeasurement=True then the routine returns the number of the last pulse to be actually measured. However, this routine does not actually wait for a pulse whatever the flag settings. If it is False, then the routine returns the calculated last pulse number. If booLastActualMeasurement=True then the routine '' Returns: ''the number of the last pulse to be actually measured. However, this routine does not actually wait for a pulse whatever the flag settings. If it is False, then the routine '' Returns: ''the calculated last pulse number.
Line 231: Line 117:
'Find out what keys are pressed on the button box plugged into the Keithly Board. The value will be 2, 4, 8, or 16 depending on which button is pressed. If more than one button is pressed, then these values add together. [[BR]]

---- /!\ '''Edit conflict - your version:''' ----
'Get the TR as estimated from all of the actual pulses measured in the experiment.

=== Function GetLastPulseTime(booLastActualMeasurement As Boolean) As Double ===
'If booLastActualMeasurement=True then the routine returns the time in ms of the last pulse to be actually measured. However, this routine does not actually wait for a pulse whatever the flag settings. If it is False, then the routine returns the calculated last pulse time.

=== Function GetLastPulseNum(booLastActualMeasurement As Boolean) As Double ===
'If booLastActualMeasurement=True then the routine returns the number of the last pulse to be actually measured. However, this routine does not actually wait for a pulse whatever the flag settings. If it is False, then the routine returns the calculated last pulse number.

=== Function GetResponse() As Integer ===
'Find out what keys are pressed on the button box plugged into the Keithly Board. The value will be 2, 4, 8, or 16 depending on which button is pressed. If more than one button is pressed, then these values add together. [[BR]]

---- /!\ '''End of edit conflict''' ----
Find out what keys are pressed on the button box plugged into the Keithly Board. The value will be 2, 4, 8, or 16 depending on which button is pressed. If more than one button is pressed, then these values add together. [[BR]]
Line 253: Line 125:

---- /!\ '''Edit conflict - other version:''' ----
'
As GetResponse except supports more than 4 buttons. Specify the number of buttons in the parameter intNumButtons and the return value will be masked appropriately.

---- /!\ '''Edit conflict - your version:''' ----
'As GetResponse except supports more than 4 buttons. Specify the number of buttons in the parameter intNumButtons and the return value will be masked appropriately.

---- /!\ '''End of edit conflict''' ----
As GetResponse except supports more than 4 buttons. Specify the number of buttons in the parameter intNumButtons and the return value will be masked appropriately.
Line 268: Line 133:

---- /!\ '''Edit conflict - other version:''' ----
'
Sets the time after which the routines will give up looking for a pulse - usually 20 seconds. dblTimeOutPeriod is in milliseconds.
Sets the time after which the routines will give up looking for a pulse - usually 20 seconds. dblTimeOutPeriod is in milliseconds.
Line 273: Line 136:
'If you set this to true, then an error message will be display if there are unusual, large changes in the TR estimate. This might be useful while debugging but don't use it when you are scanning -just better to let the experiment take its course. [[BR]] If you set this to true, then an error message will be display if there are unusual, large changes in the TR estimate. This might be useful while debugging but don't use it when you are scanning -just better to let the experiment take its course. [[BR]]
Line 276: Line 139:
'There is a bug in Matlab which means that while waiting in the StartExperiment routine a large amount of memory is consumed. After around 20 secs, this memory leak leads to the board drivers refusing to function. As a workaround, you may reduce the sample rate which slows the memory leak so that the routine doesn't crash out. We would recommend something like [[BR]]

---- /!\ '''Edit conflict - your version:''' ----
'Sets the time after which the routines will give up looking for a pulse - usually 20 seconds. dblTimeOutPeriod is in milliseconds.

=== Function ShowErrnums(booShowErrors As Boolean) ===
'If you set this to true, then an error message will be display if there are unusual, large changes in the TR estimate. This might be useful while debugging but don't use it when you are scanning -just better to let the experiment take its course. [[BR]]

=== Function SetMSPerSample(dblMSPerSample As Double) ===
'There is a bug in Matlab which means that while waiting in the StartExperiment routine a large amount of memory is consumed. After around 20 secs, this memory leak leads to the board drivers refusing to function. As a workaround, you may reduce the sample rate which slows the memory leak so that the routine doesn't crash out. We would recommend something like [[BR]]

---- /!\ '''End of edit conflict''' ----
There is a bug in Matlab which means that while waiting in the StartExperiment routine a large amount of memory is consumed. After around 20 secs, this memory leak leads to the board drivers refusing to function. As a workaround, you may reduce the sample rate which slows the memory leak so that the routine doesn't crash out. We would recommend something like [[BR]]
Line 296: Line 148:

---- /!\ '''Edit conflict - other version:''' ----
'
Used internally by SynchroniseExperiment - use this instead. [[BR]]
Used internally by SynchroniseExperiment - use this instead. [[BR]]
Line 300: Line 150:
'Gives you the calculated time of the pulse prior to the specified time. [[BR]] Gives you the calculated time of the pulse prior to the specified time. [[BR]]
Line 302: Line 152:
'Reads from Keithly board- used internally.

---- /!\ '''Edit conflict - your version:''' ----
'Used internally by SynchroniseExperiment - use this instead. [[BR]]
=== Function GetTimeOfPulsePriorTo(dblMyTime As Double) As Double ===
'Gives you the calculated time of the pulse prior to the specified time. [[BR]]
=== Function ReadPIOValue() As Integer ===
'Reads from Keithly board- used internally.

---- /!\ '''End of edit conflict''' ----
Reads from Keithly board- used internally.

Command reference

Initialising and terminating the communication with the board

Function Initialize(strConfig As String) as Integer

Gets the system ready. BR Parameters: BR strConfig You no longer need this configuration file - just specify ""

Returns: BR 0 if no error BR Keithly error code otherwise

Possible errors and causes: BR Board in use. If you haven't called the Terminate command at the end of running a program, you'll get an error when you start the program again. If this happens, just close the program entirely (e.g., quit the VB editor if you're using it) and start it again. This will release the drivers.

DASSHL32.DLL not found. You're using a computer without the Keithly drivers installed.

{{{Example BR If (objSS.Initialize("")<>0) Then End }}}

Sub Terminate

Calling this routine is no longer necessary - the board communication is terminated when the ScannerSync object is destroyed.

Generally useful

Sub SetPretendMode(booEmulateScannerPulse As Boolean)

Call this routine INSTEAD of calling Initialize command. The routines will give a warning, and wait for a keyboard press to start the experiment. They'll then pretend they are hearing pulses from the scanner at a rate a little below the TR, and ask for keyboard responses instead of using the response box. BR

{{{Example BR Change... BR If (objSS.Initialize("")<>0) Then End BR to... BR

}}}

Sub SetPretendModeExtended(booEmulateScannerPulse As Boolean, booEmulateResponses As Boolean)

Similar to SetPretendMode, but allows you to separately choose whether the routines emulate pulses from the scanner and whether they emulate the response box. If you have either as false (e.g., not pretend mode) you'll need to keep the objSS.Initialize command. {{ Example

}}

Function GetVersion() As String

This routine Returns: the version of the ScannerSync installed, currently 1.0.2 BR {{ Example

}}

Synchronisation with board

Function CheckPulseSynchrony()

Waits for a pulse. It then measures its time precisely. From the previously supplied rough estimate of the TR, the routine works out the number of the pulse that has just arrived. It then uses the exact time to work out the true TR.

This routine can be called at any point in your code, with any degree of regularity/irregularity. You choose when! The only constraint is that it should be at least 30 secs - 1 minute or so as discussed in the introduction.

Function StartExperiment(TR As Double) As Integer

This starts the clock. You should do this once per block (run of acquisitions). If no pulse is received within the timeout period (default 20s; set using SetTimeout command) then an error is returned. BR For accuracy, this command should be executed at a high thread priority (see example).

Parameters: BR TR The time between pulses that you've asked for in milliseconds.

Returns: BR

  • 0 if there has been no error BR

non zero otherwise

{{{Example BR objSS.StartExperiment 3000 BR }}}

Function SynchroniseExperiment(booActuallyWaitForPulse As Boolean, dblDelay As Double)

Sychronises the execution of your program (trial presentation) with the scanner. You can choose whether you actually wish to wait for a pulse or not. BR Parameters: BR dblDelay Time in ms after the pulse that you wish the routine to return. BR booActuallyWaitForPulse If True, then actually wait for a scanner pulse to come in. If False, then allow use of calculated scanner pulse time. The advantage of the latter is that if a pulse has just happened (say 0.5 s ago) and you want a delay of 2s, then the routine will return in 1.5s. If you insist on waiting for a pulse, then at TR=3 it will be 2.5s before this comes in, and then you'll have to wait for 2s giving a total delay of 4.5s. BR Returns: BR 0 if there has been no error BR non zero otherwise. BR ===Function SynchroniseExperimentToPulseNumber (booActuallyWaitForPulse As Boolean, intPulseNumber As Integer, dblDelay As Double) As Integer === As SynchroniseExperiment, but waits for a particular pulse number. If the pulse has already occurred then: BR if booActuallyWaitForPulse=True the routine will return straight away (without delay); BR if booActuallyWaitForPulse=False then the routine will return straight away if the desired time has passed, or at the appropriate time if it has not.

Function CheckPulseSynchronyForTime(dblTimeToWait As Double) As Integer

Waits for dblTimeToWait and records any scanner pulse(s). It will not return before this time has expired even if a pulse is found earlier. It will return at this time, even if a pulse has not been found. BR If you wish to design an experiment, but can only spend short periods listening for a pulse, then just work out how many pulses you'll catch on average by looking at the proportion of the TR that you're listening. So, for example, if you listen using this routine for 600ms using BR

then with a TR of 3000ms you'll catch a pulse on average 600/3000=0.2=20% of looks. BR

Multi-tasking routines

'Expert only!

Multi-tasking versions of all of the routines are implemented. These are identical to StartExperiment, SynchroniseExperiment etc., but can safely be interrupted. A quality control system ensures that only truely reliable measurements of scanner pulse are accounted for. The commands are the same as their non-interruptable counterparts described above, but have an additional sngRequiredConfidence parameter. This parameter describes the accuracy, in ms, that a measurement must have to be taken as a reliable timing measurement. If the routines are interrupted, and cannot guarantee their timing to this accuracy, then an error value (-1) is returned, and the measurement does not contribute to estimates of the TR etc. BR

Function WaitForPulse_Interruptable(ByRef dblPulseTime As Double, sngRequiredConfidence As Single) As Integer [[BR]]

Function StartExperiment_Interruptable(dblTR As Double, sngRequiredConfidence As Single) As Integer [[BR]]

Function CheckPulseSynchrony_Interruptable(sngRequiredConfidence As Single) As Integer

Scanner Spy [[BR]]

'This program runs in the background with a very low thread priority, listening to scanner pulses when it can and recording information about them. It uses the multi-tasking routines mentioned above, and can safely be interrupted, with poor timing measurements being discarded.

Getting information about what's happening

Function GetMeasuredTR() As Double

Get the TR as estimated from all of the actual pulses measured in the experiment.

Function GetLastPulseTime(booLastActualMeasurement As Boolean) As Double

If booLastActualMeasurement=True then the routine Returns: the time in ms of the last pulse to be actually measured. However, this routine does not actually wait for a pulse whatever the flag settings. If it is False, then the routine Returns: the calculated last pulse time.

Function GetLastPulseNum(booLastActualMeasurement As Boolean) As Double

If booLastActualMeasurement=True then the routine Returns: the number of the last pulse to be actually measured. However, this routine does not actually wait for a pulse whatever the flag settings. If it is False, then the routine Returns: the calculated last pulse number.

Function GetResponse() As Integer

Find out what keys are pressed on the button box plugged into the Keithly Board. The value will be 2, 4, 8, or 16 depending on which button is pressed. If more than one button is pressed, then these values add together. BR To find out if a particular key is pressed, use the keyword AND as in the example. BR From what I understand, there are two button boxes that plug into the Keithly Board - a left handed and a right handed one. I don't know which way the buttons are wired up. You need to find someone who knows this or work it out. Please then email the vbsupport list with the answer! BR {{{Example BR If (Not(GetResponse() And 4)) Then Debug.Print "Button 2 was pressed" }}}

Function GetResponseExtended(intNumButtons as Integer) As Integer

As GetResponse except supports more than 4 buttons. Specify the number of buttons in the parameter intNumButtons and the return value will be masked appropriately.

{{{Example BR If (Not(GetResponseExtended(7) And 64)) Then Debug.Print "Button 6 was pressed" BR }}}

Options

Function SetTimeout(dblTimeOutPeriod As Double)

Sets the time after which the routines will give up looking for a pulse - usually 20 seconds. dblTimeOutPeriod is in milliseconds.

Function ShowErrnums(booShowErrors As Boolean)

If you set this to true, then an error message will be display if there are unusual, large changes in the TR estimate. This might be useful while debugging but don't use it when you are scanning -just better to let the experiment take its course. BR

Function SetMSPerSample(dblMSPerSample As Double)

There is a bug in Matlab which means that while waiting in the StartExperiment routine a large amount of memory is consumed. After around 20 secs, this memory leak leads to the board drivers refusing to function. As a workaround, you may reduce the sample rate which slows the memory leak so that the routine doesn't crash out. We would recommend something like BR

        objSS.SetMSPerSample 2 [[BR]]

Thanks to Tom Morey for helping with this one.

Routines available that you shouldn't normally need

Function WaitForPulse(ByRef dblPulseTime As Double) As Integer

Used internally by SynchroniseExperiment - use this instead. BR

Function GetTimeOfPulsePriorTo(dblMyTime As Double) As Double

Gives you the calculated time of the pulse prior to the specified time. BR

Function ReadPIOValue() As Integer

Reads from Keithly board- used internally.

None: ScannerSyncCommandReference (last edited 2013-03-08 10:28:25 by localhost)