Visual Analog Scales, IFIS, and Button Response Units

Daniel.J.Bates at wheaton.edu Daniel.J.Bates at wheaton.edu
Wed Jul 30 19:25:32 UTC 2003


Hello Everyone...

Over the last three months, I have posted several sections of code outlining 
how to create a visual analog scale in E-Prime.  Unfortunately, none of those 
portions of code run with IFIS or Button Response Units.  For whatever reason, 
BRUs are not directly connected to the computer.  Input is first sent to a 
small box located inside the MRI room.  This box sends a discrete value (rather 
than a continuous stream) to the computer saying that a button has been 
pressed.  Unfortunately, this decreases the flexibility of the Visual Analog 
Scale (explained later).  I, therefore, have changed the code so that E-Prime 
users can use visual analog scales inside MRI machines.  I hope someone finds 
this information helpful.

Good luck...
Daniel

--------------------------------------------------
Visual Analog Scale Construction
--------------------------------------------------
1) Composed of 5 E-Prime objects in the following order
   a) InlineCode1: Defines two variables
   b) Label1
   c) Slide1
   d) Wait1
   e) InlineCode2: Responsible for the movement of the vertical bar.
2) Object Parameters
   a) InlineCode1: Cannot change parameter
   b) Label1: Cannot change parameters
   c) Slide1
      i) 3 Text Boxes
      ii) 2 images superimposed on each other (a horizontal rectangle and a  
vertical bar).  These images were created in Microsoft Paint and are named 
SlideBar1 and SliderButton2 respectively.
      iii) SlideDuration = 80 ms
      iv) InputDevices = Keyboard
      v) AllowableInput = 12345
      vi) Timelimit = [Same as duration)
   d) Wait1
      i) WaitDuration = -1 (infinite)
      ii) InputDevices = Keyboard
      iii) AllowableInput = 12345
      iv) Timelimit = [Same as duration]
      v) Logging: RESP: Records actual response of subject
3) Inline Code Explained
   a) InlineCode1
      i) Code: 
    Dim ButtonPosn As Integer
                            Dim NewButtonPosn As Integer
                            ButtonPosn = 139
                            NewButtonPosn = ButtonPosn
      ii) Defines initial values of ButtonPosn and NewButtonPosn.
      iii) Placing this code before Label1 allows the default values of 
ButtonPosn and NewButtonPosn to change
   b) InlineCode2
      i) Code: 
 Dim FinalSelection As Integer
 	 	 Dim ScreenWidth As Integer
 	 	 Dim slrLeft As Integer
 Dim slrRight As Integer
 		 Dim KeyAscii As Integer
 Dim KeyAscii2 As Integer
 Dim Tag As String
 Dim StopLoop As Integer

 ScreenWidth = 640
 slrLeft = 139	
 slrRight = 493
 FinalSelection = 0

 KeyAscii = Wait1.Resp

 Select Case KeyAscii
    Case 1
       StopLoop = 0
  	Do
	  StopLoop = StopLoop + 1
          If (Slide1.RESP = Empty) OR (StopLoop = 1) THEN
  	     StopLoop = StopLoop + 1
             If ButtonPosn >= slrLeft + 2 Then
              NewButtonPosn = ButtonPosn - 2
             Else
              NewButtonPosn = slrLeft
             End If
              CSlideImage(Slide1.States.Item("Default").Objects(1)).X = 
NewButtonPosn	   
              ButtonPosn = NewButtonPosn    
              Slide1.InputMasks.Reset
    	      Slide1.InputMasks.Add Keyboard.CreateInputMask("12345", "", Val
(Slide1.Duration), Val("1"), ebEndResponseActionTerminate, True, "", "", "")
              Slide1.Run
          Else
	     StopLoop = 501
	  End If
              Loop until StopLoop > 500

   Case 3
      FinalSelection = 1 
      Tag = Str((NewButtonPosn - slrLeft) / (slrRight - slrLeft) * 100) 
      c.SetAttrib "PainResponse" , Tag
      CSlideImage(Slide1.States.Item("Default").Objects(1)).X = 139
      Slide1.Run
   Case 5 
       Do
	  StopLoop = StopLoop + 1
          If (Slide1.RESP = Empty) OR (StopLoop = 1) THEN
  	     StopLoop = StopLoop + 1
             If ButtonPosn >= slrLeft + 2 Then
              NewButtonPosn = ButtonPosn - 2
             Else
              NewButtonPosn = slrLeft
             End If
              CSlideImage(Slide1.States.Item("Default").Objects(1)).X = 
