In this post I am going to explain how you can create a visual search display for a compound visual search task with an additional singleton that can either be singled out by color or orientation. The display has multiple items arranged in concentric circles. At the bottom there is the full code included in a working OpenSesame example.


There is nothing really special about the setup of the experimental structure in OpenSesame. The two scripts of interest are general_functions and search_display.
In search_display, I defined everything that is important to set up the display. This is called and executed on every trial. The script general_functions only includes the functions to actually draw each stimulus. The function is called from search_display for every item individually.
General idea
We want the search display to be arranged in concentric circles, so what we do is create three lists, one for each circle, which we then fill with objects. These objects contain the construction manual (i.e. size, color, orientation, etc) for the items in the search display
The inner circle has 6 items that are always nontargets (in this example), the outer circler has 18 items which are also always nontargets. These lists can be filled easily because we basically need to put in the same thing 6 respectively 18 times. The middle circle contains 12 items, one of which is the search target and one may be a distractor.
When we filled the lists with all the objects, we wil go on and loop through the lists to actually draw the items circle by circle and item by item until the whole search display is drawn.
Importantly, everything needs to be put into the prepare phase of OpenSesame because creating and drawing the stimuli is computation intensive and might slow down the experiment on slower machines. We only need one command in the run phase, which we will see later.
Below, I often use the function self.get(“VariableName“). You can replace this with var.VariableName. It’s an artifact from earlier version of OpenSesame.
Setting basic properties
First, we need to import necessary libraries which we should put in general_functions.
import math import random from random import randrange
Next, we start working within search_display. We set the basic colors for our stimuli and create the three empty lists.
# Determine the properties of the # target, distractor and non-targets target_color = "#FC0015" nontarget_color = "#00a0a6" distractor_color = "#FC0015" # Create three lists filled with the target, the # distractor (if present) and a number of # non-targets, which depends on the display size. # The lists represent the three circles. # Target and distractor can only appear on the middle circle. # Create an empty list of stimuli stimuli_circle1 = [] stimuli_circle2 = [] # circle with target and distractor stimuli_circle3 = []
Then we need to define the angles where stuff can appear on the circle. Usually you want to have all items equidistantly arranged across the whole extent of the circle.
# Set the angles at which targets can appear # assuming a circle with 12 possible positions angles = [0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330]
Remember that stimuli_circle1 and stimuli_circle3 will only contain nontargets so we will deal with them later.
Defining target and distractor
First, we specify the location of the search target. You can have a set locaiton or do it randomly, like me.
# Select random angle for the target and remove it from the lsit target_location = angles.pop(randrange(0,len(angles)))
With randrange, we select a random number within the specified range. The function pop returns an item of the list which is now saved in target_location and at the same time removes the item from the list. This is good, because we don’t want to have multiple items at the same locations.
In these types of compound searches, you want the target to have more than one “identity” so that not the same button is the correct answer in every trial (duh!). In my case, I change the orientation of the target so it either looks like an i or an !.
# Based on target identitiy (i or !), randomly pick a target orientation and add the target to the list of stimuli
if self.get("target_identity") == "i":
target_orient = random.choice( (12, 348) )
else:
target_orient = random.choice( (192, 162) )
Then we add our target item for the list of items (it’s the first in the list, yay!).
stimuli_circle2.append( (target_color, target_orient, target_location) )
The distractor is slightly more complex because we first need to check whether it is actually present in the current display and if yes, what type the distractor is. Afterwards, we can generate its location and append it to the list stimuli_circle2.
# If a distractor is present in the display,
# determine its orientation and color based on the distractor type
if self.get("distractor") == "present":
if self.get("distractor_type") == "color":
distractor_color = "#FC0015" # red distractor
distractor_orient = random.choice( (0,180) )
if self.get("distractor_type") == "orient":
distractor_orient = random.choice( (90,270) ) # horizontal distractor
# Set random distracotr location
distractor_location = angles.pop(randrange(0,len(angles)))
# Append the distractor to the list of display items
stimuli_circle2.append( (distractor_color, distractor_orient, distractor_location) )
Adding the nontargets
The idea for the inner and outer circle is simple. We create a loop that generates a random orientation for each nontarget and add it to the list. It looks like below for the inner circle.
# Add the remaining nontarget stimuli to the list - CIRCLE 1 for i in range(6 - int(len(stimuli_circle1))): nontarget_orient = random.choice((0,180)) stimuli_circle1.append( (nontarget_color, nontarget_orient) )
For the outer circle, you might have guessed it, the 6 needs to be exchanged for an 18. What we do here is to say: as long as our list of object hasn’t reached the total number of objects we want (i.e. 6), append more objects! For the middle circle, we need to add information about the location of the objects, because one or two locations are already occupied with a target plus possibly distractor.
# Add the remaining nontarget stimuli to the list - CIRCLE 2 for i in range(12 - len(stimuli_circle2)): nontarget_orient = random.choice((0,180)) nontarget_location = angles.pop(randrange(0,len(angles))) stimuli_circle2.append( (nontarget_color, nontarget_orient, nontarget_location) )
Like we did with the target and distractor, we get our remaining object locations by popping them out of the angles list. We have three lists filled with all our items now and can start to create the canvas where we later draw the items on.
Creating the canvas and setting circle properties
Creating a canvas is simple.
# Create a new offline canvas self.c = self.offline_canvas() # We want the stimuli to have some body self.c.set_penwidth(1)
We now need to decide how big our circles are gonna be. The sizes can be specified relatively or absolutely. Since I wanted to make sure that they look the same on all screens, I specified absolute pixel values. This is something you just need to try out or calculate from the visual angle you want to achieve.
# Setting circle properties radius_circle1 = 341 * 0.3333 # Distance of the inner circle from center radius_circle2 = 341 * 0.6667 radius_circle3 = 341 line_length = 76*0.5 # Size of the lines in the shapes line_width = 14 # The angular separation of the stimuli depends on the number of items angular_separation_circle1 = 360.0 / 6 angular_separation_circle2 = 360.0 / 12 angular_separation_circle3 = 360.0 / 18 # The first stimulis is drawn at angle 270 (12 clock position) angle = 270
Above we defined the radius of each circle, the length and width of our stimuli as well as the angular separation of the items in the three circles. Importantly, the angle attribute specifies where we want the items to be drawn on the circle. The first item will be drawn at 270° which is the 12 o’clock position (I don’t know why).
Drawing all stimuli
The easiest thing is the center. There is one nontarget in the middle. We need to determine its location (i.e. the center of the screen) and then draw it with the correct attributes.
# Determine coordinates of center nontarget
x = self.get("width") / 2
y = self.get("height") / 2
# Set the color of the stimulus
self.c.set_fgcolor(nontarget_color)
# draw the center nontarget
draw_asp_stimulus(x, y, line_width, line_length, nontarget_orient, self.c)
The function draw_asp_stimulus draws the actual stimulus on the canvas and will be discussed later. After drawing the central nontarget we start drawing our items from the inner to the outer circle.
# Walk through all the stimuli - CIRCLE 1 - inner circle
for color, orient in stimuli_circle1:
# Determine the coordinates of the stimulus
x = self.get("width") / 2 + radius_circle1 * math.cos(math.radians(angle))
y = self.get("height") / 2 + radius_circle1 * math.sin(math.radians(angle))
# Set the color of the stimulus
self.c.set_fgcolor(color)
# Draw special ASP stimulus which is an iterrupted bar looking like an i or bang
draw_asp_stimulus(x, y, line_width, line_length, orient, self.c)
# Make sure the next stimulus is drawn at a different location
angle += angular_separation_circle1
For each item in the stimuli_circle1 list, we determine the coordinates by using some fancy math based on the angle, set the foreground color and call the draw function. Then we add the angular separation to the angle, so that the next item will be drawn at the next position on the circle. This works similarly for all circles.
Actually drawing one stimulus
One item contains of one large turquoise rectangle and one small black rectangle which is either at the top or bottom of the large rectangle. The function draw_asp_stimulus takes the arguments x,y position, width, length, orientation and the canvas. The x,y position represents the center of mass of the object, not some corner! This means what we first need to do is calculate the x,y positions four corners.
def draw_asp_stimulus(x, y, line_width, line_length, orientation, c): # OUTER RECTANGLE # set corners x1 = x - line_width/2 y1 = y - line_length x2 = x + line_width/2 y2 = y - line_length x3 = x + line_width/2 y3 = y + line_length x4 = x - line_width/2 y4 = y + line_length
Since not all our items have the same orientation (especially target and distractor), we now need to rotate all the corner points. What we do is a point rotation around a central pivot point (the center of mass) by the orientation angle.
# polygon rotation p1 = rotate_point(x, y, orientation, x1, y1) p2 = rotate_point(x, y, orientation, x2, y2) p3 = rotate_point(x, y, orientation, x3, y3) p4 = rotate_point(x, y, orientation, x4, y4)
Unfortunately, the rotate_point function, doesn’t really exist, so we need to create our own!
def rotate_point(cx, cy, angle, x, y): s = math.sin(math.radians(angle)) c = math.cos(math.radians(angle)) x = x - cx y = y - cy xnew = x * c - y * s ynew = x * s + y * c x = xnew + cx y = ynew + cy return [x,y]
I will spare you the mathematical details of the point rotation. We now created and rotated the corner points from the outer rectangle, we need to do the same with the inner rectangle.
# INNER RECTANGLE # set corners cx1 = x - line_width/2 cy1 = y - line_length + line_width cx2 = x + line_width/2 cy2 = y - line_length + line_width cx3 = x + line_width/2 cy3 = y - line_length + line_width + line_width cx4 = x - line_width/2 cy4 = y - line_length + line_width + line_width #point rotation cp1 = rotate_point(x, y, orientation, cx1, cy1) cp2 = rotate_point(x, y, orientation, cx2, cy2) cp3 = rotate_point(x, y, orientation, cx3, cy3) cp4 = rotate_point(x, y, orientation, cx4, cy4)
Lastly, we need to draw our rectangles with the polygon function on our canvas.
self.c.polygon([(p1[0], p1[1]),(p2[0], p2[1]), (p3[0], p3[1]), (p4[0], p4[1])], fill=True)
self.c.set_fgcolor("black")
self.c.polygon([(cp1[0], cp1[1]),(cp2[0], cp2[1]), (cp3[0], cp3[1]), (cp4[0], cp4[1])], fill=True)
We now created the canvas full of juicy objects, the only thing left to do is show it at runtime. The following command needs to be included in the run phase of the search_display.
# Show the canvas! self.c.show()
Tadaa! Wasn’t so hard was it? If you have any questions, feel free to ask me at any time. I am also happy about suggestions for improving the code. Please comment or write me an email.
Below you can find the whole OpenSesame code for this experiment but you can also download it here.
---
API: 2
OpenSesame: 3.1.3
Platform: posix
---
set width 1024
set uniform_coordinates no
set transparent_variables no
set title "Marian Visual Search"
set synth_backend legacy
set subject_parity even
set subject_nr 0
set start experiment
set sound_sample_size -16
set sound_freq 48000
set sound_channels 2
set sound_buf_size 1024
set sampler_backend legacy
set round_decimals 2
set mouse_backend psycho
set keyboard_backend psycho
set height 768
set fullscreen no
set form_clicks no
set foreground white
set font_underline no
set font_size 28
set font_italic no
set font_family sans
set font_bold no
set experiment_path "/Users/mariansauter/Dropbox/PhD/Blog/Visual Search Display/MS-ASP-LT-1-Chronicles"
set disable_garbage_collection yes
set description "A probability cuing experiment"
set coordinates relative
set compensation 0
set color_backend psycho
set clock_backend psycho
set canvas_backend psycho
set bidi no
set background black
define advanced_delay advanced_delay
set jitter_mode Uniform
set jitter 200
set duration 900
set description "Waits for a specified duration"
define loop block_loop
set source_file ""
set source table
set repeat 30
set order random
set item trial_sequence
set description "A block of trials"
set cycles 4
set continuous no
set column_order "distractor;circles;inner_circle_size;mid_circle_size;outer_circle_size;target_identity;distractor_type"
set break_if_on_first yes
set break_if never
setcycle 0 distractor_type orient
setcycle 0 target_identity i
setcycle 0 distractor present
setcycle 1 distractor_type orient
setcycle 1 target_identity bang
setcycle 1 distractor present
setcycle 2 distractor_type orient
setcycle 2 target_identity i
setcycle 2 distractor absent
setcycle 3 distractor_type orient
setcycle 3 target_identity bang
setcycle 3 distractor absent
run trial_sequence
define sequence block_sequence
set flush_keyboard yes
set description "An instruction screen, followed by a block of trials and feedback"
run reset_feedback always
run block_loop always
run feedback always
define inline_script each_block
set description "Executes Python code"
___run__
current_block = current_block + 1;
self.experiment.set("block_count", current_block)
__end__
set _prepare ""
define sketchpad error_display
set reset_variables no
set duration 495
set description "Displays stimuli"
draw textline center=1 color=white font_bold=no font_family=mono font_italic=no font_size=18 html=no show_if=always text=Error x=0 y=0 z_index=0
define sequence experiment
set flush_keyboard yes
set description "The main experimental sequence"
run general_functions always
run instruction_form always
run experimental_loop always
run goodbye always
define loop experimental_loop
set source_file ""
set source table
set skip 0
set repeat 12
set order sequential
set item block_sequence
set description "Run a number of experimental blocks"
set cycles 1
set continuous no
set column_order "practice;condition"
set break_if_on_first yes
set break_if never
setcycle 0 practice no
setcycle 0 condition top
run block_sequence
define feedback feedback
set reset_variables yes
set duration keypress
set description "Provides feedback to the participant"
draw textline center=1 color=white font_bold=no font_family=mono font_italic=no font_size=18 html=yes show_if=always text="Your average response time was [avg_rt]ms" x=0 y=-128 z_index=0
draw textline center=1 color=white font_bold=no font_family=mono font_italic=no font_size=18 html=yes show_if=always text="Your accuracy was [acc]%" x=0 y=-64 z_index=0
draw textline center=1 color=white font_bold=no font_family=mono font_italic=no font_size=18 html=yes show_if=always text="Press any key to continue ..." x=0 y=64 z_index=0
draw textline center=1 color=white font_bold=no font_family=mono font_italic=no font_size=18 html=yes show_if=always text="This was block [block_count] of 12" x=0 y=-224 z_index=0
define fixation_dot fixation_dot
set y 0
set x 0
set style cross
set penwidth 3
set foreground white
set duration 0
set description "Presents a central fixation dot with a choice of various styles"
set background black
define inline_script general_functions
set description "Executes Python code"
___run__
current_block = 0
import math
import random
from random import randrange
# function rotate_point rotates a point x,y at a given angle around a pivot point cx,cy
def rotate_point(cx, cy, angle, x, y):
s = math.sin(math.radians(angle))
c = math.cos(math.radians(angle))
x = x - cx
y = y - cy
xnew = x * c - y * s
ynew = x * s + y * c
x = xnew + cx
y = ynew + cy
return [x,y]
# draws a rotated stimulus for the ASP paradigm
# takes center x, y, stimulus width and height and its orientation
def draw_asp_stimulus(x, y, line_width, line_length, orientation, c):
# OUTER RECTANGLE
# set corners
x1 = x - line_width/2
y1 = y - line_length
x2 = x + line_width/2
y2 = y - line_length
x3 = x + line_width/2
y3 = y + line_length
x4 = x - line_width/2
y4 = y + line_length
# point rotation
p1 = rotate_point(x, y, orientation, x1, y1)
p2 = rotate_point(x, y, orientation, x2, y2)
p3 = rotate_point(x, y, orientation, x3, y3)
p4 = rotate_point(x, y, orientation, x4, y4)
# INNER RECTANGLE
# set corners
cx1 = x - line_width/2
cy1 = y - line_length + line_width
cx2 = x + line_width/2
cy2 = y - line_length + line_width
cx3 = x + line_width/2
cy3 = y - line_length + line_width + line_width
cx4 = x - line_width/2
cy4 = y - line_length + line_width + line_width
#point rotation
cp1 = rotate_point(x, y, orientation, cx1, cy1)
cp2 = rotate_point(x, y, orientation, cx2, cy2)
cp3 = rotate_point(x, y, orientation, cx3, cy3)
cp4 = rotate_point(x, y, orientation, cx4, cy4)
self.c.polygon([(p1[0], p1[1]),(p2[0], p2[1]), (p3[0], p3[1]), (p4[0], p4[1])], fill=True)
self.c.set_fgcolor("black")
self.c.polygon([(cp1[0], cp1[1]),(cp2[0], cp2[1]), (cp3[0], cp3[1]), (cp4[0], cp4[1])], fill=True)
__end__
set _prepare ""
define sketchpad goodbye
set start_response_interval no
set reset_variables no
set duration keypress
set description "Say goodbye!"
draw textline center=1 color=white font_bold=no font_family=mono font_italic=no font_size=18 html=yes show_if=always text="The experiment is finished!" x=0 y=-64 z_index=0
draw textline center=1 color=white font_bold=no font_family=mono font_italic=no font_size=18 html=yes show_if=always text="Press any key to exit ..." x=0 y=64 z_index=0
define sketchpad green_fixdot
set start_response_interval no
set reset_variables no
set duration 500
set description "Displays stimuli"
draw fixdot color=green show_if=always style="medium-cross" x=0 y=0 z_index=0
define sketchpad instruction_form
set start_response_interval no
set reset_variables no
set duration keypress
set description "Present instruction for the form condition"
draw textline center=1 color=white font_bold=no font_family=sans font_italic=no font_size=18 html=yes show_if=always text="When you have read and understood the instructions, <br />you can start the experiment by pressing any key." x=0 y=0 z_index=0
define keyboard_response keyboard_response
set timeout infinite
set flush yes
set duration keypress
set description "Collects keyboard responses"
set allowed_responses "y;m"
define logger logger
set use_quotes yes
set ignore_missing yes
set description "Logs experimental data"
set auto_log no
log fixation_interval
log response
log response_time
log correct
log correct_keyboard_response
log average_response_time
log avg_rt
log accuracy
log acc
log count_experimental_loop
log practice
log condition
log repeat
log count_block_loop
log target_identity
log distractor_type
log mid_circle_size
log distractor
log inner_circle_size
log outer_circle_size
log foreground
log background
log target_location
log target_pos
log target_color
log target_orient
log distractor_pos
log distractor_location
log distractor_color
log distractor_orient
log correct_response
log count_trial_sequence
log block_count
log height
log subject_nr
log width
log count_block_sequence
log response_time_instruction_form
define sketchpad red_fixdot
set start_response_interval no
set reset_variables no
set duration 500
set description "Displays stimuli"
draw fixdot color=red show_if=always style="medium-cross" x=0 y=0 z_index=0
define reset_feedback reset_feedback
set description "Resets the feedback variables, such as 'avg_rt' and 'acc'"
define inline_script search_display
set description "The search display"
___run__
# Show the canvas!
self.c.show()
__end__
___prepare__
# Determine the properties of the
# target, distractor and non-targets
target_color = "#FC0015"
nontarget_color = "#00a0a6"
distractor_color = "#FC0015"
# Create three lists filled with the target, the
# distractor (if present) and a number of
# non-targets, which depends on the display size.
# The lists represent the three circles.
# Target and distractor can only appear on the middle circle.
# Create an empty list of stimuli
stimuli_circle1 = []
stimuli_circle2 = [] # circle with target and distractor
stimuli_circle3 = []
# Set the angles at which targets can appear
# assuming a circle with 12 possible positions
angles = [0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330]
# Select random angle for the target and remove it from the lsit
target_location = angles.pop(randrange(0,len(angles)))
# Based on target identitiy (i or !), randomly pick a target orientation and add the target to the list of stimuli
if self.get("target_identity") == "i":
target_orient = random.choice( (12, 348) )
else:
target_orient = random.choice( (192, 162) )
stimuli_circle2.append( (target_color, target_orient, target_location) )
# If a distractor is present in the display,
# determine its orientation and color based on the distractor type
if self.get("distractor") == "present":
if self.get("distractor_type") == "color":
distractor_color = "#FC0015" # red distractor
distractor_orient = random.choice( (0,180) )
if self.get("distractor_type") == "orient":
distractor_orient = random.choice( (90,270) ) # horizontal distractor
# Set random distracotr location
distractor_location = angles.pop(randrange(0,len(angles)))
# Append the distractor to the list of display items
stimuli_circle2.append( (distractor_color, distractor_orient, distractor_location) )
# determine the list of locations to be filled with nontargets and shuffle them (i dont know why I do that)
random.shuffle(angles)
# Add the remaining nontarget stimuli to the list - CIRCLE 1
for i in range(6 - int(len(stimuli_circle1))):
nontarget_orient = random.choice((0,180))
stimuli_circle1.append( (nontarget_color, nontarget_orient) )
# Add the remaining nontarget stimuli to the list - CIRCLE 2
for i in range(12 - len(stimuli_circle2)):
nontarget_orient = random.choice((0,180))
nontarget_location = angles.pop(randrange(0,len(angles)))
stimuli_circle2.append( (nontarget_color, nontarget_orient, nontarget_location) )
# Add the remaining nontarget stimuli to the list - CIRCLE 3
for i in range(18 - len(stimuli_circle3)):
nontarget_orient = random.choice((0,180))
stimuli_circle3.append( (nontarget_color, nontarget_orient) )
#
# Set correct_repsonse dpending on condition
# 'correct_response' is a special variable that, if it exists,
# is interpreted as the expected response by the
# keyboard_response item
#
if self.get("target_identity") == "i":
self.experiment.set("correct_response", "m")
else:
self.experiment.set("correct_response", "y")
###########################################################
# Create an offline canvas containing all off the stimuli
# and a fixation dot
###########################################################
# Create a new offline canvas
self.c = self.offline_canvas()
# Setting circle properties
radius_circle1 = 341 * 0.3333 # Distance of the inner circle from center
radius_circle2 = 341 * 0.6667
radius_circle3 = 341
line_length = 76*0.5 # Size of the lines in the shapes
line_width = 14
# We want the stimuli to have some body
self.c.set_penwidth(1)
# The angular separation of the stimuli depends on the number of items
# CAREFUL: middle circle locations are actually manually defined below
angular_separation_circle1 = 360.0 / 6
angular_separation_circle2 = 360.0 / 12
angular_separation_circle3 = 360.0 / 18
# The first stimulis is drawn at angle 270 (12 clock position)
angle = 270
# Determine coordinates of center nontarget
x = self.get("width") / 2
y = self.get("height") / 2
# Set the color of the stimulus
self.c.set_fgcolor(nontarget_color)
# draw the center nontarget
draw_asp_stimulus(x, y, line_width, line_length, nontarget_orient, self.c)
# Walk through all the stimuli - CIRCLE 1 - inner circle
for color, orient in stimuli_circle1:
# Determine the coordinates of the stimulus
x = self.get("width") / 2 + radius_circle1 * math.cos(math.radians(angle))
y = self.get("height") / 2 + radius_circle1 * math.sin(math.radians(angle))
# Set the color of the stimulus
self.c.set_fgcolor(color)
# Draw special ASP stimulus which is an iterrupted bar looking like an i or bang
draw_asp_stimulus(x, y, line_width, line_length, orient, self.c)
# Make sure the next stimulus is drawn at a different location
angle += angular_separation_circle1
angle = 270
# Walk through all the stimuli - CIRCLE 2 - inner circle
for color, orient, location in stimuli_circle2:
# Determine the coordinates of the stimulus
x = self.get("width") / 2 + radius_circle2 * math.cos(math.radians(location))
y = self.get("height") / 2 + radius_circle2 * math.sin(math.radians(location))
# Set the color of the stimulus
self.c.set_fgcolor(color)
# Draw special ASP stimulus which is an iterrupted bar looking like an i or bang
draw_asp_stimulus(x, y, line_width, line_length, orient, self.c)
# Make sure the next stimulus is drawn at a different location
angle += angular_separation_circle2
angle = 270
# Walk through all the stimuli - CIRCLE 3 - outer circle
for color, orient in stimuli_circle3:
# Determine the coordinates of the stimulus
x = self.get("width") / 2 + radius_circle3 * math.cos(math.radians(angle))
y = self.get("height") / 2 + radius_circle3 * math.sin(math.radians(angle))
# Set the color of the stimulus
self.c.set_fgcolor(color)
# Draw special ASP stimulus which is an iterrupted bar looking like an i or bang
draw_asp_stimulus(x, y, line_width, line_length, orient, self.c)
# Make sure the next stimulus is drawn at a different location
angle += angular_separation_circle3
__end__
define inline_script trial_prep
set description "Executes Python code"
___run__
#from random import randint
#random_fix_interval = random.randint(700,1100)
#self.experiment.set("fixation_interval", random_fix_interval)
__end__
set _prepare ""
define sequence trial_sequence
set flush_keyboard yes
set description "A single trial"
run fixation_dot always
run advanced_delay always
run search_display always
run keyboard_response always
run error_display "[correct] = 0"
run logger always
Leave a Reply