PXLab Manual

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


Stimulus and Response Timing

Every Display object has at least the following timing and response parameters:

Timer
defines the timer type which controls the duration of the Display object's main timing group. If the Display object has more than a single timing group then each timing group will usually have its own timer being defined. Possible Timer values are defined in class TimerCodes.
Duration
is the intended display duration of one of that Display object's timing groups which has Timer as its timer type.
TimeControl
contains the actual times when this display's timing groups have been shown. This parameter is set after the display has been shown and uses PXLab's high resolution clock.
TimeError
contains the timing error for every timing group of this display object which has a CLOCK_TIMER. The timing error is derived from the value of Duration and TimeControl.
ResponseTime
stores the actual display duration. For response driven timers this will also be the response time. For clock driven timers this parameter is derived from TimeControl.
ResponseCode
is a code generated by the event which stopped the display time interval. For response driven timers this will be a code generated by the response device. These codes are defined in class KeyCodes. For clock driven timers the code will be TIME_OUT. For media timers like MEDIA_START_TIMER the code will be one defined in class MediaEventCodes. If the parameter ResponseSet is defined then the response codes correspond to the position of the respective response code in the ResponseSet array.
ResponsePosition
contains an integer array with the xy-position of the response device when a response was detected.
ResponseSet
gives the set of response codes (see ResponseCode) which are acceptable as responses for stopping the respective timer. If this parameter is defined, then it also installs a code conversion function such that the actual ResponseCode values are no longer the response device codes but the indices of the respective device code in the ResponseSet array.

Defining a Timer

There basically are two different timing mechanisms: clock controlled timers with fixed durations and event controlled timers whose durations depend on the subject or other external properties. The clock controlled timer is based on PXLab's timing clock whose precision depends on the underlying hardware. The resolution is guaranteed by the Java Virtual Machine and based on the method System.nanoTime(). Note, however, that the timing resolution of the Java Virtual Machine is implementation dependent and may differ between the various operating systems. An event controlled timer is used to control timing by non-clock based events which mainly are subject response events or media events.

The timer for a timing group of a Display is defined by setting the value of the respective timer parameter. If the Display class has only a single timing group then Timer will be its timer parameter. If the Display has more than a single timing group then the timer of each group will be controlled by additional timer parameters whose names end in 'Timer'. A valid timer parameter value is a binary combination of the following timer property codes:

NO_TIMER_BIT
do not use any timer.
CLOCK_TIMER_BIT
use a clock timer.
MOUSE_BUTTON_TIMER_BIT
use a mouse button response as a timer.
KEY_TIMER_BIT
use a keyboard response as a timer.
STOP_KEY_TIMER_BIT
code for using a repeated keyboard response with a special stop key as a timer. The stop-key code is stored in the parameter StopKey. Timing group presentation is repeated until the stop key is detected. The Display object's call-back method keyResponse() is called after every key giving the Display a chance to make modifications.
XBUTTON_TIMER_BIT
code for using an external button box as a response timer. The external button box must be connected to the serial port control lines.
DOWN_TIMER_BIT
Response direction code for key or button press responses.
UP_TIMER_BIT
Response direction code for key or button release responses.
MOUSE_TRACKING_TIMER_BIT
Indicates that the response event includes mouse motion tracking. Some Display objects require this for continuous updating of their properties. The Display's call-back methods pointerActivated(), pointerReleased(), pointerDragged() , or pointerMoved() are called whenever one of the respective events is detected.
STORE_TIMER_BIT
Indicates that this timer's results are stored back into experimental parameters. Must be set for all timers which collect data.
START_RESPONSE_TIMER_BIT
Used for response intervals which span more than a single Display object. It indicates that response time measurement is started when this timer starts.
STOP_RESPONSE_TIMER_BIT
Used for response intervals which span more than a single Display object. Indicates that response time measurement is stopped when this timer stops.
VIDEO_SYNCHRONIZATION_BIT
Synchronizes the display start of the timing group controlled by this timer with the start of the next vertical blanking interval of the video system.
WATCH_SPURIOUS_RESPONSES_BIT
If set then a spurious response which happens during a clock timer interval is stored and replaces the timer duration and stopping code parameter.
SERIAL_LINE_TIMER_BIT
If set then we expect a serial line input response. This is a sequence of characters received across an activated serial port. The sequence is finished by a RETURN character. This timer should only be used for hardware devices which are connected to a serial input channel. It uses serial data transmission while XBUTTON_TIMER_BIT uses only control lines of the serial port and does not use serial data transmission.
VOICE_KEY_TIMER_BIT
Set for using the voice key timer.
SYNC_TO_MEDIA_TIMER_BIT
If set then we wait until a certain media time has been reached.
END_OF_MEDIA_TIMER_BIT
If set then we are waiting for an end of media event.