NewButtonPosn	   
              ButtonPosn = NewButtonPosn    
              Slide1.InputMasks.Reset
    	      Slide1.InputMasks.Add Keyboard.CreateInputMask("12345", "", Val
(Slide1.Duration), Val("1"), ebEndResponseActionTerminate, True, "", "", "")
              Slide1.Run
          Else
	     StopLoop = 501
	  End If
              Loop until StopLoop > 500
 		
 End Select

 If FinalSelection = 0 Then
   Goto Label1
 End If

---------------------------------------------------
Visual Analog Scale Code Explained
---------------------------------------------------
The VAS code is composed of three cases (i.e. key-presses) and several loops. 
The subject   enters the first loop as soon as he/she sees visualizes the slide 
(Case Select...End Select...Go to Label 1 if...).  Since the duration of Wait1 
is infinite, E-Prime waits indefinitely for some kind of input from the 
subject.  This input is collected by the wait object (KeyAscii = Wait1.RESP).  
Acceptable input  = 1, 3, and/or 5.  If the subject enters either 1 or 5, then 
he/she enters the second loop (Do...Loop Until).  This loop changes the 
numerical value of ButtonPosn and NewButtonPosn by +/- 2 pixels and changes the 
position of SliderButton2 on the screen.  Note that the values of ButtonPosn 
and NewButtonPosn are constrained by the values of slrLeft and slrRight.  This 
is to prevent the vertical bar from straying outside of the scale’s limits.  
Also, note that the position of SliderButton2 does not change until Slide1 is 
run (Slide1.Run).  Since the second loop is looking for input from the Slide1 
and since Slide1 only has a duration of 80 ms, the computer moves the position 
of SliderButton2 approximately 10 times per second.   Unfortunately, this low 
refresh rate makes the bar flash a little while it is moving and it is not 
possible to fix the problem without severely hampering the efficacy of the VAS 
(explained in point v).  

There are two ways out if the second loop.  The normal way out is to press a 
key on the keyboard.  This changes the value of Slide1.RESP to something other 
than empty and, therefore, prevents the subject from entering the second loop 
again.  The second way is just a safety net; to prevent the computer from 
entering a never-ending loop, the computer counts the number of times it has 
gone through the loop (StopLoop = StopLoop + 1) and exits when it reaches a 
number > 300 (Loop until StopLoop > 300).  Once the subject has exited the 
first case, the computer exits the Select Case
End Select function, realizes 
that FinalSelection still equals 0, and then returns to Label1.  The entire 
process then repeats itself.

The only way to exit the first loop (and finalize the position of 
SliderButton2) is to press #3.  This instructs the computer to do several 
things.  First, it changes the value of FinalSelection from 0 to 1.  Second, it 
computes the position SliderButton2 on the scale as a percentage (Tag =).  
Third, it records that value in an. edat file (c.SetAttrib “NameOfColomn”, 
Tag).  Fourth, it resets the numerical values of ButtonPosn and NewButtonPosn.  
Fifth, it moves the position of SliderButton2 so that it equals the numerical 
values of ButtonPosn and NewButtonPosn (Slide1.Run).  The computer then moves 
to the next part in the paradigm.

This code has one major flaw.  The computer can only collect input from the 
WaitObject or the SlideObject during the object's duration.  Since it takes a 
small amount of time for the computer to perform the rest of the code, it is 
possible for the subject to press a key without the code entering or exiting a 
loop.  Increasing the SlideObject’s duration decreases the probability of this 
happening.  In my opinion, the optimal length of the duration is 80 ms, but 
that time length can be increased.  If the duration is increased, however, it 
will take longer for the program to move the image 2 pixels.  The motion will, 
therefore, look somewhat jerky.  Even though the computer will catch more key-
presses, the efficacy of the Visual Analog Scale will be decreased.  
Unfortunately, since this flaw is caused by a hardware rather than a software 
problem, it is not easily patched.  It is rumored that IFIS is working on new 
box that fixes this problem, but, as of July 2003, it had not been completed.

---------------------------------------------------------
Explanation of particular lines of code: Destroying the Black Box
---------------------------------------------------------
1) Slide1.InputMasks: this section of code tells the computer to look for input 
from Slide2.  I do not know what all of the values mean; this code was cut-and-
pasted from another portion of the E-Prime code.

2) CSlideImage(Slide1.States.Item("Default").Objects(#)): another, more 
complicated, name for SliderButton2.

3) CSlideImage(Slide1.States.Item("Default").Objects(#)).X : the pixel position 
of SliderButton2.

4) Slide1.InputMasks.Reset: Empties the value of Slide1.Resp.

5) Slide1.InputMasks.Add Keyboard.CreateInputMasks
: This is a really strange 
way of telling the computer to collect the input from Slide1.  In this 
particular case, the numbers 1, 2, 3, 4, and 5 are acceptable kinds of input.



More information about the Eprime mailing list