PXLab Manual

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


Experimental Stimuli

Stimuli are composed of Display objects. These stimuli are called DisplayList in PXLab. There are 7 DisplayList types: Procedure(), ProcedureEnd(), Session(), SessionEnd(), Block(), BlockEnd(), and Trial(). These Stimuli are presented at the respective procedural point. An exception is the Block() DisplayList which by default is not shown for the first and the BlockEnd() DisplayList which by default is not shown for the last block in a session. This behavior may be changed by setting the global parameter SkipBoundingBlockDisplays to 0.

An experimental design may contain multiple definitions of a DisplayList type by adding an instance modifier to the declaration:

    Trial:Study(...) {
      ...
    }
    Trial:Test(...) {
      ...
    }

This defines two types of Trial() DisplayLists, one called 'Trial:Study' and one called 'Trial:Test'. These definitions are completely independent. They may be used later in the Procedure()-section of the design at any point where a Trial() is admissible. The same mechanism is available for other DisplayList types.

Sequential Presentation

The Display objects in a DisplayList are executed strictly in sequence. A Display object is painted to the screen at the start of its presentation interval and remains there until it is replaced by the next Display object. Visual Display objects always have a background area as one of their elements. Thus every visual Display object erases the preceding visual Display object. An exception to this rule is a Display object which has the Overlay flag set. This will be treated later.

Display objects themselves are composed from a series of DisplayElement objects. The first object in this series is the background DisplayElement. The following DisplayElement objects depend on the type of Display object. It may be a text string, a geometric object, an image, or anything else. In most cases the DisplayElement objects of a Display are shown simultanously. A subset of DisplayElement objects of a Display object which is always shown simultanously is called a timing group. The description of the respective Display object contains information about the timing groups of a Display if there are more than a single timing group.

The Timer parameter of a Display object determines its presentation duration. There are three general types of timers: the NO_TIMER, the CLOCK_TIMER and the RESPONSE_TIMER. If a Display has a NO_TIMER Timer value then the presentation interval is 0. This means that the subsequently following Display object is shown immediately after this object has been presented. This only makes sense in combination with the Overlay flag of subsequent Display objects which is described later. A CLOCK_TIMER is a timer with a fixed duration. The duration is defined by the parameter Duration. A RESPONSE_TIMER is a timer which is stopped by some response event. Thus if a Timer is set to RESPONSE_TIMER then the presentation of the respective Display object runs until a response event is detected. The actual duration is then stored in the parameter ResponseTime. The parameter ResponseCode then contains a code which identifies the type of the response event which stopped the timer. A more detailed description of stimulus timing will be given later.

Conditional Execution

Every Display object has an Execute parameter which by default has the value 1. This enables Display execution. If the parameter is set to 0 at runtime then the respective Display object is not shown. This feature may be used for two purposes. One is testing where it might be useful to exclude a Display object from execution. The other one is conditional Display execution. The value of the parameter Execute may be set to a variable which contains the result of some earlier event. In this case the execution of a Display is conditional upon the result of an earlier Display object. Here is an example:

    Trial:Test(TrialCounter, Message:ON.Text, NounType, Feedback:Item.CorrectCode, Message:ON.ResponseCode, TextParagraphMultiple:RK.ResponseCode) {
      TextParagraphMultiple() {
        Timer = de.pxlab.pxl.TimerCodes.NO_TIMER;
	LocationY = 200;
        Text = ["<= old", "new =>"];
	FontSize = commonFontSize;
      }
      Message:ON() {
	Overlay = de.pxlab.pxl.OverlayCodes.JOIN;
        Timer = de.pxlab.pxl.TimerCodes.RESPONSE_TIMER;
        ResponseSet = [de.pxlab.pxl.KeyCodes.LEFT_KEY, de.pxlab.pxl.KeyCodes.RIGHT_KEY];
	FontSize = commonFontSize;
      }
      Feedback:Item() {
        ResponseParameter = "Trial:Test.Message:ON.ResponseCode";
        Evaluation = de.pxlab.pxl.EvaluationCodes.COMPARE_CODE;
	Visible = 0;
        Timer = de.pxlab.pxl.TimerCodes.NO_TIMER;
	FontSize = commonFontSize;
      }
      TextParagraphMultiple:RK() {
	Execute = Trial:Test.Message:ON.ResponseCode == 0;
        Timer = de.pxlab.pxl.TimerCodes.RESPONSE_TIMER;
	LocationY = 200;
	Width = 800;
        Text = ["<= remember", "know =>"];
        ResponseSet = [de.pxlab.pxl.KeyCodes.LEFT_KEY, de.pxlab.pxl.KeyCodes.RIGHT_KEY];
	FontSize = commonFontSize;
      }
    }

