Fixing in-line script that broke from EP2 to EP3

121 views
Skip to first unread message

Caitlin

unread,
Jan 16, 2020, 3:58:07 PM1/16/20
to E-Prime
Hi everyone, 
I have been working with the in-line script below for several years without problems in E-Prime 2. I did not originate the code, and now I'm having trouble figuring out how to fix it. We do EEG experiments, and the objective is to permit the experimenter to "mark" trials that should be excluded. For instance, if there is behavioral noncompliance (looking away, off task, talking) or other errors. When I convert my ep2 files to ep3, the following seem to be problems: 
  • EP3 calls an error for: g_DebugString = ""
    • Variable not defined
    • I was not aware of needing to predefine this variable (we didn't need to in EP2), but a simple "Dim g_DebugString as String" resolved this problem.
  • EP3 calls an error for:     ModDebugString keyboardMask.Responses(I).RESP
    • Unknown command "ModDebugString"
My questions;
  1. First of all, is there an easier way in EP3 to mark trial-level data to indicate appropriate behavior -- as you can see below, we had it coded to look for spacebar presses.
  2. I can't find any documentation of why "ModDebugString" worked as a command in EP2. Any guidance? Is there a similar command in EP3?
Appreciate your help!
-Caitlin


In-line script (in User Script)
Function IsBadTrial(keyboardMask As InputMask, StartTime As Long, EndTime As Long) As Boolean
Dim I As Long
Dim Result As Boolean
'For I = 1 to keyboardMask.Responses.Count
'Debug.Print "\tResponse " & I & " is: " & keyboardMask.Responses(I).RESP
If keyboardMask.Responses(I).RTTime > StartTime Then
Result = True
ModDebugString keyboardMask.Responses(I).RESP
'If latest stroke is before trial started, then only a 
'downstroke can make the trial bad. 
Else
g_DebugString = "B" + g_DebugString
ModDebugString keyboardMask.Responses(I).RESP
If keyboardMask.Responses(I).RESP = "{SPACE}" Then
Result = True
End If
End If
End If
End If
If Result Then
g_DebugString = "B:" + g_DebugString
Else
g_DebugString = "G:" + g_DebugString
End If
IsBadTrial = Result
End Function'Debug.Print "\tRT " & I & " is: " & keyboardMask.Responses(I).RT 
'Debug.Print "\tRTTim " & I & " is: " & keyboardMask.Responses(I).RTTime
'Next I
Result = False
g_DebugString = ""
I = keyboardMask.Responses.Count
If I <> 0 Then
'Working backwards, find the latest stroke before the end of the trial
While I > 0 And keyboardMask.Responses(I).RTTime > EndTime
I = I -1
ModDebugString keyboardMask.Responses(I).RESP
Wend
g_DebugString = "E" + g_DebugString
If I > 0 Then
'If any stroke after trial started, then trial is bad. 

David McFarlane

unread,
Jan 28, 2020, 5:10:34 PM1/28/20
to e-p...@googlegroups.com
Caitlin,

First, a bit of terminology. "InLine script" (or code, as I prefer to
call it) and "User script" are two different things. You enter InLine
code using an InLine E-Object within a Procedure, and that code is local
to that Procedure. You enter global User script on the User tab of the
Script window (EP2) or in the User Script window (EP3). You may not run
any executable code within the global User script area, and you may not
define any global variables, Subroutines, or Functions within InLine code.

All variables in E-Prime must be defined using a Dim statement before
being used -- this results from the Option Explicit statement built in
to E-Prime, see that topic in the E-Basic Help. Prepending "g_" to a
variable name is a naming convention that indicates that the variable is
global and defined in the global User script area. So of course you had
to define g_DebugString, and no doubt your original EP2 version also
defined that variable.

You cannot find any documentation for "ModDebugString" because
ModDebugString is not a subroutine defined by E-Prime. ModDebugString
would be a custom subroutine defined somewhere in the global User area
of the program.

Basically, it looks to me that something got garbled when you converted
your EP2 program to EP3. You should look at the global User script area
of your EP2 & EP3 programs and see if they match. E.g., the code you
posted shows a definition for the IsBad function, properly ending with
End Function, but everything following that End Function is just a mess!

Final word -- you have While-Wend in your code!! I have ranted about
While-Wend before, so I will have nothing more to do with this thread
until you replace While-Wend with a proper Do-Loop structure :).

-- David McFarlane


On 2020-01-16 Thu 3:58 PM, Caitlin wrote:
> Hi everyone,
> I have been working with the in-line script below for several years without
> problems in E-Prime 2. I did not originate the code, and now I'm having
> trouble figuring out how to fix it. We do EEG experiments, and the
> objective is to permit the experimenter to "mark" trials that should be
> excluded. For instance, if there is behavioral noncompliance (looking away,
> off task, talking) or other errors. When I convert my ep2 files to ep3, the
> following seem to be problems:
>
> - EP3 calls an error for: g_DebugString = ""
> - Variable not defined
> - I was not aware of needing to predefine this variable (we didn't
> need to in EP2), but a simple "Dim g_DebugString as String" resolved this
> problem.
> - EP3 calls an error for: ModDebugString
> keyboardMask.Responses(I).RESP
> - Unknown command "ModDebugString"
>
> *My questions;*
>
> 1. First of all, is there an easier way in EP3 to mark trial-level data
> to indicate appropriate behavior -- as you can see below, we had it coded
> to look for spacebar presses.
> 2. I can't find any documentation of why "ModDebugString" worked as a
> command in EP2. Any guidance? Is there a similar command in EP3?
>
> Appreciate your help!
> -Caitlin
>
>
> *In-line script (in User Script)*

