PXLab Manual

[Home]    [Content]    [Previous Chapter]    [Next Chapter]


The Experimental Design Editor


The PXLab design editor has not yet been updated to version 2. It is still based on PXLab version 1 and will create design files which are not compatible with PXLab 2. We thus recommend not to use it for the creation of PXLab 2 design files.


In this chapter we define a simple experiment using the PXLab Experimental Design Editor. The experiment we create is a choice response time experiment. The stimulus is a left or right pointing arrow and the subject's task is to press a corresponding response key as fast as possible. The experimental question asked is whether left and right responses are equally fast. The independent variable is the arrow direction and the dependent variable is the response time.

To define a new experiment we use the PXLab Design Editor. After starting the program it opens a new design tree window and shows a default design tree. The default tree has a root node called Experiment and has the tree top level nodes Context, Factors, and Procedure.

The Context node defines the experimental stimuli. We open the Context node and see that there already are several subnodes:

The AssignmentGroup node contains global parameter assignments which we will treat later. The Session node defines the stimulus display shown at the start of a session. The SessionEnd node defines the closing stimulus of a session. Block and BlockEnd do the same for a block of stimuli, however, these are only shown between successive stimulus blocks. The Trial node finally defines the stimulus for a trial. We begin with defining the start of a session.

The Start of a Session

We want our experimental session to start with a message telling the subject that he or she may start the session by simply pressing the space bar of the keyboard. When the space bar is pressed then there should be a delay of 300 ms and then the first trial should start.

We open the Session node and see that by default the session starts with a Message display:

The Message display object is a text paragraph centered on the screen. Its duration is controlled by the experimental parameters Timer and Duration. Opening the Message node shows us a list of parameters of this display object:

Most of the parameters are set such that we can use the default values. We only want to change the message text here. This can be done by two ways: We can edit the design tree directly by triple-clicking on the assignment node or we can open the node's popup menu and select the entry named "Edit value". We chose the first method and enter the new text:

Note that we use the character sequence "\n" to indicate a new line character in the text. Thus the text output on the screen will look like this:

Press the
SPACE bar
to start the experiment!

The parameter definition

     Timer = de.pxlab.pxl.TimerCodes.RELEASE_RESPONSE_TIMER

defines the display object's timer to be a timer which waits until the subject releases the response key. Thus the message text is shown and then the program waits until the subject has pressed and released a response key. In order to make sure that only the space bar may be used to start the experiment we can define the parameter ResponseSet to contain only the space bar:

      ResponseSet = de.pxlab.pxl.KeyCodes.SPACE_KEY

Note that design files may contain references to public integer constants defined within PXLab classes. These constants must be addressed by their name prefixed with the PXLab package and class name.

Now we have defined the message which starts the session. Since we want to have a 300 ms delay after the message disappears we have to add another display object to the Session node. This must be a ClearScreen object since nothing is to be shown. To add the ClearScreen object we point at the Session node and press the right mouse button in order to get this node's popup menu. From "Add Display from Menu" we select the "Clear Screen" submenu and from this we select the "Clear Screen Display" object:

Selecting the ClearScreen object opens a dialog which asks for a name for this ClearScreen object:

This name is necessary since there may be several ClearScreen objects being used within the experiment. We enter "Session" as the instance name of the ClearScreen object and press the dialog's "OK"-Button.

This adds a new instance of the class ClearScreen named "Session" to the display list of the Session node:

Note that the name of the new instance of the class ClearScreen is "ClearScreen:Session" in order to indicate that this instance of the ClearScreen class has the instance name "Session".

Since the new ClearScreen object's parameters still have its default values we have to open the new node and modify its timing parameters. We assign to it a clock controlled timer and set the duration to 300 ms:

This finishes the session start display. We start with a message on the screen which is visible until the subject presses and releases the space bar. Then there is a 300 ms delay and then the first trial starts.