In this example from a remember/know memory task the Display object named TextParagraphMultiple:RK is executed only if the ResponseCode parameter of the earlier Message:ON object is 0. Since Message:ON creates a 0 ResponseCode value only if the subject's response was 'old' the question for 'remember or know' is shown only if the subject responds with the 'old' key to the target item presentation in Message:ON.

Another example may be found in an adaptive method demonstration experiment where conditional execution is used for deciding whether a subject simulation display object should be used or real data should be collected:

        PsychometricFunctionSimulator() {
	  Execute = Simulation;
	  pse = 320;
          jnd = 10;
          StimulusParameter = "Trial.HorizontalVerticalIllusion.CutLine";
        }
        ClearScreen() {
	  Execute = !Simulation;
          Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
          Duration = 200;
        }
	SetParameter:A() {
          Execute = AdaptiveProcedure == de.pxlab.pxl.AdaptiveProcedureCodes.UP_1_DOWN_1;
          Parameter = "result1";
	  Value = Trial.HorizontalVerticalIllusion.CutLine;
        }

Here the value of parameter Simulation decides whether PsychometricFunctionSimulator is executed or not. Also note that the following ClearScreen object is executed only if PsychometricFunctionSimulator is not executed. Note that the parameter Execute is a property of the display object PsychometricFunctionSimulator. this implies that the properties of this display object have to be computed even if it is not run. This means that all display object properties must have valid states in this case also.

Display Composition: Overlays

The Display elements of a DisplayList are in general shown strictly sequentially and every Display object has a background object which automatically destroys the previous Display. However, Display objects may be joined by setting the Overlay parameter of class Display to the value JOIN. The result is such that the DisplayElement objects of a Display are painted on top of any previously shown object and are shown simultanously. No background field is drawn for Display objects having the Overlay parameter set to JOIN.

Thus we may show multiple Display objects simultaneously by setting the Overlay parameter of every Display object but the first to JOIN and setting the Timer of every Display object to NO_TIMER except for the last Display in the sequence. Here is an example from a design file which is a simple slide show:

    Trial(TrialCounter, Picture.FileName) {
      Picture() {
	Duration = 2000;
        Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
	Directory = "/images";
      }
    }

This trial does nothing but present an image file for 2 seconds. Now suppose we want to add the file name as a title line on top of the image. We can do this by preceding the Picture object by a Message object which does have a NO_TIMER value of Timer and set the Overlay parameter of the Picture object to JOINsuch that the message text is not erased when the image is drawn:

    Trial(TrialCounter, Picture.FileName) {
      Message() {
	Text = Trial.Picture.FileName;
        Timer = de.pxlab.pxl.TimerCodes.NO_TIMER;
	LocationY = -160;
      }
      Picture() {
	Overlay = de.pxlab.pxl.OverlayCodes.JOIN;
	Duration = 2000;
        Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
	Directory = "/images";
      }
    } 

There are some restriction to observe for JOIN-overlay objects:

  1. The object preceding a JOIN-overlay object must have its Timer parameter set to NO_TIMER.
  2. The overlay object(s) have to have their Overlayparameter set to JOIN in order to prevent erasing of previously drawn screen elements.
  3. JOIN-overlay objects may contain only a single timing group.
  4. If a JOIN-overlay object has the parameter JustInTime set to 1 then the preceding object also must have set JustInTime to 1.
  5. If a Display object is followed by one or more JOIN-overlay objects and the Display object has its parameter Execute set to 0 then the whole chain of Display objects is not presented. The Execute parameters of the JOIN-overlay objects are ignored in this case.
  6. If a Display object with Execute set to 1 is followed by one or more JOIN-overlay objects and any of the JOIN-overlay Display objects has its parameter Executeset to 0 then this respective Display object is not presented. Thus if the non-JOIN-overlay Display object which precedes a JOIN-overlay has its Execute parameter set to 1 then the Execute parameters of subsequent JOIN-overlay objects are observed.

It is not possible to JOIN-overlay an object which has a timer not equal to NO_TIMER. The reason for this is that PXLab's fast image preloading technique creates the joined display image in a single back buffer before the display is shown. Thus all joined components are actually shown simultanously and the timing for this joined display object actually is the timing of he last display element in a sequence of JOIN-overlay objects.

A simpler version of an overlay without the restrictions of JOIN is the Overlay value TRANSPARENT. Display objects which have the Overlay parameter being set to TRANSPARENT behave exactly like any other display object and do not have any timing restrictions. The only visible effect of the TRANSPARENT code is to supress drawing of the background. TRANSPARENT-overlay objects, however, can not use fast image preloading. Thus they should be avoided if optimal timing precision is required.

