I would have said to set stimulus PreRelease to same as Duration and
use inline code after the stimulus to look for the timeout, but I
like Paul's solution much, much better and will add that to my own
bag of tricks (thanks, Paul!).
Just a couple more thoughts on this:
1) Shouldn't the line
timeLeft = 120000 - Stimulus.TargetOnsetTime
instead read
timeLeft = 120000 - (Stimulus.TargetOnsetTime - FirstOnset)
? Also, the first time the initialization line
FirstOnset = Stimulus.TargetOnsetTime
runs, Stimulus.Target is 0, and that may adversely affect the
Duration for the first run of Stimulus. This could be fixed by
instead using GetNextTargetOnset time, thus,
FirstOnset = GetNextTargetOnsetTime
Also, timeLeft is based on the OnsetTime of the previous run of
Stimulus, but I think you need to take into account how long that run
lasted. You could do that by using GetNextTargetOnsetTime
instead. Putting that all together, the inline code might instead read
' FirstOnset is a global variable which is declared in the user section of
' the script window
If (FirstOnset = 0) Then FirstOnset = GetNextTargetOnsetTime
Dim timeLeft As Long
timeLeft = 120000 - (GetNextTargetOnsetTime- FirstOnset)
If (timeLeft > 0) Then
Stimulus.Duration = timeLeft
Else
Stimulus.Duration = 0
End If
Finally, instead of a FirstOnset you might instead use a LastOffset,
thus (also using Iif() to suit my own peculiar tastes),
' LastOffset is a global variable which is declared in the user section of
' the script window
If (LastOffset = 0) Then LastOffset = GetNextTargetOnsetTime + 120000
Dim timeLeft as Long
timeLeft = LastOffset - GetNextTargetOnsetTime
Stimulus.Duration = Iif( timeLeft > 0, timeLeft, 0 )
' or set Stimulus.Duration as an attribute reference
2) Alternatively, set your stimulus to use Cumulative timing mode,
and set its Duration to 120000. Define FirstOnset in global User
Script as before. Then in inline code at the start of the Procedure, use
' FirstOnset is a global variable which is declared in the user section of
' the script window
If (FirstOnset = 0) Then FirstOnset = GetNextTargetOnsetTime
SetNextTargetOnsetTime FirstOnset
(see the SetNextTargetOnsetTime topic in the E-Basic Help
facility). Now each run of the stimulus will behave as though it
started at the onset of the first run of the stimulus, and end 12000
ms after the start of the first run.
It just depends on whether you prefer to manipulate stimulus Duration
or NextTargetOnsetTime. In any case, given the general principles,
Kate and others should readily figure out the specifics.
I went ahead and attached a demo program for each solution. Thanks
again, Paul, for the great inspiration!
-- David McFarlane