In order to make it easier to define useful timer properties some commonly used combinations have predefined names:

NO_TIMER
code for using no timer. Timing groups which do not have a timer are shown but are immediately replaced by the next timing group. This is useful if the next timing group works as a JOIN-overlay. This is a method to simultanously show different Display objects.
CLOCK_TIMER
This describes a timer which is controlled by a clock with a fixed delay period and whose actual timing data are stored.
RAW_CLOCK_TIMER
This describes a timer which is controlled by a clock with a fixed delay period and whose actual timing data are not stored.
VS_CLOCK_TIMER
A timer which is controlled by a clock which only starts to run at the start of the next vertical retrace of the video system. It thus creates a timing interval whose begin is synchronized to the vertical retrace of the video system.
WATCHING_CLOCK_TIMER
This describes a timer which is controlled by a clock with a fixed delay period. The display element group controlled by this timer remains unchanged until the respective time period has passed. The timer also watches for spurious responses during the timing interval. The actual time passed is stored in the respective response time parameter. If there is a spurious response detected then this response's time and code are stored in the parameters ResponseTime and ResponseCode instead of the timer's actual time and stopping code.
KEY_RESPONSE_TIMER
This timer uses a keyboard press response to stop its delay interval. The timing and response code are stored.
RELEASE_KEY_RESPONSE_TIMER
This timer uses a keyboard release response to stop its delay interval. The timing and response code are stored.
RESPONSE_TIMER
This timer uses a mouse, a keyboard, or an external button press response to stop its delay interval. The actual timing and response code are stored.
VS_RESPONSE_TIMER
This timer uses a mouse, a keyboard, or an external button press response to stop its delay interval. The actual timing and response code are stored. The start of this timing interval is synchronized to the vertical retrace period.
RELEASE_RESPONSE_TIMER
This timer uses a mouse, a keyboard, or an external button release response to stop its delay interval. The timing and response code are stored.
LIMITED_RESPONSE_TIMER
This element's duration is controlled either by a subject response action as defined by RESPONSE_TIMER or by a time out clock period whatever comes first. The timing and response code are stored.
GO_TIMER
This is a timer which waits for any go-signal of the subject. No clock timing or time out control is involved. The subject's go-response is any of a keyboard, mouse button, or external button release. Usually this response is only used for proceeding within the display. No timing protocol is stored.
LIMITED_GO_TIMER
This is a timer which waits for any go-signal of the subject or of a clock. The subject's go-response is any of a keyboard, mouse button, or external button release. Same as a GO_TIMER timer but with a limited waiting interval.
MOUSE_TRACKING_TIMER
This timer uses a continuous mouse response and stops on mouse button release. The timing and response code are stored. The Display's call-back methods pointerActivated(), pointerReleased(), pointerDragged() , or pointerMoved() are called whenever one of the respective events is detected.

Some Display objects implement a screen button extension of the mouse buttons. This is a rectangular button on the screen which has a text label and acts like a response key while mouse tracking is active. If a mouse button is pressed or released on this button while mouse tracking is activated it generates a mouse button event. The key code for this button is SCREEN_BUTTON. Thus the following definitions will activate a mouse tracking timer and will set the SCREEN_BUTTON as the only acceptable response 'key':

	Timer = MOUSE_TRACKING_TIMER;
	ResponseSet = SCREEN_BUTTON;
The effect is that the subject can move the mouse and the response timer is stopped when a button is released on the screen button area.

A Display object will show a screen button only if two conditions are satisfied: (1) the respective Display object must implement it and (2) it must be activated by setting the global experimental parameter ScreenButtonSize to a nonzero positive value.

STOP_KEY_TIMER
Uses a response which is only stopped by the current stop-key. Other keys may result in some update or adjustment action of the display. The stop-key code is stored in the parameter StopKey. The timing and response code are stored. The Display object's call-back method keyResponse() is called after every key giving the Display a chance to make modifications.
MOUSE_TRACKING_STOP_KEY_TIMER
combines the properties of a MOUSE_TRACKING_TIMER and a STOP_KEY_TIMER
MOUSE_TRACKING_KEY_TIMER
combines the properties of a MOUSE_TRACKING_TIMER and a KEY_RESPONSE_TIMER
MOUSE_TRACKING_RELEASE_KEY_TIMER
combines the properties of a MOUSE_TRACKING_TIMER and a RELEASE_KEY_RESPONSE_TIMER
SERIAL_LINE_INPUT_TIMER
If set then we expect a serial line input response. This is an input across a serial line channel which is stopped by detection of a carriage return character. The input string is stored in the respective timing group's ResponseCode parameter.
VOICE_KEY_TIMER
Set this to use a voice key timer for any arbitrary non-sound display object. Do not use this timer for the VoiceKey display object.
START_RESPONSE_TIMER
Used for response intervals which span more than a single Display object. It indicates that response time measurement is started when this timer starts.
STOP_RESPONSE_TIMER
Used for response intervals which span more than a single Display object. Indicates that response time measurement is stopped when this timer stops.
END_OF_MEDIA_TIMER
Use this timer to wait until a playing or recording media object is finished. The stop event is created when the media processor has stopped playing media data because the end of the data stream has been detected.
WATCHING_END_OF_MEDIA_TIMER
Use this timer to wait until a playing or recording media object is finished and record spurious responses while the media object plays or records its data.
SYNC_TO_MEDIA_TIMER
Use this timer to synchronize to a media object. The sync event is created when the media processor has arrived at a certain media time in playing the media data. The media time is given by the timing group's Duration parameter. Media time is the time relative to the start of the media.