We now can modify the SessionEnd node in a way such that it simply shows the string "E N D" for a fixed duration of 2 seconds and then stops the program:

We do not modify the Block() and BlockEnd() nodes since these are only shown if an experiment contains more than a single block. This will not be the case in this little demo experiment and thus we do not need to change the defaults.

Excursion: Using the Display Editor to Edit Display Objects

Up to now we always have used the keyboard to enter parameter values of display objects. The Design Editor also has access to PXLab's Display Editor. We show its use for the Message object of the SessionEnd node. Suppose we have not yet set the properties of the SessionEnd Message object. We then point at the Message object and open the pop up menu by pressing the right mouse button:

Activation of the "Edit" entry opens the Display Editor for the Message object:

The Display Editor shows the color view of the display object. We change to the geometry view by pressing the "Geometry" button and chage the text to "E N D" by entering the string into the respective text field of the parameter "SessionEnd.Message.Text". Note that the text is shown immediately.

We now switch to the timing view by pressing the "Timing" button and select the "CLOCK_TIMER" and set the "SessionEnd.Message.Duration" parameter's value to 2000 ms:

This finishes the Message object for our SessionEnd node. We press the "OK" button of the Display Editor and switch back to the Design Editor. The Message object parameters show those values which have been entered into the Display Editor. This finishes our short excursion into the Display Editor and we move back to our experiment.

The Trial Display

A single trial of our simple experiment should look like this: First the signal is shown. This is an arrow which either points to the left or to the right. The subject then has to respond with pressing the corresponding arrow key on the keyboard. When the subject presses the key the arrow disappears and is replaced by a feedback message. If the response direction was correct then the response time is shown as a feedback. If the response was to the wrong side then a warning is shown. The feedback message is visible for 500 ms and followed by a delay of 2 seconds until the next signal appears.

First we open the Trial node and remove the default Message display object by pointing at the Message node, pressing the right mouse button, and and selecting the "Remove" item from the popup menu.

We then add the arrow display by pointing to the Trial node, pressing the right button and selecting the Arrow object from the "Simple Geometry" submenu of the "Add Display from Menu" popup menu entry:

This, again opens a dialog for naming this instance of the display class Arrow:

We can leave the text field empty in this case since there will be only a single instance of class Arrow in our experiment. Thus the instance name simply becomes "Arrow".

We now have to modify some of the parameters of the Arrow object:

  1. The Timer parameter must be set to de.pxlab.pxl.TimerCodes.LIMITED_RESPONSE_TIMER. This assigns a timer to the Arrow object which is stopped by the subject's response or a fixed duration clock whichever comes first.
  2. The Duration parameter is set to 1200. This defines the time out limit for responses.
  3. The Color parameter of the arrow is set to [80.0, 0.313, 0.329] which corresponds to white at 80 candela per square meter.
  4. The parameter ResponseSet is set to an array which contains only the admissible response key codes. These are the left and right arrow keys which have the codes 37 and 39 respectively.

    Note that setting the parameter ResponseSet not only restricts the set of possible response keys but also enables a translation mechanism. This translates the response key codes to response code values which correspond to the position within the array ResponseSet. In our case this means that if the response set is defined to be [37, 39] and the actual response key has the code 39 then the parameter ResponseCode is set to 1 which is the index of the code 39 in the array ResponseSet. We thus have two possible ResponseCode values: 0 and 1.

    Also note that the current version of PXLab does not yet allow symbolic constants within array values.

Thus the parameters of the Arrow stimulus object look like this:

Note that we did not set the Orientation parameter which will be the independent variable in our experiment. This parameter will be set later when we define the parameters for every single trial of the experiment.

The next display object in our trial display list is a Feedback object. We add it by pointing to the Trial node, selecting "Add from Menu" from the popup menu and choosing the "Feedback Message" from the "Feedback" submenu. Here too we do not use an instance modifier such that the design editor enters the instance named "Feedback" to the display list:

The Feedback display class essentially is a text paragraph display object where the text to be shown is defined by conditions which are related to parameter values of other displays. The parameter Evaluation of a feedback object defines how the evaluation is done and the parameters CorrectText and FalseText contain the respective text strings for correct and false responses.

The response in our experiment is stored in the parameter ResponseCode of the object named Trial.Arrow. Note that the full instance name of a display object has its display list name as a prefix. The response code may only be the code corresponding to the left or the right cursor key as translated by the ResponseSet mechanism. For every trial we will have to tell the Feedback object which of these codes is the correct response. This is done by setting the parameter CorrectCode of the Feedback display object. This, however, is not done now, but only later when the single trials are defined. For now we have to tell the Feedback object which type of evaluation to use by setting the parameter Evaluation to the value de.pxlab.pxl.EvaluationCodes.COMPARE_CODE and the parameter ResponseParameter to "Trial.Arrow.ResponseCode". This results in the following behavior: The feedback object compares the value of the parameters CorrectCode and Trial.Arrow.ResponseCode. If these are equal then the string contained in CorrectText is shown as a feedback. If the two parameter values are not equal then the string contained in parameter FalseText is shown.

Thus we make the following modifications of the parameters of the feedback object:

  1. Set Timer to a fixed clock timer de.pxlab.pxl.TimerCodes.CLOCK_TIMER.
  2. Set Duration to 500 ms.
  3. Set Evaluation to the value de.pxlab.pxl.EvaluationCodes.COMPARE_CODE
  4. Set ResponseParameter to "Arrow.Trial.ResponseCode".
  5. set CorrectText to "%Trial.Arrow.ResponseTime% ms". This results in showing the response time since the parameter Trial.Arrow.ResponseTime contains the subject's response time and any parameter name enclosed between percent signs is replaced by its current value.
  6. We do not need to set FalseText since we can keep the default value "False!".

The Feedback object then has these parameter values (we show only those which have been changed):

Many experimental parameters have a strongly restricted set of possible values. The Design Editor knows about the set of possible values for most of the experimental parameters. Thus in order to find out what the possible values of a parameter are we have to point at the respective assignment, open the pop up menu by pressing the right mouse button and chose the "Edit" entry. Doing that for "Evaluation" opens the editing dialog for "Evaluation":

We activate "COMPARE_CODE" and press the "OK" button.

Finally we add a ClearScreen object to the trial display list, give it an instance name "Trial", assign it a clock timer and set its duration to 2000 ms:

Note that we can remove those parameters from the design tree node which have their default values.

We now have defined the stimuli for our simple choice response time experiment. The next step is to look at the factorial structure of the experiment.

The Experimental Factors

The Factors node defines the independent and dependent factors of an experiment. Our experiment is a very simple design with only a single factor, the direction of the stimulus arrow. The question posed by the experiment is whether left and right responses are equally fast. The independent factor is the direction of the stimulus and the dependent factor is the response time. The independent factor has 2 levels: left and right.

The Factors node of the default design has already an independent factor defined. However, we want to change its name and we also have to define the operationalizing parameters of the factor. When defining an experimental factor we usually will use a symbolic name for the factor. In our example we use "Direction" as the name of the independent variable factor. Every factor must have one or more operationalizing parameters. These describe properties of a display object which actually operationalize the experimental factor.

Which parameters of our stimuli operationalize the experimental factor? There are two parameters: The parameter Orientation of the arrow object and the parameter CorrectCodeof the Feedback object. To edit the IndependentFactor node we point at the node, open its popup menu, and select the "Edit Factor" item:

This opens the dialog for editing Factor nodes. We enter the factor name "Direction" and aczivate its operationalizing parameters: Trial.Trial.Orientation and Trial.Feedback.CorrectCode. We also define the factor as a within-factor since every subject will run all conditions:

Our independent factor has two factor levels: left and right direction of the stimulus array. In order to define the factor levels we press the "Define Factor Levels" button of the factor editing dialog and enter the factor levels:

We use the value 1 for the left direction and 2 for the right direction. The arrow orientation has to be a rotation of 180 degree for left and of 0 degree for the right direction. The correct response code for the left arrow is 0 and for the right arrow it is 1. These values correspond to the index positions of the actual key codes de.pxlab.pxl.KeyCodes.LEFT_KEY (37) and de.pxlab.pxl.KeyCodes.RIGHT_KEY (39) in the array ResponseSet of the Arrow stimulus object. After closing the dialogs we see the independent factor definition in our design tree:

We then point to the default dependent factor node, open its popu menu and edit this factor. We select the experimental parameter Trial.Arrow.ResponseTime as the dependent factor:

This concludes the definition of the Factors node. We have defined an independent factor, the stimulus arrow direction and a dependent factor, the response time. The independent factor has two factor levels, left and right direction of the stimulus arrow:

So we are now ready to define the trials of the experiment.

Sessions, Blocks, and Trials

Sessions, blocks, and trials are defined in the Procedure node of the design file. By default we have a single session containing a single block with a single trial:

We will neither add sessions nor blocks but will define additional trials. However, before adding trials we have to look at PXLab's mechanism for defining experimental parameters for trials. We have already defined what happens during a single trial in the Trial node of the Context section. We have an Arrow object, a Feedback object and a ClearScreen object. All of these have experimental parameters which define their properties. However, these properties have to be modified by the experimental conditions which are realized in a single trial. Thus we have to tell every Trial node in the Procedure section which experimental condition is realized by that Trial. This is done by adding the respective factor level code into the Trail node's argument list.

Since our independent factor Direction has two factor levels which have the codes 1 for left and 2 right, we need at least two different types of trials. The first type must realize factor level 1 for left directed arrows and the second type must realize factor level 2 for right directed arrows. We thus might expect the trial defintions to look like

     Trial(1)
     Trial(2) 

for the two factor levels. However, this is not enough. Trial nodes do not only differ by the independent factor level they will also differ by the dependent factor value. This value, however, is not yet known when defining the trial. Unknown parameter values are described by a question mark in PXLab. Thus our minimal trial definition might look like

     Trial(1, ?)
     Trial(2, ?) 

where the first argument now denotes the factor level and the second argument denotes the yet unknown dependent factor value. How can we tell PXLab what the Trial node argument values actually mean? This is done by listing the parameter names which correspond to the Procedure Trial argument values as arguments in the Trial node of the Context section. So in order to tell PXLab that trials have two arguments where the first argument is the independent factor Direction and the second argument is the dependent factor Trial.Arrow.ResponseTime we list these names as arguments of the Trial node in the Context section.

We go back to the Context node, point at the Trial node to open its popup menu and select "Edit Arguments". This opens a dialog to edit the Trial node's argument list:

The bottom list contains all experimental parameters which are available. Ordering is such that display parameters are listed first and system parameters are listed at the end. Parameters are sorted alphabetically within their respective group. Note that entering "Direction" as a factor name has implicitly created a parameter named "Direction" contained in the list. We select "Direction" and press the "Add" button. This moves the "Direction" parameter into the argument list at the top of the window. The same is done for the parameter "Trial.Arrow.ResponseTime":

After closing the argument editing dialog we see the new arguments appear in the Trial node:

Note that the "Trial" prefix of the parameter "Trial.Arrow.ResponseTime" has been removed within the context of the Trial node. Also note that the argument list of the Trial subnode in the Procedure section also has been changed in order to reflect the number of arguments of the Trial node. We see that the Trial argument list of the Trial node in the Procedure section has automatically been changed to have two arguments. We now edit the arguments of the first trial to have the value 1 for the direction parameter and the unknown question mark value for the response time parameter:

Finally we open the popup menu for the Procedure Trial node, duplicate the node and edit the second node to have 2 as its first argument:

Now we have defined two trials, one for each level of the independent factor. Of course we actually need more than two trials but all other trials we need are copies of the two different ones we have already defined and PXLab has a simple mechanism built in to replicate defined Procedure Trial nodes.

There is a global experimental parameter named TrialFactor which defines how often each defined Trial is presented. The parameter TrialFactor is part of the Context section and may be included into the AssignmentGroup node which by default is defined as a subnode of Context. We go back to the Context node, open the AssignmentGroup node and open its popup menu:

We choose the "Add Assignment" item and the editor opens a parameter assignment editing dialog:

The dialog shows all global experimental parameters and we select "TrialFactor". This adds some parameter value editing tools to the dialog:

We edit the value field such that it defines 2 replications for each trial, this is enough for testing. Closing the dialog adds the respective assignment to the AssignmentGroup node:

This finishes the definition of our experiment. We choose "Save Design" or "Save Design as ..." from the "File" menu and save our definition to a file.

Collecting Data

Our experiment is now ready for a first run. We can open the design editor's file menu and select the "Run in Window" item or we simply push the tool bar button with the same label. This opens a framed window and starts the experiment. The session starts with the session start message. We press the space bar as requested and then we get four trials, two for every experimental condition. What remains to be done is to define where and how the data should be stored.

Every session of an experiment creates a data file. By default the data file name is generated from the subject code. The subject code is a code which is stored in the global parameter SubjectCode and which may be entered at the command line when an experiment is started. We use PXLab's default subject code "pxlab" here since this code generates a special behavior: Repeated sessions with the same subject code overwrite the created data file. This is useful for testing. During data collection we use true subject codes and then data files are not overwritten by PXLab.
To create true subject codes you have to add the parameter SubjectCode to the Procedure node arguments. (For further explication see chapter "Procedure Definition".) This results in a dialog popping up when the experiment is started requesting that the user enters a value - i. e. a subject code for the current subject - for the global parameter:

The directory where the data file is stored is defined by the parameter DataFileDestination. We can set this to "." in order to store the data in the current directory.
Note that you can store the data file on any existing directory on your computer. To store the data on any other directory simply set the parameter DataFileDestination to the adress of the desired directory - e. g.

DataFileDestination = "D:/Experiment/Data"

The data format is defined by the parameter DataFileTrialFormat. This parameter defines the format for the data stored for each trial. The format string is a string which may contain experimental parameter names enclosed in percent characters such that they are replaced by their current values during the experiment. We define DataFileTrialFormat such that the subject code, the factor level, and the response time value is stored for each trial.

Since all of these parameters are global parameters we go back to the AssignmentGroup node and use its popup menu to add these definitions. We may also change the trial replication factor in order to have an acceptable number of repetitions per condition:

That's it. We have defined our simple choice response time experiment and are now ready to collect data.

Additional Features

After running the experiment we may see that some desirable features are missing:
  1. The data file does not contain the information whether the response was correct or not. Solution: Add the parameter Response of the Feedback object to the trial arguments and to the DataFileTrialFormat string. This parameter contains the response as it is evaluated by the Feedback object.
  2. The data file should contain a counter which counts the trials. Solution: Add the global parameter TrialCounter to the trial arguments and to the DataFileTrialFormat string. This parameter is automatically incremented for each trial and thus simply counts the trials.
  3. There should be some trials for training and the data collected in the training trials should not be stored in the data file. Solution: Add a new block of a smaller number of trials whose data are not stored.

Fixing the Data Format

First we add the parameters TrialCounter and Trial.Feedback.Response to the Trial node arguments. We open the Trial subnode of the Context node and select the menu entry "Edit Arguments". We add "TrialCounter" and "Trial.Feedback.Response" to the list of arguments and use the "up"-button to move "TrialCounter" to the first position:

After this is done we see that the editor has automatically changed the argument list of the Trial nodes in the Procedure tree also:

Since both of the new parameters are dependent parameters which are controlled by the program we do not need to set their values in the Procedure tree. However, we have to insert them into the DataFileTrialFormat string in order to store the parameters' values into the formatted data file. We do this by editing the parameter assignment for DataFileTrialFormat in the AssignmentGroup using the "Edit Value" menu entry:

It shows up in the tree:

Adding Trials for Training

Adding a block for training trials requires some more modifications:
  1. We need to add a new Block node in the Procedure tree. As a consequence we also have to define the stimuli for starting and ending a block since we then will have two blocks and these will be separated by block starting and ending stimuli. We did not define these until now since they are not shown if there is only a single block within a session.
  2. The Block node arguments have to be changed in order to tell the program whether the trials in the block have to be stored into the data file or not. The parameter TrialFactor also has to be modified in order to have different factors in the training and the data collection block.

Let's first add another Block node to the Procedure tree. We open the popup menu of our Block node and select the "Duplicate" item. This adds a copy of the selected Block node to the Session node's list of blocks:

Now let's change the Block node argument list. We have to add two parameters: StoreData in order to control whether the data are stored into the formatted data file, and TrialFactor in order to allow for different replication factors in each block.

We open the Context node, triple click on the Block node and enter these two parameters into the argument list:

Note that here the Procedure tree Block node arguments are modified automatically. We then can edit the Procedure Tree Block node argument values for the training block. The StoreData parameter is set to 0 and the TrialFactor parameter value is set to 5. This results in 10 trials for training which are not stored. The parameter StoreData is a boolean flag which is true if the parameter has a nonzero value and is false if the parameter is 0:

A Final Remark on the Parameter Value Scope

Looking at the parameter TrialFactor we see that this parameter now appears two times in our file: (1) it is set in the AssignmentGroup and (2) it is contained in the Block node argument list. This demonstrates the scope rules of PXLab parameter values. In general parameters have global values which are effective for the whole experiment. This rule is overridden if a parameter is contained in the argument list of a session, block, or trial node. In this case the respective parameter value becomes localized to the subtree of the respective node.

Thus the assignment in the AssignmentGroup section assigns a global value to the parameter TrialFactor. Since TrialFactor is contained in the argument list of the Block node it gets local values for each Block of the Procedure section. This local value is effective for the respective Block node and all of its subnodes. Thus TrialFactor has the value 5 for all Trial nodes in the first block and has the value 20 for all Trial nodes in the second block.

In our file we have explicitly defined the TrialFactor argument for the second block. However, we could also use the question mark '?' in the second block's argument list as a value for TrialFactor, since in this case the effective value for the TrialFactor would be the value effective in the surrounding scope which is controlled by the assignment in the AssignmentGroup which assigns the value 20 to the TrialFactor. Thus question marks as parameter values serve a double purpose: (1) they indicate that the respective parameter is a dependent parameter whose value need not be set as for example with Array.Trial.ResponseTime and (2) they implicitly assign the value of the surrounding scope to a parameter. This same mechanism is the reason why parameters like Direction or Feedback.Trial.CorrectCode which have different values for every trial must be Trial node parameters.

There is a subtle difference between the parameter Direction and the parameter Feedback.Trial.CorrectCode: The latter is a parameter of the display object Feedback and is defined by this object's Java class code. 'Direction' is the name of an independent factor. The first name of an independent factor node's argument list always is the factor name. If this is not the name of an existing parameter then this parameter is created at runtime. It can, however, be used as any other parameter. This is the only case where parameters are implicitly created. In general new parameters must be created by explicit statements for creating a new parameter which could look line

     new Direction = 0
and are allowed everywhere where an assignment statement is allowed.

The Final Design File

The complete experimental design is contained in the file crt_simple.pxd.

[This file was last updated on July 15, 2010, 12:07:01.]

[Home]    [Content]    [Previous Chapter]    [Next Chapter]