The effect of JOIN-overlaying an object with non-zero timer may be achived by a sequence of the original object and a duplicate with a JOIN-overlay. Here is the previous example modified such that the file name alone is shown first for 1 second and then the image is added:

    Trial(TrialCounter, Picture.FileName) {
      Message:first() {
	Text = Trial.Picture.FileName;
        Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
	Duration = 1000;
	LocationY = -160;
      }
      Message:second() {
	Text = Trial.Picture.FileName;
        Timer = de.pxlab.pxl.TimerCodes.NO_TIMER;
	LocationY = Trial.Message:first.LocationY;
      }
      Picture() {
	Overlay = de.pxlab.pxl.OverlayCodes.JOIN;
	Duration = 2000;
        Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
	Directory = "/images";
      }
    } 

Note that the parameter LocationY of the second Message instance is copied from the first instance in order to have only a single place where the text location is being defined.

The same functionality may be achieved simpler by using the TRANSPARENT code for the Picture object:

    Trial(TrialCounter, Picture.FileName) {
      Message {
	Text = Trial.Picture.FileName;
        Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
	Duration = 1000;
	LocationY = -160;
      }
      Picture() {
	Overlay = de.pxlab.pxl.OverlayCodes.TRANSPARENT;
	Duration = 2000;
        Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
	Directory = "/images";
      }
    } 

List Overlays

In some cases it might be useful to have an overlay span multiple Display objects which themselves are not overlays. An example being a test string telling the subject which trial number he/she is currently working at. This may be done by setting a Display object's Overlay parameter to DISPLAY_LIST. In this case the respective Display becomes an overlay for every following Display object of the DisplayList. Here is an example from a previous section:

  Trial(Message.Text, Message.ResponseCode, Message.ResponseTime) {
    Message:Counter() {
      Timer = de.pxlab.pxl.TimerCodes.NO_TIMER;
      FontSize = 20;
      Text = "Trial %TrialCounter%";
      LocationY = 300;
      Overlay = de.pxlab.pxl.OverlayCodes.DISPLAY_LIST;
    }
    FixationMark() {
      LineWidth = 3;
      Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
      Duration = 300;
    }
    ClearScreen() {
      Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
      Duration = 300;
    }
    Message() {
      Timer = de.pxlab.pxl.TimerCodes.RESPONSE_TIMER;
      FontSize = 40;
    }
    ClearScreen:Break() {
      Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
      Duration = 500;
    }
  }

The Display object Message:Counter is defined as a display list overlay. It will be shown with every Display object in the list. The text shown is the string 'Trial' followed by the current value of the parameter TrialCounter. The location of the text is on the bottom of the screen.

The overlay is shown for every Display in the list. If it should be removed earlier then the respective Display object must have the Overlay parameter set to CLEAR_DISPLAY_LIST:

     Overlay = de.pxlab.pxl.OverlayCodes.CLEAR_DISPLAY_LIST;

removes the overlay from the display list beginning at the current Display object.

Just in Time Computing

The Display objects in a DisplayList have to be computed at runtime. This includes the preparation of text strings and other geometric properties which may be time consuming. To optimize Display presentation most of the computing is done at the start of a DisplayList. However, in some cases it may be necessary to delay computing up to that point in time when the Display has to be shown. This is true for cases where one Display content depends on the results of an earlier Display in the same DisplayList. An example might be a feedback element where the response time to a previous Display object is presented in the same DisplayList.

Here is an example where immediately after the response a text string is shown which contains the value of the parameter ResponseTime of the Message object:


  Trial(Message.Text, Message.ResponseCode, Message.ResponseTime) {
    FixationMark() {
      LineWidth = 3;
      Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
      Duration = 300;
    }
    ClearScreen() {
      Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
      Duration = 300;
    }
    Message() {
      Timer = de.pxlab.pxl.TimerCodes.RESPONSE_TIMER;
      FontSize = 40;
    }
    Message:Feedback() {
      Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
      Duration = 1000;
      Text = "%Trial.Message.ResponseTime@i% ms";
      JustInTime = 1;
      FontSize = 40;
    }
    ClearScreen:Break() {
      Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
      Duration = 500;
    }
  }

The Message:Feedback() Display object has the parameter JustInTime set to 1. This has the effect that the parameters of this object are computed only immediately before it is shown. If the default value of 0 for JustInTime were used, then the text string of Message:Feedback() would contain the value of ResponseTime at the beginning of the DisplayList. Since JustInTime is set to 1 the computation of the text string is done after the Message object has been run and its ResponseTime parameter has been set. And thus the text string of Message:Feedback() shows the content of the ResponseTime parameter correctly.

There exists a general feedback object named Feedback which behaves similar to Message, has its parameter JustInTime activated by default and also can do more complicated response evaluation.