The timer codes are defined in class TimerCodes of the package de.pxlab.pxl of PXLab. Thus in order to assign the respective timer code to a parameter we may write

   Timer = de.pxlab.pxl.TimerCodes.RELEASE_RESPONSE_TIMER;

which assigns the code RELEASE_RESPONSE_TIMER to the parameter Timer. For timer codes this may be simplified to

   Timer = RELEASE_RESPONSE_TIMER;

since class TimerCodes is a member of the package de.pxlab.pxl.

Response Time and Event Data

Every Display object has its own timer and duration parameter. Every Display object also has parameters called ResponseTime, ResponseCode, and ResponseSet. The first two are data parameters which means that their values must not be defined within the design file but are set during run time. These actually are data collected by the experimental run. The parameter named 'ResponseTime' contains the actual duration as measured during runtime. For timers of type CLOCK_TIMER comparing the parameter Duration and the parameter ResponseTime gives some information about the precision of the timing process during runtime. If timing is perfect then these should have the same value. For every timing group of a display the difference between these two parameters is stored in parameter TimeError.

The parameter called 'ResponseSet' restricts the set of admissable response codes to its values. All responses which generate codes not contained in the array are ignored. If the parameter is set like this:

   ResponseSet = [de.pxlab.pxl.KeyCodes.LEFT_BUTTON, de.pxlab.pxl.KeyCodes.RIGHT_BUTTON];

then the only responses which are accepted are the left or the right mouse buttons as these have - as we will see later - the corresponding response codes de.pxlab.pxl.KeyCodes.LEFT_BUTTON and de.pxlab.pxl.KeyCodes.RIGHT_BUTTON.
The parameter ResponseSet does not only restrict the acceptable response set, it also enables a translation mechanism which translates the response codes mentioned above to device independent codes. These are values which correspond to the position of a code value within the array ResponseSet. This means that if the response set is defined as above then the response code corresponding to the left mouse button will be 0 and the response code corresponding to the right button will be 1 which are the respective positions in the array. These translated codes will then be stored in parameter ResponseCode.

The parameter ResponseCode contains information about the event which stopped the respective timer. It will be TIME_OUT for a timer which is stopped by an internal clock. It will be some other value for other timers, like response timesr which are stopped by subject responses. In this case the ResponseCode is a code of the button, key, or device which stopped the timer. These are the valid mouse button codes:

LEFT_BUTTON
left mouse button
MIDDLE_BUTTON
center button
RIGHT_BUTTON
right mouse button

The valid keyboard codes correspond to the virtual key codes as they are defined in class de.pxlab.pxl.KeyCodes. For character keys these are the ASCII codes of the respective characters. Function keys are special:

ESCAPE_KEY
Escape key
SPACE_KEY
Space bar
PAGE_UP_KEY
Page up key
PAGE_DOWN_KEY
Page down key
END_KEY
End key
HOME_KEY
Home or Pos 1 key
LEFT_KEY
Cursor left
UP_KEY
Cursor up
RIGHT_KEY
Cursor right
DOWN_KEY
Cursor down

See class de.pxlab.pxl.KeyCodes for more key codes.

Timing Groups

Display objects are built from groups of DisplayElement objects. These are the primitive objects like bars, disks, or text elements which make up a Display. Multiple DisplayElement objects are grouped together to form a DisplayElement timing group of a Display. This is a group of DisplayElementobjects which have the same timing properties and thus are always shown simultaneously. Thus timing parameters of Displayobjects always refer to DisplayElement timing groups and not to single DisplayElement objects. Most Display objects have only a single timing group and thus the Timer parameter refers to the whole Display object.

A Timing Group Example: The Stroop Experiment