Caitlin

unread,
Feb 13, 2020, 4:03:49 PM2/13/20
to E-Prime
Hi David, 
Apologies, just now seeing this response. Appreciate your feedback and vocab lesson - bear in mind that I did not write this code, which is part of the difficult nature of sussing it out. I personally haven't written Do-Loops, but will look into this ASAP. We're in a bit of a time crunch, so I'll try to sort back through your posts but do let me know if there was a particular thread that you know would be helpful.

I found the section that was missing from the User Script in EP3, and it was missing from the EP2 experiment foundation I was using.. so a true user error. However, I'm curious if you have any thoughts on my other more broad question -- are there other mechanisms or strategies (besides the clunky code that I'm borrowing) to track ongoing keyboard presses? In fact, I'm not entirely convinced that the strategy I'm hoping to implement will work given that participants are also marking responses. For instance, in the current experiment I'm attempting to get off the ground, we have the participant's behavioral responses restricted to digits (1-8) corresponding with the button box, ostensibly reserve the SPACEBAR for our behavioral coding (i.e., was participant on task?). I'll do some testing this afternoon, but would value any insights to other strategies that might be easier to implement and/or more robust. 

appreciate your time,
-Caitlin

David McFarlane

unread,
Aug 9, 2022, 9:46:28 AM8/9/22
to e-p...@googlegroups.com
It has taken a couple years for my mind to clear enough to address the
primary objective here. I think I got distracted by the extensive
programming code here, which is secondary to the primary objective,
which I think we can address with little if any code. So just in case
anyone ever stumbles onto this thread ...

Restating the primary objective as I understand it: For each trial we
want to allow the experimenter to use a keyboard key to indicate a
problem with the trial so that we may exclude it, and we want that
information to appear as a marker/signal/trigger in the EEG record for
that trial.

We could do that very simply using a Wait object with an extended input
mask (see Appendix C in the User's Guide for EP2) that could run during
the entire trial. Specifically, we could start the trial Procedure with
a Wait object -- let's call it TrialExcludeWait. We would give this a
Duration of 0, and add a keyboard input mask with Allowable set to, say,
"{SPACE}", Time Limit of either "(infinite)" or "(end of proc)", and End
Action of "(none)". Now TrialExcludeWait would not affect timing within
the Procedure, but its input mask would still run throughout the
Procedure and allow the experimenter to enter a response at any time.
If we also enable response logging for TrialExcludeWait then we will get
that info in the resulting E-DataAid file. (We actually do something
very much like this in an exercise in my online E-Prime 2.0 course.)

Now we still need to output a marker for the EEG, either at the end of
the trial or at the time that the experimenter presses the key. Let's
assume that we are using EP2.0.10 or later so that we can use a
ParallelPort device for the output.

To output the marker at the end of the trial Procedure we could use a
bit of InLine code, e.g.,

Const ExcludeMarker As Integer = 253 ' select some appropriate
marker value
If (TrialExcludeWait.RTTime > 0) Then
ParallelPort.WriteBye ExcludeMarker
End If

(Note that we could use a variety of other conditionals for the If-Then
construct here depending on taste & style.)

To instead output the marker at the time that the experimenter presses
the key, we could use Task Events. So back on TrialExcludeWait we would
add a Task Event for TrialExcludeWait.Keyboard(1).Press, set the Task to
ParallelPort with a Delay of 0, set the Action to WriteByte, leave
Source at "(custom)", set Custom to, say, 253, set the Data Type to
Byte, and leave Enabled to Yes. And as explained in several other
threads here we would add another Task Event to reset the output after
some suitable delay: Add a second Task Event for
TrialExcludeWait.Keyboard(1).Press, set the Task to ParallelPort but
this time with a Delay of, say, 20, set the Action to WriteByte, leave
Source at "(custom)", set Custom this time to 0, set the Data Type to
Byte, and leave Enabled to Yes.

Besides outputting the marker at the time that the experimenter presses
a key, the Task Events method requires no programming code. But
depending on the design of the trial Procedure it may allow the
exclusion marker to interfere with other markers in the trial, so use
with care.

-- David McFarlane


On 2020-02-13 Thu 4:03 PM, Caitlin wrote:
> Hi David,
> Apologies, just now seeing this response. Appreciate your feedback and
> vocab lesson - bear in mind that I did not write this code, which is
> part of the difficult nature of sussing it out. I personally haven't
> written Do-Loops, but will look into this ASAP. We're in a bit of a time
> crunch, so I'll try to sort back through your posts but do let me know
> if there was a particular thread that you know would be helpful.
>
> I found the section that was missing from the User Script in EP3, and it
> was missing from the EP2 experiment foundation I was using.. so a true
> /user/ error. However, I'm curious if you have any thoughts on my other
Reply all
Reply to author
Forward
0 new messages