PXLab Tutorial

     

  1. Introduction
  2. PXLab is a software system for the design and execution of psychological experiments. It is based on the Java programming language and PXLab based experiments can be run on every computer system which can run Java programs. This covers Microsoft Windows, Unix and its many derivatives, including Apple Macintosh computers. PXLab experiments are controlled by design files which can be created with any arbitrary text editor and the same design file will run on every operating system. PXLab experiments can also be run as applets under browser control using the same design file which is used for local client applications.

    This tutorial tries to introduce the features of PXLab by examples. The tutorial contains applets which may be run within the browser and it contains exercises which you should work on. You will need to download the example files and edit them with a text editor like Windows Notepad.

    You will have to install a Java runtime environment and the PXLab runtime package on your system in order to run the examples as local applications after you have edited the design files.

    Three Steps to Run PXLab Applications
    1. Make sure that you have the latest Java software installed. You can check this by going to java.com, the download page for the Java runtime environment (JRE). Select 'Verify Installation' (German: 'Installation überprüfen') from the choices offered on this page and press the button labeled 'Verify Installation' on the subsequent page. If the response tells you that you have the latest Java then goto step 2. If you do not have the latest Java software, then go to the download section of java.com and download the latest Java runtime environment. Use the 'Typical setup' installation option and use 'Verify installation' to check whether the installation was successful. [This step is sufficient to run most of the demo applets contained in this manual and on the demo pages.]
    2. Download the file PXLabRT.zip and unzip it into a PXLab installation directory of your choice, c:\pxlab say. You will need a program to unzip the archive PXLabRT.zip. If you do not have such a program installed then Windows will offer you to open the zip archive directly. Create your destination directory c:\pxlab with the file explorer in this case and copy the archive content into this directory.
    3. Use your file explorer to find the file named pxlab.jar in the PXLab installation directory. Double click on this file and the PXLab ExRun control program starts with its Open Design File dialog. Go into the subdirectory of your installation root named pxd and choose a design file (a file with extension pxd) from this subdirectory and the experiment will start.

    Although this tutorial will in some cases refer to Windows features you should keep in mind that the core of PXLab is pure Java code and thus you will be able to run the examples of this tutorial on every system where a Java runtime environment is available.

     

  3. Basic Design File Structure
  4. Every experiment which is run by PXLab is defined in a design file. This is a text file which can be edited using any text editor which does not insert text formatting information into the text file. On a Windows system Notepad is appropriate for this task. Design files usually have the extension pxd.

    Let's start with a very simple example. Suppose we want to measure the binary choice response time to a left/right signal. The signal has two states: left or right and the subject has two response alternatives: the left and the right mouse button. The first version of our experiment will use a single word as a signal. The signal either is 'left' or is 'right'. The signal will be shown on the screen and the subject's task will be to press the corresponding mouse button as fast as possible. Here is a design file which defines such a task:

    Experiment() {
      Context() {
        AssignmentGroup() {
          SubjectCode = "pxlab";
          TrialFactor = 2;
        }
        Trial(TextParagraph.Text, TextParagraph.ResponseTime) {
          TextParagraph() {
            Timer = RESPONSE_TIMER;
          }
        }
      }
      Procedure() {
        Session() {
          Block() {
            Trial("left", ?);
            Trial("right", ?);
          }
        }
      }
    }

      Design File crt_001.pxd

    Every design file starts with the term Experiment. The name Experiment is followed by a pair of round brackets which itself are followed by an opening brace. The last character of the file must be the corresponding closing brace. The content of this pair of braces is the Experiment section. This is the highest level block of a design file. The label Experiment tells PXLab that this starts the definition of an experiment. The round brackets may contain arguments. These are variables which contain information for PXLab at runtime. We will come back to these later. The braces of the Experiment section contain the definition of the major parts of the experiment. A design file is a collection of structured sections or blocks. The highest level block named 'Experiment' contains up to three subsections: the Context, the Factors, and the Procedure section. These sections will be called 'top-level' blocks or sections.

    Experiment() {
      Context() {
         ...
      }
      Procedure() {
         ...
      }
    }
    

    In our case the definition of the experiment contains two top level sections of PXLab: the Context section and the Procedure section. The Context section defines all stimulus properties. The major job of the Context section is to define the stimuli for single trials. This is done by binding together stimuli from the PXLab collection of stimuli and setting their parameters.

    Within the PXLab system the concept of a 'display' corresponds most closely to what we usually call a 'stimulus'. We will consider a single trial to contain multiple stimuli. As an example there may be an attention signal, a target signal and a feedback message within each single trial. Thus we assume a trial to contain a sequence of stimuli or display objects. The notion of a 'display object' relates to the object orientation of the Java programming language and, when talking about design files, we will use the terms 'stimulus' and 'display' as synonyms. Thus in PXLab 'stimuli' correspond to 'display objects' and a trial will be defined by a sequence of stimuli or a sequence of display objects. Such a sequence is called 'display list' in PXLab. A display list is a sequence of display objects and the definition of a trial display list will completely describe what happens in a trial. In addition to defining the trials, the Context section also contains parameter settings for global parameters of an experiment like a repetition factor for trials. Global parameters are parameters which are not directly related to stimuli but may control other features of an experiment. The global parameter settings are collected together in an AssignmentGroup. In our case the AssignmentGroup defines two parameter values. The first is a default value for the global parameter SubjectCode which is used to identify a single subject. The second assignment is a value for the parameter TrialFactor which defines the number of repetitions of each trial. Note that a global parameter is simply set by an equation statement: We have to write the name of the parameter, the equals sign, and the value to be assigned to the parameter. A Context section may contain more than a single AssignmentGroup subsection.

    Experiment() {
      Context() {
        AssignmentGroup() {
          SubjectCode = "pxlab";
          TrialFactor = 2;
        }
        ...
      }
      ...
    }
    

    The most important part of the Context section is the definition of a trial. This starts with the name Trial followed by a list of arguments enclosed in round brackets and then followed by a block which is enclosed in braces. The meaning of Trial arguments will be explained later. The Trial block contains the list of stimulus objects which are shown to the subject during a trial. In our example the list contains only a single display: TextParagraph. This is a display which shows one or more lines of text on the screen.

    Experiment() {
      Context() {
        ...
        Trial(TextParagraph.Text, TextParagraph.ResponseTime) {
          TextParagraph() {
            Timer = de.pxlab.pxl.TimerCodes.RESPONSE_TIMER;
          }
        }
      }
      ...
    }
    

    Every stimulus or display like TextParagraph has many parameters which may be used to define its properties. In our case this may be the font, the color, the position and many more properties. Here we use only three property parameters of the TextParagraph object: the Timer, the TextParagraph.Text, and the ResponseTime.

    The parameter Timer is set to the value RESPONSE_TIMER. This tells PXLab that the time interval for showing the TextParagraph object is stopped by a subject response. Thus the TextParagraph display object will be shown on the screen and then PXLab will wait until it detects a subject response. If this happens, the TextParagraph object will be replaced by the next stimulus object. The parameters TextParagraph.Text, and the ResponseTime are not used within the block defining the properties of TextParagraph, but are used as arguments for the Trial section. This means that the values of these parameters are not fixed but may change its value for every trial. They behave as if they were variables whose values may change for every trial.

    This finishes the definition of the stimulus properties in our example. However, We still have not defined the actual text for every trial which will be shown on the screen. This definition is contained in the list of executable trials which is contained in the Procedure section of the design file. The section named Procedure is contained in the Experiment section and defines the actual sequence of sessions, blocks, and trials of an experiment. We will call the Session, Block, and Trial sections contained in the Procedure section 'procedure units' in order to differentiate them from the corresponding definitions in the Context section. In our simple example the Procedure section contains a single Session, which contains a single Block, and this Block contains two Trials. The Trial entries in the Procedure section do not have a block enclosed in braces but do only have a list of argument values. In this case, the arguments are not names of experimental parameters but are values which will be assigned to those experimental parameters whose names are contained in the argument list of the trial definition in the Context section. We will call the list of parameter names in the argument of a display list definition in the Context section an 'argument list' and we will call the list of values in the argument of a proicedure unit a 'argument value list'. The Trial procedure unit definition

            Trial("left", ?);
    

    implicitly assigns the value "left" to the experimental parameter TextParagraph.Text and the value '?' the the parameter ResponseTime. The value '?' is a place-holder for unknown parameter values which will later be filled with data values. After the trial is executed the experimental parameter ResponseTime will contain the actual response time. Thus this Trial procedure unit definition finally defines the text which is shown on the screen for this trial.

    The Procedure section of our example contains two Trial definitions. One for the 'left' and one for the 'right' stimulus. Since the global experimental parameter TrialFactor is set to 2 in the AssignmentGroup every trial defined in the Procedure section will be shown 2 times. So our design file actually defines four trials. Two with the 'left' and two with the 'right' stimulus. By default the trial sequence will be randomized. The button below starts the experiment. It will be shown in a window and you may use the mouse buttons to respond. Make sure that the mouse pointer is inside the stimulus window when you respond.

    When running this 'experiment' you will immediately notice one major problem: there may be no feedback which tells the subject that the response has been accepted. This happens in those cases where the two identical stimuli are shown immediately after one another. In these cases the screen does not change after the response. What is the reason for this somewhat strange behavior? The reason is that our trial contains only a single stimulus object. Thus repeatedly showing the same stimulus in subsequent trials will not change the screen content.

    The solution to this problem is to insert a second stimulus object which replaces the TextParagraph object immediately after the response has been detected. We do this by inserting a ClearScreen object after the TextParagraph object and define the Timer parameter of the ClearScreen object to be a CLOCK_TIMER. This is a timer which runs for a fixed duration. We use the parameter Duration to define that the ClearScreen object will be shown for 400 ms.

    Experiment() {
      Context() {
        AssignmentGroup() {
          SubjectCode = "pxlab";
          TrialFactor = 2;
        }
        Trial(TextParagraph.Text, TextParagraph.ResponseTime) {
          TextParagraph() {
            Timer = RESPONSE_TIMER;
          }
          ClearScreen() {
            Timer = CLOCK_TIMER;
            Duration = 400;
          }
        }
      }
      Procedure() {
        Session() {
          Block() {
            Trial("left", ?);
            Trial("right", ?);
          }
        }
      }
    }

      Design File crt_002.pxd

    Now the subject will notice that the response has been accepted by the short clear screen between successive trials.

    Exercises

    The following exercises require you to edit a design file. On Windows you may do this in the following way: Start the Windows Notepad editor. Use your browser to open the above design file crt_002.pxd and copy the file's content from the browser window into the Notepad window. Then edit the design file according to the exercise and use 'Save File as' in Notepad to store the new design file into your design file directory or wherever you like. Note that you should select 'All files' in the Notepad file dialog and use the extension 'pxd' for your design file. If you do not select 'All Files' in the Notepad file dialog then Notepad may add the extension 'txt' to your file name and you might have difficulties to find your file later. Then start the PXLab ExRun application by double clicking on pxlab.jar and open and run your newly created design file.

    If there is a syntax error in your design file then PXLab can tell you where the error is. In this case PXLab will open an error dialog box and tell you what type of error had been found and in which line and at which character position the error is.

    1. Modify the design file such that every trial defined in the design file is shown three times.

    2. Modify the design file such that instead of 'left' and 'right' the signal is '<-' and '->'.

    3. Modify the design file such that the clear screen duration between successive trials is 1 s.

     

  5. Extending the First Example
  6. Our first example still lacks some important features of a real experiment. We will now add some of these properties:

    1. We need some type of welcome message for the subject.
    2. The subject should get some feedback about her or his response speed.
    3. We want to check whether the subject responds with the correct response or not.

    Looking at the Procedure section of our design file we see that there actually are four types of procedure objects: Procedure, Session, Block, and Trial. For every procedure object we can define stimuli to be shown when the respective procedure object starts and when it ends. An exception is the Trial procedure which does not have separate stimuli for its end.

    UnitWhen it is presentedHow many instancesnecessary:
    yes/no
    Procedureprogram startsonly one instance can existno
    Sessiona session startsmultiple instances may existno
    Blocka block startsmultiple instances may existno
    Trialwhithin a blockmultiple instances should existyes
    BlockEnda block is finishedmultiple instances may existno
    SessionEnda session is finishedmultiple instances may existno
    ProcedureEndall sessions have been runonly one instance can existno

    The stimuli for the procedure objects are defined in the Context section as we have done for the Trial. Stimuli which are shown in a procedure are called display list in PXLab since they are instances of the class DisplayList. A display list is a sequence of display objects which are instances of class Display. Our design file currently defines only a single display list, the display list for the trial. The display list for our trial contains a sequence of two display objects: TextParagraph and ClearScreen.

    Now lets add a display list for the start of a Session procedure which then will be used as an introduction to the subject. This is done by adding a Session definition to the Context section. The Session definition contains a single display object named Instruction. The Instruction is essentially the same as a TextParagraph but has some special features for introductory screens. We need only set a single parameter of the Instruction object, its TextParagraph.Text parameter.

    Experiment() {
      Context() {
        AssignmentGroup() {
          SubjectCode = "pxlab";
          TrialFactor = 2;
        }
        Session() {
          Instruction() {
            Text = ["Welcome to the Experiment",
                    " ",  
                    "You will see a 'left' and a 'right' signal.",
                    "Your task is to press the respective mouse button as fast as possible.",
                    " ",
                    "Press any key now to start the experiment."];
          }
        }
        Trial(TextParagraph.Text, TextParagraph.ResponseTime) {
          TextParagraph() {
            Timer = RESPONSE_TIMER;
          }
          ClearScreen() {
            Timer = CLOCK_TIMER;
            Duration = 400;
          }
        }
      }
      Procedure() {
        Session() {
          Block() {
            Trial("left", ?);
            Trial("right", ?);
          }
        }
      }
    }

      Design File crt_003.pxd

    Note that we use an array to set the parameter TextParagraph.Text to a complete paragraph of text. Experimental parameter values may be arrays. In this case we have an array of strings. Every single string is a sequence of text characters enclosed between double quotes. The array is a sequence of strings separated by a semicolon and enclosed between square brackets. We use two strings which contain only a space character to generate empty lines. The Instruction object breaks lines into paragraphs of text but observes strings. Thus the start of a new string will always start a new line.

    Now we want to implement feedback for the subject. The first step will be to tell the subject the actual response time achieved. The task then is to show a text on the screen which contains the actual response time. We can do this by showing another TextParagraph object and set its TextParagraph.Text parameter to a string which contains the actual response time.

          TextParagraph:Feedback() {
            Text = "%Trial.TextParagraph.ResponseTime@i% ms";
            Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
            Duration = 1000;
            JustInTime = 1;
          }
    

    This declaration contains several important new features to note:

    The last modification we want to make is to check whether the subject's response is correct or not. This requires two changes of our design file: first we have to tell PXLab for every trial what the correct response is, and second we have to modify the feedback such that it reflects the correctness of the response. The first step requires a change of the Trial argument list. We have to enter the code of the response device which has been activated by the subject into the argument list and we have to enter the correct value of this code. The code of the response is stored in parameter ResponseCode of the TextParagraph stimulus object. So we add 'TextParagraph.ResponseCode' to the Trial argument list.

    In order to tell PXLab what the correct code is, we have to add another parameter which will contain the correct code. This is not a parameter of the TextParagraph stimulus object. We have to create a new parameter for this and can do this in the AssignmentGroup of our Context section:

        AssignmentGroup() {
          SubjectCode = "pxlab";
          TrialFactor = 2;
          new correctCode = 0;
        }
    

    The attribute 'new' creates a new experimental parameter with the given name. Its value is initialized to 0. We can now add this parameter to the list of Trial arguments and can then set its value to the correct response code for every trial.

        Trial(TextParagraph.Text, correctCode, TextParagraph.ResponseCode, TextParagraph.ResponseTime) {
          ...
    

    Remember that Trial arguments are those parameters which can have different values in every trial. This is true for the stimulus text and for the correct response code. These two parameters can be thought of as the operationalization of our independent variable 'orientation'. The parameters for the response code and time also will have different values for every trial since these will store the experimental data.

    The Trial definitions in the Procedure section have to be modified too. They now contain four arguments: The stimulus word, the correct response code, the response code data, and the response time data.

      Procedure() {
        Session() {
          Block() {
            Trial("left", LEFT_BUTTON, ?, ?);
            Trial("right", RIGHT_BUTTON, ?, ?);
          }
        }
      }
    

    Finally we have to define what has to be done with the information about the correct response code. We modify our feedback text. If the response code is correct then we present the response time as before. If the response is false, we change the text to 'False !' and do not show the response time.

          TextParagraph:Feedback() {
            Text = (Trial.TextParagraph.ResponseCode == correctCode)? 
                    "%Trial.TextParagraph.ResponseTime@i% ms": "False !";
            Timer = CLOCK_TIMER;
            Duration = 1000;
            JustInTime = 1;
          }
    

    This is achived by using a conditional expression to define the feedback text. A conditional expression is an expression which looks like

       A? B: C
    

    If the term A is true then the value of this conditional expression is B. If A is false then the value of the expression is C. Usually the term A in a conditional expression is a logical statement. In our case it is

       Trial.TextParagraph.ResponseCode == correctCode
    

    This term is true if the value of the experimental parameter Trial.TextParagraph.ResponseCode is equal to the value of the experimental parameter correctCode. Thus the term is true if the ResponseCode parameter of the TextParagraph object in the current trial is equal to the current value of correctCode. The parameter correctCode is defined by the experimenter and contains the response code which corresponds to the correct response. The correct response for the 'left' signal is the left mouse button. Its code is LEFT_BUTTON. The correct response for the 'right' signal is the right mouse button and its code is RIGHT_BUTTON.

    The term 'B' in our conditional expression is

                    "%Trial.TextParagraph.ResponseTime@i% ms"
    

    This is a text string which contains the current integer value of the parameter Trial.TextParagraph.ResponseTime followed by 'ms'. The mechanism which replaces an experimental parameter name enclosed between two percent signs by its value has been described earlier. The value 'C' in our example is the string

                    "False !";
    

    which only contains the text 'False !'. The result is that the conditional expression contains a string showing the response time in case of a correct response and showing 'False !' in case of false responses.

    Remember the Trial definition:

        Trial(TextParagraph.Text, correctCode, TextParagraph.ResponseCode, TextParagraph.ResponseTime) {
          ...
    

    The corresponding Trial procedure is

            Trial("left", LEFT_BUTTON, ?, ?);
            Trial("right", RIGHT_BUTTON, ?, ?);
    

    The first Trial assigns "left" to Trial.TextParagraph.Text and LEFT_BUTTON to correctCode. This tells the program that LEFT_BUTTON is the correct response for the 'left' signal.

    Also remember that this only works since we have set JustInTime to 1. Only then do we get a valid feedback text since this forces the program to evaluate the conditional expression after the response has been collected.

    Experiment() {
      Context() {
        AssignmentGroup() {
          SubjectCode = "pxlab";
          TrialFactor = 2;
          new correctCode = 0;
        }
        Session() {
          Instruction() {
            Text = ["Welcome to the Experiment",
                    " ",  
                    "You will see a 'left' and a 'right' signal.",
                    "Your task is to press the respective mouse button as fast as possible.",
                    " ",
                    "Press any key now to start the experiment."];
          }
        }
        Trial(TextParagraph.Text, correctCode, TextParagraph.ResponseCode, TextParagraph.ResponseTime) {
          TextParagraph() {
            Timer = RESPONSE_TIMER;
          }
          TextParagraph:Feedback() {
            Text = (Trial.TextParagraph.ResponseCode == correctCode)? 
                    "%Trial.TextParagraph.ResponseTime@i% ms": "False !";
            Timer = CLOCK_TIMER;
            Duration = 1000;
            JustInTime = 1;
          }
          ClearScreen() {
            Timer = CLOCK_TIMER;
            Duration = 400;
          }
        }
      }
      Procedure() {
        Session() {
          Block() {
            Trial("left", LEFT_BUTTON, ?, ?);
            Trial("right", RIGHT_BUTTON, ?, ?);
          }
        }
      }
    }

      Design File crt_005.pxd

    Start the example program and check the feedback by giving correct and false responses.

    Exercises

    1. Check out what happens if you set the parameter JustInTime of the feedback object to 0 such that its display screen is created before the trial starts.

    2. Add a clear screen period of 500 ms duration after the introductory message of the Session procedure.

    3. Change the feedback text such that it tells the subject that the response was false but also reports the response time. Note that if you insert the character sequence '\n' into a string then this creates a new line character.

    4. Add a SessionEnd procedure to the Context section which shows the string 'E N D' at the end of a session. The SessionEnd procedure may be identical to the Session procedure with two exceptions: Its name is 'SessionEnd' instead of 'Session' and it should contain a single display object of class TextParagraph with a constant duration timer and a properly defined text string.

    The file crt_006.pxd contains a sample solution to these exercises.

     

  7. Stimulus Objects
  8. Now that we have set up a first experiment we will see how PXLab defines stimulus objects and their properties. The stimulus objects we have been using so far are

    TextParagraph
    shows a paragraph of text;
    Instruction
    also shows a paragraph of text (and is a special case of TextParagraph), but has some special features which are useful for instruction text.
    ClearScreen
    shows an empty screen.
    Thus the whole example essentially has been built with a single non-empty stimulus object, the TextParagraph object. The different properties of this stimulus object have been defined by setting some of its parameters, like the text content, or its timing properties. We will describe the use of experimental parameters for defining stimulus properties in the next chapter in detail. In this chapter we will introduce some more stimulus objects.

    Adding Additional Stimulus Features

    We stick to our choice response example experiment. The next step is to add an attention signal and to replace the verbal direction signal by a graphic direction cue. The attention signal will be a fixation mark and the target signal will be an arrow pointing to the target direction.

    The PXLab library contains a fixation mark signal called FixationMark. If you click on the link to FixationMark you will arrive at a page which contains the description of the class FixationMark. The term 'class' here refers to the Java programming concept of a 'class'. PXLab display objects are instances of classes with the same name. A Java class is the Java language concept which is used to define programming constructs and its properties. We need not touch the Java internals here. We only might remember that display objects correspond to Java classes and every single instance of a display or stimulus object is an instance of a Java class. The major feature of Java classes is inheritage: every class is a subclass its superclass and every subclass inherits all properties of its superclass. The superclass of all display objects in PXLab is the class Display. Stimulus parameters which belong to every stimulus are parameters of the class Display and are inherited by all subclasses. Examples for these are the parameters Timer, ResponseTime, or ResponseCode. Other parameters like FixationMark.Size are special for a single class and thus do only exist for this display object.

    The class FixationMark is the actual program element which generates the fixation mark and the class description is the most complete description of all properties of FixationMark which you can get. For our purpose here the most important part of this description is the list of experimental parameters contained in the section with the heading 'Field Summary'. We look at the following properties here:

    FixationMark.Type
    defines the type of the fixation mark. We will use FIXATION_CROSS to get a cross as a fixation mark.
    FixationMark.Size
    defines the size of the fixation mark in pixels.
    FixationMark.LineWidth
    defines the line width of the fixation mark lines in pixels.

    Showing the attention signal should be the first step in a trial. Thus the attention signal must be the first stimulus component to be shown. Its duration should be fixed and it should be replaced by an empty screen. Thus the beginning of the new Trial definition might look like this:

          FixationMark() {
            Type = FIXATION_CROSS;
            Size = 30;
            LineWidth = 3;
            Timer = CLOCK_TIMER;
            Duration = 500;
          }
          ClearScreen:Attention() {
            Timer = CLOCK_TIMER;
            Duration = 300;
          }
          TextParagraph() {
            Timer = RESPONSE_TIMER;
          }
          ...
    

    We have inserted the FixationMark and a new ClearScreen object in front of the TextParagraph object which shows the target stimulus. Note that the ClearScreen object got an instance name added: we call it 'ClearScreen:Attention' in order to differentiate it from the already existing ClearScreen object at the end of the trial. This instance name modifier is necessary since otherwise the display objects cannot be accessed from outside of a trial. Also note that we have set both new objects' Timer parameter to CLOCK_TIMER which results in a fixed duration defined by the parameter Duration. The file crt_007.pxd contains the complete experiment including the attention signal.

    Our next step now is to replace the verbal signal by an arrow. We use the PXLab display object Arrow. The link to Arrow shows us the special parameters of this class in the section 'Field Summary. Note that the Arrow class actually can show a double arrow. By default, however, the left head of the arrow is set to 0 size such that only a single arrow head is shown by default. Here we only have to change the parameters Arrow.Color, and Arrow.Orientation. Here is the definietion of our arrow element:

          ...
          Arrow() {
            Color = lightGray();
            Orientation = 0;
            Timer = RESPONSE_TIMER;
          }
          ...
    

    Note that the Timer value is the same as used before with TextParagraph. The parameter Arrow.Color is set to 'lightGray()' which results in the same color used for all other stimulus elements. We will explain the function 'lightGray()' later. The direction where the arrow points to is defined by the parameter Arrow.Orientation. The value 0 corresponds to a right pointing arrow and the value 180 creates a left pointing arrow.

    Replacing TextParagraph by Arrow requires some further changes in our design file. The most obvious ones relate to the argument list of the Trial definition. Since we replace the TextParagraph object as a stimulus element by the Arrow object we also have to replace the respective parameters in the Trial argument list. The new argument list is

        Trial(Arrow.Orientation, correctCode, Arrow.ResponseCode, Arrow.ResponseTime) {
          ...
    

    Our new independent variable is 'Arrow.Orientation' and the response data now are contained in Arrow.ResponseCode and Arrow.ResponseTime. The feedback text object also refers to the response code data and has to be changed to use the Arrow parameters.

          TextParagraph:Feedback() {
            Text = (Trial.Arrow.ResponseCode == correctCode)? 
                    "%Trial.Arrow.ResponseTime@i% ms": 
                    "False !\n%Trial.Arrow.ResponseTime@i% ms";
          ...
    

    And finally we have to modify the Trial elements in the Procedure section in order to use the new values of the independent variable Orientation:

            Trial(180, LEFT_BUTTON, ?, ?);
            Trial(0, RIGHT_BUTTON, ?, ?);
    

    The file crt_008.pxd contains the experiment with the arrow signal.

    Exercises

    1. Change the instruction text of the last example such that it describes the target signal correctly.

    2. Look into the documentation of the Arrow object to find other parameters which describe the appearance of the arrow, like length and width of the shaft and the head.

    3. The horizontal location of the arrow is defined by the parameter Arrow.LocationX. The origin of the coordinate system in PXLab is at the screen center and the coordinates increase from left to right and from top to bottom. Define the horizontal location such that the right pointing arrow is at the right and the left pointing arrow is a the left border of the screen.

      Hint: The orientation is defined by the parameter with the full instance name 'Trial.Arrow.Orientation'. You may use a conditional expression as described earlier with the condition 'Trial.Arrow.Orientation == 0' to select the right pointing condition and define the horizontal location depending on whether the orientation parameter is 0 or not.

    Images instead of Arrows

    As a final example in this chapter we replace the arrow stimulus by an image stimulus. Suppose we want to have an experiment where two types of images are shown: One group of images contains images of humans and the other group of images contains images of houses. Here are the steps we have to do. These are almost the same steps we had to do when changing from a text patagraph to the arrow stimulus:

    This seems to be all which has to be done. The file crt_010.pxd contains the picture experiment.

    Exercises

    1. If you want to run the experiment on your own machine you will have to also download the images 8105_lores.jpg, 9163_lores.jpg, 8873_lores.jpg, 9160_lores.jpg, and store them on your PC. The directory name in the design file has to be changed accordingly.

    2. When running the last experiment you will notice that every image is shown twice. The reason is that we forgot to set TrialFactor back to 1 in the AssignmentGroup of our design file. You may do this and also change the instruction text as an exercise. The file crt_011.pxd contains the fixed picture experiment.

    Which Stimulus Objects Do Exist?

    As menioned earlier all stimulus objects in PXLab are display objects and all of them are subclasses of the class Display. The documentation page of this class contains a list of all subclasses which currently exist and which are potential stimulus objects. The manual chapter named Stimulus Elements also contains a list of available stimuli and also contains a list of those experimental parameters which are common to all stimulus objects.

    Another way to look at the PXLab collection of stimuli is to start the PXLab Display Editor. Its a relative of the PXLab Vision Demonstrations application and may be started from the button below. See the instructions of the vision demonstrations program on how to use the editor. It lets you select any of the PXLab display objects and shows it on screen. It also shows most of the parameters of every display and lets you mofify the parameter values interactively.

    Exercises

    1. Try to design an experiment which resembles the first experiment of our lab course named 'Simple Response Time to Optic Signals' and described in the first chapter of the book Experimentalpsychologisches Praktikum. A trial starts with a fixation cross as an attention signal. The cross disappears and there is a random time interval with a blank screen. Then there is a target disk and the subject has to respond. We simplify the task by requiring that the response be a button press. After the response has been found the response is shown as a feedback. The independent variable is the luminance of the target disk. There is a dark and a bright target disk. The experimental question is whether the response time is shorter for the bright signal as compared to the dark signal.

      Hints: The target signal may be the display object SimpleDisk and the clear screen period with a random time interval may be ClearScreenRandomTime. Disk color values may be 'darkGray()' and 'white()'.

    2. Extend your program to run 5 trials for every level of the independent variable and take care that the subject instruction is correct.

    3. The target signal is still rather bright for the value 'darkGray()'. So you may use PXLab's method to define color coordinates in a standardized color coordinate system. This is the CIE 1931 chromaticity coordinate system. It defines colors with three coordinates: luminance, and the xy-chromaticity coordinates. A rather dark gray has the coordinates [1.0, 0.309, 0.329], while [90.0, 0.309, 0.329] has the same chromaticity but has a luminance of 90 cd/m2 instead of 1.0 cd/m2. Thus the Trial argument value list may look like

              Trial(white(), ?);
              Trial(darkGray(), ?);
      

      or if you used coordinates directly it may look like

              Trial([ 1.0, 0.309, 0.329], ?);
              Trial([90.0, 0.309, 0.329], ?);
      

      depending on how you have defined your Trial argument list.

     

  9. Names and Values
  10. Its time now to look a little bit closer at the PXLab design file syntax. The first aspect which will be treated in this chapter is the distinction between names and values.

    PXLab design files have their own grammar rules. The complete description of the PXLab design file grammar is written in the so-called 'Backus-Naur-Form'. We do not need the to study the complete grammar here but we may start with simple assignments of values to experimental parameters. Look at the AssignmentGroup section of example crt_008.pxd:

        AssignmentGroup() {
          SubjectCode = "pxlab";
          TrialFactor = 2;
          ...
        }
    

    The first assignment assigns the value 'pxlab' to the parameter named 'SubjectCode'. The parameter name 'SubjectCode' actually is the name (or address) of some storage space in computer memory where the character sequence 'pxlab' will be stored. The double quotes around 'pxlab' tell the program that the character sequence 'pxlab' is to be considered a value and not the name of another parameter. This distinction is necessary since, as we will see later, the PXLab design file syntax allows parameter names not only to apear on the left but also on the right side of an equals sign in an assignment.

    The second assignment assigns the integer number 2 to the experimental parameter 'TrialFactor'. This means that the integer value 2 is stored in the storage space named by 'TrialFactor'. In this case it is not necessary to use double quotes around the value '2' because of a special naming rule in the PXLab grammar: a parameter name never has a digit as its first character. This means that a sequence of characters starting with a digit can never be the name of a parameter but always is a value. Actually the syntax of PXLab is a little bit more restrictive: It requires that any single value evaluates to a literal value. And there are essentially only three types of literal values: integer numbers like '1', '255', or '-17', floating point numbers like '1.5' or '3.141592' and string literals like 'pxlab', or '3ABC'. And the rule is that string literals always have to be enclosed between double quotes when used as values in assignments:

          SubjectCode = "pxlab";
          FileName = "flower.jpg";
          Luminance = 34.2;
    

    Explicit assignments are not the only place where values are used in a PXLab design file. They are also used in the implicit assignments of a Trial procedure argument value list like that of example crt_011.pxd:

        Trial(Picture.FileName, correctCode, Picture.ResponseCode, Picture.ResponseTime) {
    
        ...
    
            Trial("8105_lores.jpg", LEFT_BUTTON, ?, ?);
            Trial("9163_lores.jpg", LEFT_BUTTON, ?, ?);
            Trial("8873_lores.jpg", RIGHT_BUTTON, ?, ?);
            Trial("9160_lores.jpg", RIGHT_BUTTON, ?, ?);
    

    This is an implicit assignment of the string literal value "8105_lores.jpg" to the parameter 'FileName' of the Picture display object.

    This last example also seems to show a violation of the rule that there exist only integer or floating point numbers and literal strings as values. It implicitly assigns the value 'LEFT_BUTTON' to the parameter 'correctCode'. A similar construct has frequently been used to define the Timer parameter:

            Timer = CLOCK_TIMER;
    

    Actually this is not an exception of the rule. 'CLOCK_TIMER' and 'LEFT_BUTTON' are examples of named class constants. These names are defined in special classes and their essential feature is that they have constant values. Thus the name 'CLOCK_TIMER' is not a variable name which can appear on the left of an equals sign and which can be assigned different values but is a name for a constant value. The purpose of giving a constant value a name is to enhance readability of the code. As an example the integer value of 'CLOCK_TIMER' is 513. It is much easier to remember the name 'CLOCK_TIMER' than to remember the number 513. Furthermore changing the source code of PXLab may change the value of 'CLOCK_TIMER'. Thus a design file using the value 513 would no longer work correctly if the value of 'CLOCK_TIMER' had been changed in the program code. It is a convention that class constant names only use upper case letters in order to indicate their special status. A complete list of all known class constants and their defining classes is contained in the PXLab API documentation.

    The above example also shows a special feature of implicit assignments: The character '?' may be used to not assign a value by implicit assignment. This character cannot be used in explicit assignments. Thus the '?'-character can never appear at the right side of an equals sign. If this character is used in an argument value list it may have two purposes:

    We have said that values of experimental parameters in PXLab always are integer, floating point or string values. Actually this is incomplete. The truth is that PXLab values always are arrays of these primitive types and that every value simultanously has an integer, a floating point and a string value. Thus it is syntactically correct to simultanously use the following assigments:

          FileName = 13;
          FileName = 3.141592;
          FileName = "rose.jpg";
          FileName = ["ann.jpg", "mike.jpg", "jack.jpg", "eve.jpg"];
    

    Here is what happens to the internal PXLab values if the various types of assignments are used:

    assigned valuePXLab internal values
    integerfloating pointstring
    131313.0"13"
    3.14159233.141592"3.141592"
    3.843.8"3.8"
    "rose.jpg"00.0"rose.jpg"

    Remember that these assignments are only syntactically correct. This does not say anything about the semantics. In most cases using '13' as a value for 'FileName' will be syntactically correct but it will be semantic nonsense since no file with such a name will exist. Also, in many cases it won't make sense to assign an array to a parameter since the semantics will be such that only the first entry of the array will be used. An exeption we already have been using several times is the parameter Instruction.Text of the Instruction object:

          Instruction() {
            Text = ["Welcome to the Experiment",
                    " ",  
                    "You will see a 'left' and a 'right' signal.",
                    "Your task is to press the respective mouse button as fast as possible.",
                    " ",
                    "Press any key now to start the experiment."];
          }
    

    Here every element in the array corresponds to a line of text. We see that an array is a list of literal values enclosed in square brackets.

    Expressions

    In the previous section we have described assignments of literal values to experimental parameters. The PXLab design language also allows the assignment of expressions to experimental parameters. Expressions may contain literal values, operations, and functions, and may also contain experimental parameters. An example is the conditional expression we have been using for the assignment of feedback text:

            Text = Trial.TextParagraph.ResponseCode == correctCode? 
                    "%Trial.TextParagraph.ResponseTime@i% ms": "False !";
    

    The expression on the right side of the equals sign contains several experimental parameters and operators. The first subexpression is

            Trial.TextParagraph.ResponseCode == correctCode
    

    This subexpression is true if the values stored in the parameter named 'Trial.TextParagraph.ResponseCode' is equal to the value stored in the parameter 'correctCode'. PXLab does not have a special logical or boolean type. It uses the convention that a parameter or expression is true if and only if its value is not 0 and a parameter or expression is false if and only if its value is 0.

    PXlab can handle most of the usual mathematical operations. Expressions may also contain function calls like in the color example:

            Color = lightGray();
    

    Here 'lightGray()' is a function which returns a color value which actually is a floating point arrow with three components. The PXLab manual contains a list of all available functions.

    Exercises

    1. The class constant names for the left and right mouse button response codes are 'LEFT_BUTTON' and 'RIGHT_BUTTON' respectively. Define a new experimental parameter named 'p1' whose value is 1 if and only if the ResponseCode parameter of a TextParagraph object in a Trial is the left button code and whose value is 2 otherwise.

    2. Extending the previous exercise: Define a new experimental parameter named 'p2' whose value is 1 if and only if the ResponseCode parameter of a TextParagraph object in a Trial is the left button code, whose value is 2 if and only if the response code is the right button code and whose value is 0 otherwise.

    3. Extending the previous exercise: Define a new experimental parameter named 'p3' which is true if the response was any of the two button responses and which is false if the response was something else.

    4. Suppose we have a mechanism which generates two random integer numbers and stores them in experimental parameters named 'a' and 'b'. Define new experimental parameters 'x1', 'x2', ... which get the following values:

      1. the sum of a and b;
      2. the product of a and b added to b;
      3. the product of a with the sum of a and b;
      4. 1 if a is equal to b and 2 otherwise;
      5. true if a is larger than b and false otherwise;
      6. true if a is odd and false otherwise;

      Solutions to these exercises are available.

    5. PXLab has a set of positioning functions which return the coordinates of certain screen positions. These are described in the PXLab manual. Use some of these functions and the parameter FixationMark.LocationX of the fixation mark in example crt_007.pxd to define the horizontal position of the attention signal such that it always indicates where the target arrow will point to. Thus as an example if the target arrow will be left pointing then the attention signal position should be at the left screen border. See crt_007a.pxd for the solution.

    6. Modify the previous exercise for crt_007a.pxd such that the attention cue is only valid in half of the trials and that the cue is invalid in the other half of the trials. Hint: You might introduce a new experimental parameter named 'validCue' which is set to true if the attention signal is valid and which is set to false if it is invalid. The solution is in crt_007b.pxd

    Expression Evaluation

    Expressions always have to evaluate to literal constants at runtime. It is important to remember that expressions are not evaluated when read but are only evaluated when the respective parameter is used at runtime.

    Default Evaluation

    By default the experimental parameter values of display objects are evaluated immediately before the display list is shown, which contains the respective display object. As an example consider the Trial display list of example crt_008.pxd. It contains the display objects FixationMark, ClearScreen, Arrow, TextParagraph, and another ClearScreen in that sequence. By default all experimental parameters of all of these display objects are evaluated immediately before the Trial starts. The reason is that PXLab builds all screen content of a display list immediately before the list is presented in order to optimize timing speed. This also means that any changes of parameter values after a Trial has started by default are ignored. Thus by default parameter changes due to subject responses are not used in evaluation.

    Just In Time Evaluation

    If the value of an experimental parameter changes within a trial and this value should be used in a display object then the respective display object has to make sure that its own parameters are evaluated only immediately before the display object is presented to the subject. Thus is done by the experimental parameter JustInTime. This parameter is a parameter of every display object. It is not a global parameter but every display object hast its own private instance of this parameter. If JustInTimeis set to 1 then the respective display object's parameters are only evaluated immediately before the display object is presented. This feature should be used only if necessary since it may speed down the presentation timing. However, it makes sure that the experimental parameter values also use response information which has only been gathered immediately before.

    Thus in our feedback text example the conditional expression is only evaluated when the value of the Text parameter is used. This evaluation has to be done only after the response has been collected since otherwise the parameter 'Trial.TextParagraph.ResponseCode' does not yet contain the actual data value. This is the reason why the parameter JustInTime of the text paragraph display object has to be set to 1. This makes sure that the evaluation of the expression is done only immediately before the text is shown and after the response has been collected.

    Parameter Instance Names

    The feedback example also shows an example of the full instance name of an experimental parameter: 'Trial.TextParagraph.ResponseCode'. Here 'Trial' is the display list which contains the display object 'TextParagraph' and 'ResponseCode' is a parameter of this display object. Experimental parameters come in two groups: Parameters like 'ResponseCode' or 'Timer' which always are parameters of a special display object, and global experimental parameters like 'TrialFactor' or 'SubjectCode' which exist independently of any display object.

    Global Parameters

    Global parameters have unique names and every name uniquely defines the respective parameter. There is no need for an instance name in this case. The same holds for experimental parameters which are created new in the design file. Only global parameter can be created and they must have a unique name. An example for this has been used in crt_005.pxd:

            new correctCode = 0;
    

    This creates a new global parameter which is not associated with any display object and initializes it to 0. This parameter can be used in the same way as any other global parameter.

    Experimental parameters are instances of class ExPar and the API documentation page of this class contains a list of all existing global experimental parameters under the heading 'Field Summary' with a description under the heading 'Field Detail'.

    Display Object Parameters

    In general display object parameters have always be named by their full instance name like 'Trial.TextParagraph.ResponseCode'. There are, however, two exceptions which simplify typing:

    1. If the parameter of a display object is used as an argument in a display list argument list and the respective display object is contained in the display list then the display list prefix may be dropped. Again looking at crt_005.pxd we have the following Trial display list:

          Trial(TextParagraph.Text, correctCode, TextParagraph.ResponseCode, TextParagraph.ResponseTime) {
            TextParagraph() {
              Timer = RESPONSE_TIMER;
            }
            TextParagraph:Feedback() {
              Text = (Trial.TextParagraph.ResponseCode == correctCode)? 
                      "%Trial.TextParagraph.ResponseTime@i% ms": "False !";
              Timer = CLOCK_TIMER;
              Duration = 1000;
              JustInTime = 1;
            }
            ...
          }
      

      In the argument list of the Trial display list the display list prefix 'Trial' for 'TextParagraph.ResponseCode' is dropped. This is an application of the previously stated rule: The Trial display list contains the TextParagraph display object and thus the prefix for the display list in the argument list can be left out. Note, however, that the full instance name of the parameter 'Trial.TextParagraph.ResponseCode' has to be given in the feedback text expression.

    2. If a parameter of a display object is used on the left side of an assignment in a display object definition, then both the display list and the display prefix can be dropped. Thus if the previous example were:

          Trial(TextParagraph.Text, correctCode, TextParagraph.ResponseCode, TextParagraph.ResponseTime) {
            TextParagraph() {
              Text = "left";
              ...
            }
            ...
          }
      

      then the parameter name 'Trial.TextParagraph.Text' can be written as 'Text' within any assignment inside of the definition of the TextParagraph object itself. Note that this only holds for the left side of the assignment. The short hand notation is not allowed on the right side of the equals sign.

    Naming Restrictions

    We previously have stated that new global experimental parameter names can be arbitrary names. This has to be qualified.

    1. Parameter names may never have a digit as their first character.
    2. Some other characters like '?', '.', '-', or quotes are not allowed in parameter names.
    3. Case is observed. Thus 'feedback' and 'Feedback' are different.
    4. Some names are reserved for PXLab design file keywords. These are listed in section 'Keywords' of the PXLab grammar description.

    Multiple Instances of Display Lists and Objects

    The examples in this section assume that there is only a single instance of the display list and the display object used. We have seen earlier that a display list can contain more than a single instance of a display object like TextParagraph. In this case the display object must get an instance modifier which can be any arbitrary name like 'Feedback' to get 'TextParagraph:Feedback'. The instance modifier both for display objects and display lists is separated by a ':'-sign from the class name. Thus if a design file contains multiple instances of Trial definitions it may add instance modifiers like 'Trial:Study' and 'Trial:Test' in order to identify the two different types of trials. The full instance name of an experimental display parameter may get rather large in this case: 'Trial:Study.TextParagraph:Feedback.Text' would in this case be the full instance name of the parameter 'Text' of display object instance 'TextParagraph:Feedback' in display list 'Trial:Study'. Instance modifiers for display lists and objects may be dropped if the names remain unique.

    Exercises

    1. Each of the following new parameter definitions contains an error. Try to find it.

      1. new Block = Trial.TextParagraph.Text;
      2. new 1stName = "one";
      3. new Jack-Daniels = "Drink";
      4. new message = this is easy;
      5. new count = 2ndCount;
      6. new text = Trial.TextParagraph.text;

    2. The parameter TextParagraph.FontSize by default is defined by the following assignment:

        FontSize = idiv(screenHeight(), 28);
      

      Figure out what this means and define the parameter TextParagraph.FontSize such that there fit at least 32 lines of text on the screen. Hint: see the respective manual page on the meaning of the function idiv().

     

  11. Importing Design Node Declarations
  12. Experiments sometimes exist in slightly different variants with most of the declarations being identical. In those cases it is frequently useful to to put some of the declarations into an external file such that more than a single design file can import these declarations and thus always use the same declarations. The main advantage being that a change of any of these declarations has to be done only once and is applied immediately to all those design files which import these declarations.

    The PXLab parser allows importing design nodes from other files. These files must contain a list of design node declarations. Not all nodes may be imported and there are some restrictions as to where importing statements are allowed. The general syntax of the Import statement is

    Import( "directory-name", "file-name");

    This imports the design node list from file file-name contained in directory directory-name. If the directory name is "." then the file to be imported must be in the same directory as the importing file. The Import statement is allowed

    The following example shows several Import statements: The first one imports a Session display list declaration and the second one imports a display declarations.

    Experiment()
    {
      Context()
      {
        AssignmentGroup()
        {
          SubjectCode = "pxlab";
        }
        Import(".", "import_session.ipxd");
        Block(Trial.Arrow.RightHeadLength, Trial.Arrow.ShaftWidth) 
        {
        }
        Trial( TrialCounter, Direction, Feedback.CorrectCode, Color, Feedback.Response, Arrow.ResponseTime)
        {
          ClearScreen:pause()
          {
            Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
            Duration = 1000;
          }
          FixationMark()
          {
            Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
            Duration = 500;
          }
          ClearScreen:wait()
          {
            Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
            Duration = 300;
          }
          Import(".", "import_arrow.ipxd");
          Nothing()
          {
            Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
            Duration = 1000;
          }
        }
      }
      Factors()
      {
        IndependentFactor( Direction, Trial.Arrow.Orientation)
        {
          FactorLevel( "left", 180);
          FactorLevel( "right", 0);
        }
        IndependentFactor( Color, Trial.Arrow.Color)
        {
          FactorLevel( "red", [21.26, 0.621, 0.34]);
          FactorLevel( "green", [21.26, 0.3, 0.55]);
        }
        DependentFactor( Trial.Arrow.ResponseTime);
        DependentFactor( Trial.Feedback.Response);
      }
      Procedure()
      {
        Session()
        {
          Block(180, 120)
          {
            Import(".", "import_trials.ipxd");
          }
          Block(270, 60)
          {
            Import(".", "import_trials.ipxd");
          }
        }
      }
    }
    

      Design File import.pxd

    Here is the content of the file declaring the Session display list.

        Session() {
    	Instruction() {
    	    Text = ["Left / Right Response Time Measurement",
                        " ",
                        "Please press the left or right mouse button as fast as you can, depending on the direction of the arrow you will see.",
                        " ",
                        "Press any key now to start!"];
    	}
        }
    
        SessionEnd() {
    	Message() {
    	    Text = ["E N D",
                        " ",
                        "Thanks for your participation."];
    	    Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
    	    Duration = 2000;
    	}
        }
    

      Design File import_session.ipxd

    And here is the content of the file defining the actual stimuli.

          Arrow()
          {
            Timer = de.pxlab.pxl.TimerCodes.RESPONSE_TIMER;
            ResponseSet = [de.pxlab.pxl.KeyCodes.LEFT_BUTTON, de.pxlab.pxl.KeyCodes.RIGHT_BUTTON];
            RightHeadWidth = 180;
            RightHeadLength = 180;
            ShaftWidth = 120;
            ShaftLength = 200;
          }
          ClearScreen:afterArrow()
          {
            Timer = de.pxlab.pxl.TimerCodes.NO_TIMER;
          }
          Feedback()
          {
            ResponseParameter = "Trial.Arrow.ResponseCode";
            CorrectText = "%Trial.Arrow.ResponseTime@i% ms";
            FalseText = "";
            Evaluation = de.pxlab.pxl.EvaluationCodes.COMPARE_CODE;
            Text = "%Trial.Arrow.ResponseTime% ms";
            Timer = de.pxlab.pxl.TimerCodes.NO_TIMER;
          }
          Smiley()
          {
    	Execute = Trial.Feedback.Response != de.pxlab.pxl.ResponseCodes.CORRECT;
            Mood = Trial.Feedback.Response;
    	Overlay = de.pxlab.pxl.OverlayCodes.TRANSPARENT;
            Timer = de.pxlab.pxl.TimerCodes.NO_TIMER;
          }
    

      Design File import_arrow.ipxd

    The last file to be imported contains a list of trials.

            Trial( ?, "left", 0, <"red", "green">, ?, ?);
            Trial( ?, "right", 1, <"red", "green">, ?, ?);
    

      Design File import_trials.ipxd

    This shows that imported nodes have to follow the same syntax as if these same nodes were contained in the importing file. The imported text is simply inserted at the Import statement's position. Importing is done when the parser reads the main design file. If it sees an Import statement it will create a new parser for the file to be imported and this parser instance will parse the imported file and return the node list created. On return the main parser adds this list of design nodes to the node which is currently being created.

    Imported nodes are always imported exactly as defined in the design file. In some cases it may be necesary to change the behavior of an imported node depending on the importing file. This can easily be done by using experimental parameters as is done in the above example. The imported display node Arrow uses two parameters named RightHeadLength and ShaftWidth. These are declared to be Block parameters. This makes it possible to use different parameter values for these two parameters for the two different imports in the two Blocks of the experiment's Session declaration.

    Finally we may run this example experiment.