We look at a Stroop experiment as an example. Every trial of this experiment starts with an attention mark which is a cross at the center of the screen. The cross is shown until the subject presses and releases any of the mouse buttons. Following the cross the screen is cleared and remains so for some time. For PXLab this means that a clear screen object is shown for some time. The next object visible is a single text string which usually is a color name and whose letters are drawn in color. While this string remains visible a second string appears only a short time interval later at a position below the first string. The subject's task is to decide whether the second probe string names the color of the letters of the first test string. The two strings remain visible until the subject responds by pressing a mouse button. Immediately after the button has been pressed there appears a feedback text which tells the subject what the response time was. The text is visible for some time and then the screen is cleared until the next trial starts with the attention signal.

The trial of this experiment starts with an attention mark which is visible as long as the subject presses and then releases a response button. This can be achieved by using a RELEASE_RESPONSE_TIMER. The class FixationMark has a single timer parameter called Timer which controls its duration. The Stroop example contains only a single instance of FixationMark such that the instance name need not be used:

    FixationMark() {
      Timer = de.pxlab.pxl.TimerCodes.RELEASE_RESPONSE_TIMER;
    }

After the subject has released the response button in order to start the trial there is a first clear screen period with a fixed duration of 500 ms. Since the Stroop experiments uses more than a single instance of class ClearScreen we have to use an instance name also:

    ClearScreen.wait1() {
      Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
      Duration = 500;
    }

This defines the instance named 'wait1' of class ClearScreen and sets its parameter Timer to a clock controlled timer and its duration to 500 ms.

The next Display object is an instance of subclass TwoStrings. This class has two timer parameters: TwoStrings.SOATimer and Timer. The TwoStrings.SOATimercontrols the time interval between the onset of the test and the onset of the probe string. This interval corresponds to the first timing group of this Display object. The second timer simply named Timer controls the duration of the second timing group which contains both the test and the probe string. The first timing group has a fixed time interval of 100 ms. The second timing group is response controlled but has a time out limit of 5000 ms. The response set of admissible response codes contains only the codes which correspond to the left and the right mouse button respectively:

    TwoStrings() {
      SOATimer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
      SOADuration = 100;
      Timer = de.pxlab.pxl.TimerCodes.LIMITED_RESPONSE_TIMER;
      Duration = 5000;
      ResponseSet = [de.pxlab.pxl.KeyCodes.LEFT_BUTTON, de.pxlab.pxl.KeyCodes.RIGHT_BUTTON];
    }

Note that this example measures the response time as starting from the begin of the probe signal. If the response interval should start with the start of the test signal and last until the end of the probe signal then the TwoStrings.SOATimer must be given the attribute START_RESPONSE_TIMER and the Timer must correspondingly have the attribute STOP_RESPONSE_TIMER:

    TwoStrings() {
      SOATimer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER 
                 | de.pxlab.pxl.TimerCodes.START_RESPONSE_TIMER;
      SOADuration = 100;
      Timer = de.pxlab.pxl.TimerCodes.LIMITED_RESPONSE_TIMER
                 | de.pxlab.pxl.TimerCodes.STOP_RESPONSE_TIMER;
      Duration = 5000;
      ResponseSet = [de.pxlab.pxl.KeyCodes.LEFT_BUTTON, de.pxlab.pxl.KeyCodes.RIGHT_BUTTON];
    } 

In this case the actual response time will be stored in a global parameter named ResponseTime and will not be stored in any of the parameters of the TwoStrings object. This is necessary since the parameters of TwoStrings already store the response data of their respective timing groups.

Finally the Feedback object has fixed duration of 1200 ms and there is a fixed duration ClearScreen object separating one trial from the next:

    Feedback() {
      Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
      Duration = 1200;
    }
    ClearScreen.wait2() {
      Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
      Duration = 1000;
    }
  }

Note that the second ClearScreen object has the instance name 'wait2' in order to discriminate it from the first instance named 'wait1'. Here is the Stroop example with a small number of trials:

The Voice Key Timer

The voice key timer for any non-sound stimulus object is activated by setting the Timer parameter to VOICE_KEY_TIMER. This timer uses microphone input. It waits until the voice key threshold has been passed and sets the parameter ResponseTime to the respective response time. The voice key timer uses the following global parameters:
VoiceKeyThreshold
the threshold value for the voice key.
VoiceKeyRecordingBufferSize
the size of the low level sound input data buffer. This parameter should not be changed. Its default value is 44 and it must be a multiple of 4.
VoiceKeyStopImmediately
a flag which stops voice recording immediately after the voice key threshold has been passed. The default is 'true'. This flag may be set 'false' if the recorded voice is written to a file and analyzed later.

The design file Voice_Key_Timer.pxd contains an example for using the voice key timer.

