This problem looked interesting enough that I asked Elif to send me the
program, along with an example .edat2 file that showed the behavior, and
Elif kindly complied. I suspected that the problem might be simple but
subtle, and I did find such a problem.
First some backgroud: Each trial Procedure runs a sequence of a dozen
separate stimulus Slides. Subjects respond by clicking the mouse on the
Slide. Inline code that follows each Slide checks each mouse click --
it ignores mouse clicks until a click occurs in one of the SlideImage
subobjects, after which the program moves on.
In order to allow multiple mouse clicks during the inline response code,
each stimulus Slide has the Mouse input mask set to a Max Count of 100
(in the "Advanced..." dialog). So far, so good. And so that the input
mask will run indefinitely until the inline code finds a response, each
stimulus Slide has Time Limit set to "(infinite)". And therein lies the
problem.
With Time Limit set to "(infinite)", each stimulus Slide keeps silently
taking responses, even after your program has moved on to another
stimulus that uses the same input mask -- i.e., each mouse click acts as
a response not only to the currently displayed stimulus Slide, but also
to all previous stimulus Slides in the Procedure, right up through the
last response to the last stimulus Slide. This behavior may run counter
to your natural expectation, but in fact it is useful behavior once you
understand it, and is exactly how E-Prime should behave.
Now recall that, when you allow multiple responses (Max Count > 1), by
default E-Prime logs only the *last* response for RESP, RT, RTTime, etc.
(to get around this, see the "Multiple Response Collection" example from
the PST website). And as discussed above, with all stimulus Slides set
to a Time Limit of "(infinite)", the last response to the last stimulus
Slide will count as the final response to *all* the stimulus Slides in
the Procedure. So each successive Slide *starts* at a later time, they
all get their final response at the same time, and thus RT values
monotonically decline throughout the Procedure!
So let's follow an example: Your trialprocGor Procedure runs the
stimslideGor1 Slide, and the GetResponseGor1 inline code waits for a
valid mouse response. The Procedure runs on to stimslideGor2 &
GetResponseGor2, but the input mask for stimslideGor1 is still active!
And so on right up through stimslideGor12. The final response to
stimslideGor12 becomes the final response for stimslideGor1 through
stimslideGor12, and the RT value for each stimulus is calculated from
that response. So on one example run, you get RT values of 47791,
40114, ..., 5089.
You would see this more clearly (and would have seen the problem
immediately) if you logged RTTime values in addition to RT values -- you
would then see that you get the same RTTime value for *all* stimulus
Slides in any one run of a trial Procedure. But please do not take my
word for this -- run the exercise for yourself, and then write back to
tell me whether I am right or wrong! I generally favor eliminating
extraneous data columns in order reduce clutter & confusion, but one
must be judicious ("better to have something & not need it than to need
something & not have it"). Whenever you log RT, you should also log
RTTime -- RTTime can serve as a great safety check, as this example shows.
After all that, how to fix this? Three approaches ...
1) Restructure your program. Instead of running a Procedure that runs a
dozen individual stimulus Slides (each followed by an individual
response InLine), use a subtrial List for the stimlulus Slides. The
subtrial Procedure would run one stimulus Slide + response InLine, with
the subtrial List providing information for each of a dozen stimuli.
This restructuring would accomplish several things at once: Data for
each stimlus Slide gets logged right after getting a response, so you
get correct RT values; you reuse one stimulus Slide + response InLine
for all dozen stimuli, instead of needing a dozen objects of each, which
greatly simplifies the program; the response data for each stimulus
Slide in a Procedure will now run down a single column, instead of
across several columns. Personally, I would do this above all else. (I
would also then set Time Limit to "(end of proc)" -- this would not
change any behavior in this case, but it would better represent my
intention.)
2) Once your InLine code sees a valid response, have it explicitly
terminate the input mask: See the InputMaskManager.Terminate topic in
the E-Basic Help. This is the quick & dirty solution to your problem.
If it were me I would do (1), but in the spirit of "belt + suspenders" I
would probably also do this, if I used an input mask at all (see below).
3) Do not use an input mask at all. Instead, use some combination of
Clock.Read, MouseDevice.GetCursorPos, SlideState.HitTest, and
Context.SetAttrib to directly handle the mouse responses (see those
topics in the E-Basic Help facility). This takes considerably more
programming work, but I find it much more adaptable, and I now take this
approach myself (I have written my own extensive routine library for
this purpose, which I might make publicly available some time).
(Technical aside: You could also just disable the logging from stimulus
Slides, and do that (c.SetAttrib) from your InLine response code
immediately after getting a valid response. You see, when you enable
logging from the GUI, E-Prime sets the logged attribute from the value
that it finds at the *end* of the Procedure, which causes your problem.
If you set the attribute right after getting the response, and do
*not* let E-Prime later override that, then all will work as you like.
But if you take this approach then you are asking for trouble when
someone works with the program later -- at least, add extensive comments
in an InLine to explain what you are doing & why!)
---------------
David McFarlane
E-Prime training online:
http://psychology.msu.edu/Workshops_Courses/eprime.aspx
Twitter: @EPrimeMaster (
https://twitter.com/EPrimeMaster)