Adjustable Display Objects

An adjustable display is a display which is shown repeatedly while one of its parameters is being changed depending on the response key being pressed. This type of adjustment is 1-dimensional such that there has to be a single pair of an up- and a down-key being defined. There also must be a stop key being defined which tells the program to accept the adjusted value.

A display object becomes an adjustable display object if one of its local parameter assignments contains the modifier "adjustable" like in the following example of a horizontal-vertical illusion experiment:

      HorizontalVerticalIllusion()
      {
        BaseLine = 400;
        adjustable CutLine = 400;
        Timer = de.pxlab.pxl.TimerCodes.RESPONSE_TIMER;
      }

The modifier marks the display object as an adjustable object and simultanously defines the respective parameter as the adjustable parameter. The timer associated with the adjustable display's timing group should be a RESPONSE_TIMER otherwise the input keys will not be accepted for adjustment and for signalling the program to finish adjustment.

The respective adjustment keys and the adjustment step size should be explicitly defined in the global parameter assignment section:

 
      AdjustmentUpKey = de.pxlab.pxl.KeyCodes.RIGHT_KEY;
      AdjustmentDownKey = de.pxlab.pxl.KeyCodes.LEFT_KEY;
      AdjustmentStopKey = de.pxlab.pxl.KeyCodes.SPACE_KEY;
      AdjustableStep = 2;

The example shows the default key definitions for adjustment. Note that in order for the above key codes to work properly the parameter ResponseSet must not be defined since it implicitly changes the response key codes!

How does adjustment work? An adjustable display does not alter the way of showing a display list but only affects how the adjustable display itself is presented. Actually the only special thing is that the adjustable display is shown repeatedly depending on which response key code is found. If the response key code is equal to one of the up- or down key codes then the respective adjustable parameter is changed by the current adjustment step size and the display is asked to recompute its properties and is shown again. If the response code is the adjustment stop key then the next display object in the display list is shown.

This procedure is somewhat different from the case where a STOP_KEY_TIMER is being used for a display's timing group. In this case the respective single timing group of this display is shown repeatedly until the stop key defined by the global parameter StopKey is found. For each non-stop key the display object's call-back method keyResponse() is called giving the Display itself a chance to make some modifications. This requires that the Display object has been programmed to handle the changes. The previously defined adjustment method, however, does not need any special modification of the Display object's code. It is applicable to every Display class.

Quick Guide for Setting up an Adjustment Method

  1. Define the adjustment keys and the stopping key you want to use by defining the parameters AdjustmentUpKey, AdjustmentDownKey, and AdjustmentStopKey in the global assignment section. The defaults for these keys are the cursor up/down key and the space-key. You don't need to define these parameters if you accept the defaults.
  2. Also define a proper AdjustableStep which is the size of a single adjustment step which follows a single response key entry. This must also being done in the global parameter assignment section.
  3. Add the modifier prefix "adjustable" to the adjustable parameter's assignment statement in the display declaration section.
  4. Set the adjustable display object's Timer parameter to RESPONSE_TIMER.
  5. Make sure that the Display parameter ResponseSet is undefined and that the adjustable parameter is contained in the trial argument list.

Here is an example for the adjustment methods. It shows the horizontal-vertical illusion pattern of an invertet T and the subject's task is to adjust the vertical line such that it looks equal in length to the horizontal line. Adjustment is done with the cursor left and right keys. The space-key signals satisfaction with the adjusted length. There are six trials in this demo.

Where to Get Display Objects

All Display objects are subclasses of class Display and are all contained in the package de.pxlab.pxl.display. Finding a Display object suitable for a certain experiment may be difficult since there are so many Display objects available. The starting point for finding a Display object may be the PXlab display editor DisplayEditor which contains a selection menu of all available display objects and also is able to show and interactively edit every Display object. The PXLab design editor ExDesignEditor is another way to find Display objects since ExDesignEditor also allows efficient paging through all available Display objects. If none of the available Display objects fits your plans then it is possible to write your own subclass of Display in Java and use it. There is an extra chapter about how to write new Display objects using the PXLab API. This manual also contains a chapter which describes all available Display objects.

Which Parameters Does a Display Object Have?

The parameters of a display are described in the PXLab API doumentation. Special display objects may be found as subclasses of class Display. Whenever ExDesignEditorimports a Display instance it also creates an assignment node for every parameter of the display. Thus the design editor always shows every parameter of a Display object as a subnode of this Display object.

The display editor DisplayEditor also shows every parameter of a Display object in one of its display property panels. There are 3 property panels which cover three mutually exclusive groups of parameters: color, geometry, and timing. The display editor also has a menu entry in its popup menu which can show a textual list of all parameters of a Display object.

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

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