There also is a special voice key display object named VoiceKey. This works like a sound recording object whose duration is controlled by the voice input signal. This display object allows for full recording of the voice key duration period. Recording is switched on by setting this object's parameter VoiceKey.Directory to a non-zero string. If the global parameter VoiceKeyStopImmediately is 'false' then the full duration voice signal will be recorded. If VoiceKeyStopImmediately is 'true' then recording stops after the threshold has been passed. The VoiceKey object also has a parameter to control the recording sample rate. The design file Voice_Key.pxd contains an example for using the VoiceKey object. Chapter ,Sound and Video' contains some hints how to control the sound input channel for the voice key.

Video System Synchronization

Whenever we have very short video display objects we may want to synchronize the display of these stimuli with the vertical refresh cycle of the video system. PXLab contains a Windows native library which allows video synchronization under Windows using DirectX methods. This does not work for other runtime environments and it does not work for applets since it both violates strict device independence and the security restrictions for applets.

Display synchronization of the objects of a single timing group is achieved by adding the flag VIDEO_SYNCHRONIZATION_BIT to the property mask of a timer. This makes the display controller wait until the next vertical blanking interval starts before showing the objects of the timing group which is controlled by the respective timer. A consequence of this is that the timing interval immediately before the synchronized timer may be longer than requested. Up to one video display cycle may be added.

There also exist timer codes for video synchronization which behave as described in the previous paragraph and may be used fór clock and response timers. These are VS_CLOCK_TIMER and VS_RESPONSE_TIMER. These constitute timers whose start is synchronized with the vertical retrace signal of the video system. Note that if the complete display duration of an object should be synchronized to the vertical retrace then it is not sufficient to synchronize the target object's timer, since this only synchronizes its start time. We also have to synchronize the target object's stop time and this must be done by synchronizing the Display object which immediately follows the target object.

Display List Control Objects

A display list control object is a special type of Display which does not show any objects on the screen but executes some influence on how and which Display objects of a DisplayList are shown. The response timing mechanism uses display list control objects to control a response gate which can define intervals where certain responses are forbidden or certain responses are allowed. This mechanism is also used to check the response state at certain points within display list presentation.

ResponseControlStart
starts a response control interval where spurious subject responses are collected. This is required for cases where it must be guaranteed that the subject does not press any response button before a certain Display object is shown or that the response buttons must be in a certain state before a stimulus can be shown. When this Display is inserted into a DisplayList then all response events which happen during the following CLOCK_TIMER intervals are stored.
ResponseControlStop
stops a response control interval. This Display stops watching for response events during CLOCK_TIMER intervals.
ResponseControlCheck
checks for spurious responses during an active response control interval. This Display object checks whether a certain response event has happened during the most recent response control interval. The following parameters are used to define the response event to be checked for:

These parameters define a response event group to look for, the expected responses. The Display object reports its state to the DisplayList controller via a return flag. If this flag is set then the DisplayList controller immediately stops the current DisplayList.

The actual working of ResponseControlCheck is controlled by the parameter Type which accepts values of class ResponseControlCodes. If the value is ANY_RESPONSE then any spurious response sets the return flag. If the value is LAST_RESPONSE then only the last spurious response is checked and if the value is FIRST_RESPONSEthen only the first spurious response is checked. If the parameter is nonzero and there is a spurious response then the respective response time is stored in the global parameter ResponseTime and the respective response code is stored in the global parameter ResponseCode. If the response is one of the expected responses as defined by the parameters Device, Direction, and Codes, then the return flag is set. If the parameter is not expected or there is no spurious response then the return flag is not set.

Here is an example for using the ResponseControlCheck Display. This is a simple response time measurement experiment. The subject sees an attention signal and then has to press a mouse button until the signal appears. The response is to release the mouse button as fast as possible.

    Trial( TrialCounter, Luminance, ResponseTime) {
      ClearScreen:Pause() {
        Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
        Duration = 2000;
      }
      ResponseControlStart();
      FixationMark() {
        Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
        Duration = 1000;
      }
      ClearScreen:WaitSignal() {
        Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
        Duration = 500;
      }
      ClearScreenRandomTime() {
        Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
        ExpectedWait = 1000;
        WaitingTimeLimit = 3500;
        Duration = 3000;
      }
      ResponseControlCheck() {
        Type = de.pxlab.pxl.ResponseControlCodes.LAST_RESPONSE;
        Device = de.pxlab.pxl.TimerBitCodes.MOUSE_BUTTON_TIMER_BIT;
        Direction = de.pxlab.pxl.TimerBitCodes.DOWN_TIMER_BIT;
        Codes = ?;
        Text = ["Error!",
		" ",
		"Please hold down the response button after the fixation mark appears!"];
        Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
	Duration = 2000;
      }
      SimpleDisk() {
        Size = 300;
        Duration = 100;
        Timer = de.pxlab.pxl.TimerCodes.VS_CLOCK_TIMER | de.pxlab.pxl.TimerCodes.START_RESPONSE_TIMER;
      }
      ClearScreen:WaitResponse() {
        Timer = de.pxlab.pxl.TimerCodes.RELEASE_RESPONSE_TIMER | de.pxlab.pxl.TimerCodes.STOP_RESPONSE_TIMER;
      }
      ResponseControlStop();
      Feedback() {
        Text = "%ResponseTime@i% ms";
        Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
        Duration = 1000;
      }
    }

The trial starts with a ClearScreen shown for 2000 ms and then the ResponseControlStart Display object starts spurious response control. Then there is an attention signal FixationMark which tells the subject to press a mouse button and hold it down until the target signal shows up. The attention signal is shown for 1000 ms followed by a ClearScreen with fixed duration of 500 ms and a ClearScreenRandomTime with random duration of up to 3500 ms and an expected duration of 1000 ms. The subject has to hold down the mouse button during this time and any button release were a spurious response which should lead to stopping the trial. The ResponseControlCheck Display checks for spurious responses immediately before the signal, a SimpleDisk, appears. The ResponseControlCheck has Type set to FIRST_RESPONSE such that the first spurious response is checked and the target is any mouse button response since Direction and Codes are not set to any specific value. If a spuriuos response is found then The error message is shown for 2000 ms and the Trial is stopped. Otherwise the target signal is shown and a Feedback object shows the resulting response time. Check out the trials in the following demo. Remember to hold down the button when then fixation mark appears and release the button as fast as possible when the target signal is shown.

Timing Across Multiple Displays

The preceding example contains one more timing feature of interest here. The target stimulus is SimpleDisk which has a fixed duration of 100 ms. The SimpleDisk is followed by a ClearScreen which actually contains the response timer. Thus the ResponseTime parameter of the ClearScreen object contains the response time but this time interval is reduced by the duration of the SimpleDisk Object. The correct response time interval should start with the start of the SimpleDisk object and end with the following ClearScreen object. This can be achieved by adding the flag START_RESPONSE_TIMER to the Timer of the SimpleDisk object and the flag STOP_RESPONSE_TIMER to the Timer of the following ClearScreen object.

      ...
      SimpleDisk() {
        Size = 300;
        Duration = 100;
        Timer = de.pxlab.pxl.TimerCodes.VS_CLOCK_TIMER | de.pxlab.pxl.TimerCodes.START_RESPONSE_TIMER;
      }
      ClearScreen:WaitResponse() {
        Timer = de.pxlab.pxl.TimerCodes.RELEASE_RESPONSE_TIMER | de.pxlab.pxl.TimerCodes.STOP_RESPONSE_TIMER;
      }
      ResponseControlStop();
      Feedback() {
        Text = "%ResponseTime@i% ms";
        Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
        Duration = 1000;
      }

    }

The effect is that a response interval is measured which starts with the SimpleDisk object and ends with the ClearScreen object. The resulting time interval is not stored in any of the Display object parameters but in the global parameter ResponseTime and the respective event code is stored in the parameter ResponseCode. This is why the Feedback object has the global ResponseTimeparameter contained in the value of its Text parameter.

Response Collection During A Clock Timer Interval

The standard behaviour of PXLab is to not collect any subject response while a timer of type CLOCK_TIMER is running. As an example look at

      Message() {
	Text = "Press any key now!";
        Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
	Duration = 500;
      }

This display object is shown for 500 milliseconds and the response keys are inactive while this time interval is running. Now suppose that we want to collect a subject response while a fixed duration time interval is running. In this case we have to use a timer of type WATCHING_CLOCK_TIMER. This timer behaves exactly like a CLOCK_TIMER but response keys are active while the clock is running. If there is a response event during the timing interval then the respective response time and response code are stored into the Display object's parameters ResponseTime and ResponseCode. Only the first response event in the timing interval is stored!

This mechanism may also be used to control execution of a subsequent display object which only has to be shown when no response event has happened. Here is an example:

      Message() {
	Text = "Press any key now!";
        Timer = de.pxlab.pxl.TimerCodes.WATCHING_CLOCK_TIMER;
	Duration = 2000;
      }
      Message:Why() {
	Execute = Trial.Message.ResponseCode == de.pxlab.pxl.ResponseCodes.TIME_OUT;
	Text = "I am still waiting!";
        Timer = de.pxlab.pxl.TimerCodes.RESPONSE_TIMER;
      }
      Feedback() {
        Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
	Duration = 2000;
        Text = Trial.Message:Why.Execute? 
               "Response Code = %Trial.Message:Why.ResponseCode%":
               "Response Code = %Trial.Message.ResponseCode%";
      }

The first Message object has a WATCHING_CLOCK_TIMER of 2000 ms duration. If there is any response during the display interval then this object's parameter ResponseCode contains the respective response or key code. If there is no response then the response code is TIME_OUT. This is the default response code for CLOCK_TIMER intervals terminating normally. The subsequent display object has ist Execute parameter defined to an expression:

	Execute = Trial.Message.ResponseCode == de.pxlab.pxl.ResponseCodes.TIME_OUT;

This expression is non-zero if the Message object's response code is TIME_OUT. In this case the second Message object is shown if and only if the first Message object did not find any spurious response. Finally the Feedback object uses the second Message object's Execute parameter to decide, which is the response code to use as data:

        Text = Trial.Message:Why.Execute? 
               "Response Code = %Trial.Message:Why.ResponseCode%":
               "Response Code = %Trial.Message.ResponseCode%";

A slight modification is necessary in order to also collect the response time across optional displays as used in this example. We have to use the timer properties START_RESPONSE_TIMER and STOP_RESPONSE_TIMER here in order to get a response time which possibly spans the two successive Message objects:

    Trial() {
      Message() {
	Text = "Press any key now!";
        Timer = de.pxlab.pxl.TimerCodes.WATCHING_CLOCK_TIMER 
		| de.pxlab.pxl.TimerCodes.START_RESPONSE_TIMER 
		| de.pxlab.pxl.TimerCodes.STOP_RESPONSE_TIMER;
	Duration = 2000;
      }
      Message:Why() {
	Execute = Trial.Message.ResponseCode == de.pxlab.pxl.ResponseCodes.TIME_OUT;
	Text = "I am still waiting!";
        Timer = de.pxlab.pxl.TimerCodes.RESPONSE_TIMER 
		| de.pxlab.pxl.TimerCodes.STOP_RESPONSE_TIMER;
      }
      Feedback() {
        Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
	Duration = 2000;
        Alignment = de.pxlab.pxl.AlignmentCodes.LEFT;
        Text = "ResponseCode = %ResponseCode%\nResponseTime = %ResponseTime@i% ms";
      }
    }

The first Message object has set both START_RESPONSE_TIMER and STOP_RESPONSE_TIMER and the second Message object has set STOP_RESPONSE_TIMER. Thus the global parameters ResponseCode and ResponseTime are set by which STOP_RESPONSE_TIMER becomes effective last. Note that we use the global ResponseCode here also to show the response code.

How to Check Proper Timing

In many experiments precise timing is essential. Programs like PXLab which run in a multitasking and non-realtime environment can never guarantee a precision in timing which is high enough for all possible psychological experiments. However, given the current speed of laboratory computers, there will not be many experiments which really need more precision than is available. Although initially PXLab has not been developed with high precision in timing as one of its primary design goals, considerable effort went into the code of PXLab version 2 to make timing as precise as possible. Actually timing precision is the major advance to version 2.

Given the multitasking environment with its timing uncertainty the optimal way to handle timing problems seems simply to be trying things out and check whether they work in an acceptable way. 'Trying out and check' means to run the experiment and look at the timing as it may be measured. Timing measurement may be done externally using special hardware as suggested by De Clercq, Crombez, Buysse, & Roeyers, (2003) or Plant, Hammond & Turner (2004). However it my also be done internally with high precision by using an internal high resolution timer. The high resolution timer used by PXLab is based on the Java method System.nanoTime() which is available in Java version 1.5. This method reports time intervals with nanosecond resolution from the most precise available timer on the system. The Timing Environment Dialog menu entry of the ExDesignEditor application may be used to investigate which of several possible high resolution timers PXLab is actually using.

This example shows a configuration where PXLab uses the Java 5 nanoTime() method of class System as its high resolution timing tool. Note that PXLab limits its timer resolution to 1 ms. The dialog also shows that the built in timing method currentTimeMillis() of class System has a resolution of 16 ms only. The number of 'Checks per Step' gives the number of calls to PXLab's high resolution timing method which have been executed to determine a single resolution step of the respective timer. This number will strongly depend on CPU speed. This example has been run on a 3 GHz CPU running Windows XP.

Timer debugging my be activated by using the debug option 'timing' when starting ExRun:

    java de.pxlab.pxl.run.ExRun -D timing

When this debugging option is activated a timing protocol is printed after every display list. This protocol contains three entries for every timing group of every display object in the display list. Here is an example section of such a protocol:

Trial.FixationMark[0]
1067441475
1067441476
1067441876
Trial.Message[0]
1067441876
1067441879
1067442311
Trial.ClearScreen[0]
1067442311
1067442311
1067442612

Trial.FixationMark[0]
1067442648
1067442649
1067443048
...

Each entry starts with the instance name of the respective display object followed by the timing group index. In this example only display objects with a single timing group have neen used such that the timing group index always is '0'. The timing values following are times in milliseconds. Their meaning is as follows: The first value is the time immediately before computation of the display elements of a display timing group is started. The second value is the time immediately after the display elements have been painted to the screen and have become visible and the third value is the time when the timer delay assigned to the respective timing group has passed. Here is the trial definition for this example:

    Trial(TrialCounter, Message.Text, Message.ResponseTime) {
      FixationMark() {
        Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
        Duration = 400;
      }
      Message() {
        Timer = de.pxlab.pxl.TimerCodes.RESPONSE_TIMER;
      }
      ClearScreen() {
        Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
        Duration = 300;
      }
    }

In this definition we see that the intended duration of the fixation mark is 400 ms. The actual value measured is (1067441879 - 1067441476) = 403 ms. This is the second number of Trial.Message minus the second number of Trial.FixationMark. The delay between the point in time when the Message was visible and the Message object's time interval was stopped is (1067442311 - 1067441879) = 432 ms. This is exactly the same value as found in the first trial of the respective response data file:

pxlab 0 432
pxlab 1 262
pxlab 2 268
...

The difference between the second value of Message and the second value of ClearScreen is the actual visiblity duration of the Message object. This is (1067442311 - 1067441879) = 432 ms which is the same as the measured response time when working with millisecond precision.

The difference between the first and second time value of each entry always is the time for computing and drawing needed by PXLab. This time varies depending on the complexity of the display element. The difference between the third and the second time value either corresponds to the response time or should be equal to the intended duration value of a CLOCK_TIMER timer. This interval should not deviate much from the intended duration as long as a CLOCK_TIMER timer type is used. The time between successive display lists represents the time PXLab needs to organize a display list. In our example this is (1067442648 - 1067442612) = 36 ms which seems acceptable. These measuerements have been made on a completely standard Windows XP system with a 3 GHz Intel Pentium 4 CPU.

If instead of 'timing' the option name 'hrtiming' is used for the debug option, then all time values are printed with nanosecond resolution instead of millisecond resolution.

Timing Adjustment for Complex Stimulus Calculations

The timer debugging option may be used to adjust time intervals for complex stimulus calculations. Here is an example for a complex stimulus, a moving Gabor pattern:

    Trial(GaborPatternAnimation.HighColor, 
          GaborPatternAnimation.AngleOfRotation, 
          GaborPatternAnimation.ResponseTime) {
      GaborPatternAnimation() {
        Timer = de.pxlab.pxl.TimerCodes.RESPONSE_TIMER;
	Width = 300;
	Height = 300;
    	FramesPerCycle = 12;
	FrameDuration = 40;
	AmplitudeModulation = 0;
      }
      Feedback() {
	Text = "Time = %Trial.GaborPatternAnimation.ResponseTime%";
	Duration = 1500;
        Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
      }
    }

The subject's task in this example may be to detect the direction of motion and there is a feedback of the response time for 1500 ms. Now if we look at the timing protocol, we see that the computation of the Gabor images takes about 1300 ms. This is the time interval between the end of a Feedback and the start of the following GaborPatternAnimation object:

--- Trial.Feedback[0]
1086078800
1086078834
1086080334

--- Trial.GaborPatternAnimation
1086081620
1086081620
1086082926
--- Trial.Feedback[0]
1086082927
1086082929
1086084428

This time adds to the display duration of the Feedback object which effectively becomes (1086081620 - 1086078834) = 2786 ms. Knowing this, we may decrease the Feedback Duration by 1300 ms such that the effective feedback duration becomes approximately 1500 ms as intended:

      Feedback() {
	Text = "Time = %Trial.GaborPatternAnimation.ResponseTime%";
	Duration = 1500 - 1300;
        Timer = de.pxlab.pxl.TimerCodes.CLOCK_TIMER;
      }

This gives us the following timing protocoll:

--- Trial.Feedback[0]
1086289774
1086289808
1086290008

--- Trial.GaborPatternAnimation
1086291405
1086291405
1086292832

We have an effective Feedback duration here of (1086291405 - 1086289808) which is 1597 ms in this case. This is much nearer to the intended value of 1500 ms as without adjustment.

References

De Clercq, A., Crombez, G., Buysse, A., & Roeyers, H. (2003). A simple and sensitive method to measure timing accuracy. Behavior Research Methods, Instruments, & Computers, 35, 109-115.

Plant, R. R., Hammond, N., & Turner, G. (2004). Self-validating presentation and response timing in cognitive paradigms: How and why? Behavior Research Methods, Instruments, & Computers, 36, 291-303.

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

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