### Install OpenSesame on Linux
Source: https://github.com/open-cogsci/opensesame/blob/nightingale/readme.md
Use this bash script to install OpenSesame and its dependencies on Linux, creating a virtual environment and a desktop shortcut. Tested on Ubuntu 24.04.
```bash
bash <(curl -L https://github.com/open-cogsci/OpenSesame/raw/refs/heads/4.1/linux-installer.sh) --install
```
--------------------------------
### Experiment Factory
Source: https://context7.com/open-cogsci/opensesame/llms.txt
The `Experiment()` factory function initializes the necessary subsystems for running an experiment programmatically. It can be used to start a fully programmatic experiment or to load and run an existing .osexp file.
```APIDOC
## Experiment Factory
### Description
Initializes the display, sound, clock, and log subsystems for scripted experiments, bypassing the GUI. Returns a 4-tuple: `(exp, win, clock, log)`.
### Usage
```python
from libopensesame.python_workspace_api import Experiment
# Option 1: Fully programmatic experiment
exp, win, clock, log = Experiment(
canvas_backend='legacy', # or 'psycho', 'xpyriment'
log_path='subject_01.csv',
fullscreen=False,
subject_nr=1
)
# Option 2: Load and run an existing .osexp file
exp, win, clock, log = Experiment(
osexp_path='stroop_task.osexp',
subject_nr=2,
log_path='subject_02.csv',
fullscreen=True
)
exp.run()
```
```
--------------------------------
### Clock: Measure Elapsed Time
Source: https://context7.com/open-cogsci/opensesame/llms.txt
The `clock` object provides millisecond-accurate timing. Use `clock.time()` to get the current time and `clock.sleep()` to pause execution.
```python
# Measure elapsed time between two events
t0 = clock.time()
clock.sleep(500)
t1 = clock.time()
print(f'Elapsed: {t1 - t0:.1f} ms') # ~500 ms
```
```python
# Stimulus onset asynchrony (SOA) with accurate sleep
c1 = Canvas()
c1.fixdot()
t_fix = c1.show()
clock.sleep(500) # hold fixation for 500 ms
c2 = Canvas()
c2.text('Target', color='white')
t_stim = c2.show()
soa = t_stim - t_fix
print(f'Actual SOA: {soa:.1f} ms')
```
--------------------------------
### Get Elements at Mouse Coordinates
Source: https://context7.com/open-cogsci/opensesame/llms.txt
Determine which canvas elements are located at specific mouse coordinates using the `elements_at()` method. This is useful for implementing region-of-interest (ROI) hit-testing and interactive elements.
```python
# Element-at-position (for ROI hit-testing)
names = c.elements_at(mouse_x, mouse_y)
```
--------------------------------
### Initialize and Run Experiment Programmatically
Source: https://context7.com/open-cogsci/opensesame/llms.txt
Use the Experiment() factory function to initialize experiment subsystems and run experiments either fully programmatically or by loading an existing .osexp file. Specify canvas backend, log path, and subject number.
```python
from libopensesame.python_workspace_api import (
Experiment, Canvas, Text, Keyboard, Sampler, Synth, Mouse, Form,
Label, Button, TextInput
)
# --- Option 1: fully programmatic experiment ---
exp, win, clock, log = Experiment(
canvas_backend='legacy', # or 'psycho', 'xpyriment'
log_path='subject_01.csv',
fullscreen=False,
subject_nr=1
)
# Draw a welcome screen
c = Canvas()
c += Text('Welcome! Press any key to begin.', color='white')
c.show()
kb = Keyboard(timeout=None) # wait indefinitely
key, t = kb.get_key()
# Clean up and exit
exp.end()
# --- Option 2: load and run an existing .osexp file ---
exp, win, clock, log = Experiment(
osexp_path='stroop_task.osexp',
subject_nr=2,
log_path='subject_02.csv',
fullscreen=True
)
exp.run()
```
--------------------------------
### Sampler: Basic Sound Playback
Source: https://context7.com/open-cogsci/opensesame/llms.txt
The `Sampler` class plays audio files (`.wav`, `.mp3`, `.ogg`). Playback parameters like `volume` and `pan` can be set at construction or per-call. Use `wait()` to block until playback finishes.
```python
# Basic playback
src = pool['beep.wav']
snd = Sampler(src, volume=0.8, pan=0)
snd.play()
snd.wait() # block until finished
```
```python
# Play with per-call overrides
snd.play(volume=0.5, pitch=1.5, fade_in=50)
```
```python
# Non-blocking playback with duration limit
snd.play(duration=300, block=False)
clock.sleep(100)
if snd.is_playing():
snd.stop()
```
```python
# Pause and resume
snd.play(block=False)
clock.sleep(200)
snd.pause()
clock.sleep(500)
snd.resume()
snd.wait()
```
```python
# Pan left/right
beep_left = Sampler(pool['tone.wav'], pan='left', volume=1.0)
beep_right = Sampler(pool['tone.wav'], pan='right', volume=1.0)
beep_left.play()
```
--------------------------------
### Create Consent Form with Label and Button
Source: https://context7.com/open-cogsci/opensesame/llms.txt
Demonstrates creating a simple form with a consent label and an 'I Agree' button. The form execution blocks until the button is clicked.
```python
form = Form(cols=1, rows=2, margins=[50, 50, 50, 50])
form.set_widget(
Label(text='Informed consent
Do you agree to participate?'),
(0, 0)
)
form.set_widget(
Button(text='I Agree', var='consent'),
(0, 1)
)
form._exec() # blocks until button click; var.consent = 'I Agree'
```
--------------------------------
### Sampler - Sound File Playback
Source: https://context7.com/open-cogsci/opensesame/llms.txt
Plays `.wav`, `.mp3`, or `.ogg` files from the file pool. Playback keywords (`volume`, `pitch`, `pan`, `duration`, `fade_in`) can be set at construction or per `play()` call.
```APIDOC
## Sampler
### Description
Plays `.wav`, `.mp3`, or `.ogg` files from the file pool. Playback keywords (`volume`, `pitch`, `pan`, `duration`, `fade_in`) can be set at construction or per `play()` call.
### Method
`Sampler(source, volume=1.0, pitch=1.0, pan=0.0, duration=None, fade_in=0, fade_out=0, block=True)`
### Parameters
#### Constructor Parameters
- **source** (str) - The path to the sound file in the file pool.
- **volume** (float) - The playback volume, from 0.0 to 1.0.
- **pitch** (float) - The playback pitch, where 1.0 is normal pitch.
- **pan** (float or str) - The stereo panning, from -1.0 (left) to 1.0 (right), or 'left'/'right'.
- **duration** (int) - Optional - The duration of playback in milliseconds.
- **fade_in** (int) - The duration of the fade-in in milliseconds.
- **fade_out** (int) - The duration of the fade-out in milliseconds.
- **block** (bool) - Whether to block execution until playback is finished.
### Methods
- **play(volume=None, pitch=None, pan=None, duration=None, fade_in=None, fade_out=None, block=None)**: Starts playback of the sound.
- **wait()**: Blocks execution until playback is finished.
- **stop()**: Stops playback immediately.
- **pause()**: Pauses playback.
- **resume()**: Resumes playback from a paused state.
- **is_playing()**: Returns `True` if the sound is currently playing, `False` otherwise.
### Request Example
```python
# Basic playback
src = pool['beep.wav']
snd = Sampler(src, volume=0.8, pan=0)
snd.play()
snd.wait() # block until finished
# Play with per-call overrides
snd.play(volume=0.5, pitch=1.5, fade_in=50)
# Non-blocking playback with duration limit
snd.play(duration=300, block=False)
clock.sleep(100)
if snd.is_playing():
snd.stop()
# Pause and resume
snd.play(block=False)
clock.sleep(200)
snd.pause()
clock.sleep(500)
snd.resume()
snd.wait()
# Pan left/right
beep_left = Sampler(pool['tone.wav'], pan='left', volume=1.0)
beep_right = Sampler(pool['tone.wav'], pan='right', volume=1.0)
beep_left.play()
```
```
--------------------------------
### Resolve File Paths with FilePoolStore
Source: https://context7.com/open-cogsci/opensesame/llms.txt
Demonstrates using the `pool` object to resolve filenames to absolute paths within the experiment's file pool. It supports dictionary-like access and checking for file existence.
```python
# Resolve a file to its full path (raises OSError if not found)
img_path = pool['stimuli/face_01.png']
snd_path = pool['bark.ogg']
# Check existence without raising
if 'instructions.html' in pool:
with open(pool['instructions.html']) as f:
html = f.read()
# Add a file to the pool at runtime
pool.add('/tmp/generated_stim.png', new_name='stim_current.png')
# List all files
for path in pool:
print(path)
# Pool size in bytes
print(f'Pool size: {pool.size()} bytes')
# All search folders (pool folder + fallbacks)
for folder in pool.folders():
print(folder)
# Use in Canvas
c = Canvas()
c.image(pool['face.png'], center=True, x=0, y=0)
c.show()
# Use in Sampler
snd = Sampler(pool['beep.wav'], volume=0.9)
snd.play()
```
--------------------------------
### Create Free-text Input Form
Source: https://context7.com/open-cogsci/opensesame/llms.txt
Illustrates creating a form for free-text input, where pressing Enter in the text field submits the form. Includes a label and an OK button.
```python
form3 = Form(cols=1, rows=3)
form3.set_widget(Label(text='Enter your participant ID:'), (0, 0))
form3.set_widget(
TextInput(var='participant_id', stub='Type here...', return_accepts=True),
(0, 1)
)
form3.set_widget(Button(text='OK', var='ok_btn'), (0, 2))
form3._exec()
print(f'Participant ID: {var.participant_id}')
```
--------------------------------
### Pause and Inspect Workspace
Source: https://context7.com/open-cogsci/opensesame/llms.txt
Shows how to pause the experiment execution and enter the GUI's interactive workspace for debugging purposes using the `pause` function.
```python
# Pause and inspect workspace in GUI
from libopensesame.python_workspace_api import pause
if var.debug_mode:
pause()
```
--------------------------------
### Create Multi-column Rating Scale Form
Source: https://context7.com/open-cogsci/opensesame/llms.txt
Shows how to create a form with multiple columns and rows, featuring a rating scale widget. The form has a timeout set to None.
```python
form2 = Form(cols=[1, 3, 1], rows=[1, 1], timeout=None)
form2.set_widget(Label(text='How confident are you?', center=True), (0, 0), colspan=3)
from libopensesame.widgets.widget_factory import RatingScale
form2.set_widget(
RatingScale(min_val=1, max_val=7, left_label='Not at all',
right_label='Very', var='confidence'),
(0, 1), colspan=3
)
form2._exec()
print(f'Confidence rating: {var.confidence}')
```
--------------------------------
### Copy and Modify Sketchpad Canvas
Source: https://context7.com/open-cogsci/opensesame/llms.txt
Shows how to copy an existing sketchpad's canvas using `copy_sketchpad` to allow for programmatic modifications before displaying it.
```python
# Copy a sketchpad's canvas for programmatic modification
from libopensesame.python_workspace_api import copy_sketchpad
c = copy_sketchpad('target_sketchpad')
c['probe'] = Text('X', color='red', x=100, y=0)
c.show()
```
--------------------------------
### Manage Experiment Responses with ResponseStore
Source: https://context7.com/open-cogsci/opensesame/llms.txt
Use `responses.add()` to log individual responses and `responses.acc`/`responses.avg_rt` for aggregate feedback. Responses can be iterated, sliced, reset, or cleared.
```python
# Manually add a response (e.g., from a custom input routine)
responses.add(
response='left',
correct=1,
response_time=412.5,
item='my_custom_trial',
feedback=True # include in acc/avg_rt
)
# Read aggregate feedback variables
print(f'Accuracy: {responses.acc}%') # int or 'undefined'
print(f'Mean RT: {responses.avg_rt} ms') # int or 'undefined'
# Iterate over all responses (newest first)
for r in responses:
print(f"response={r.response}, correct={r.correct}, "
f"rt={r.response_time:.1f} ms, item={r.item}")
# Slice: get the 3 most recent responses
last_3 = responses[:3]
for r in last_3:
print(r.correct)
# Reset feedback counters mid-experiment (e.g., after practice block)
responses.reset_feedback()
# Clear all responses entirely
responses.clear()
# Access flat lists
print('All responses:', responses.response)
print('All RTs:', responses.response_time)
print('All correct:', responses.correct)
```
--------------------------------
### Safe Variable Access with Exception Handling
Source: https://context7.com/open-cogsci/opensesame/llms.txt
Illustrates how to safely access variables using a try-except block to catch `VariableDoesNotExist` exceptions, providing a default value if the variable is not found.
```python
from libopensesame.exceptions import (
VariableDoesNotExist,
InvalidValue,
ItemDoesNotExist,
PythonError,
UserAborted,
MissingDependency,
)
# Safe variable access
try:
speed = var.speed
except VariableDoesNotExist:
speed = 1.0
```
--------------------------------
### Handle User Abort in OpenSesame
Source: https://context7.com/open-cogsci/opensesame/llms.txt
Catch the UserAborted exception to gracefully end the experiment and log a message when the user interrupts the process.
```python
try:
key, t = kb.get_key()
except UserAborted:
log.write(f'Experiment aborted by user at trial {var.count_trial_sequence}')
exp.end()
```
--------------------------------
### Register Cleanup Function
Source: https://context7.com/open-cogsci/opensesame/llms.txt
Demonstrates registering a function to be executed automatically when the experiment ends or crashes, using `register_cleanup_function`. This is useful for saving state or performing final operations.
```python
# Register a cleanup function (runs after experiment ends or crashes)
from libopensesame.python_workspace_api import register_cleanup_function
def save_extra_data():
import json
with open('extra_data.json', 'w') as f:
json.dump({'subject': var.subject_nr, 'acc': responses.acc}, f)
register_cleanup_function(save_extra_data)
```
--------------------------------
### Synth - Tone Synthesis
Source: https://context7.com/open-cogsci/opensesame/llms.txt
Synthesizes a tone and returns a `Sampler` object, enabling precise frequency and envelope control without needing a sound file.
```APIDOC
## Synth
### Description
Synthesizes a tone and returns a `Sampler` object, enabling precise frequency and envelope control without needing a sound file.
### Method
`Synth(osc='sine', freq='A4', length=1000, attack=10, decay=10, sustain=0, release=10, volume=1.0, pitch=1.0, pan=0.0)`
### Parameters
#### Constructor Parameters
- **osc** (str) - The waveform to synthesize ('sine', 'square', 'saw', 'triangle', 'white_noise').
- **freq** (float or str) - The frequency of the tone in Hz, or a musical note name (e.g., 'C4', 'A#5').
- **length** (int) - The total length of the tone in milliseconds.
- **attack** (int) - The duration of the attack envelope in milliseconds.
- **decay** (int) - The duration of the decay envelope in milliseconds.
- **sustain** (int) - The duration of the sustain level in milliseconds.
- **release** (int) - The duration of the release envelope in milliseconds.
- **volume** (float) - The playback volume, from 0.0 to 1.0.
- **pitch** (float) - The playback pitch, where 1.0 is normal pitch.
- **pan** (float or str) - The stereo panning, from -1.0 (left) to 1.0 (right), or 'left'/'right'.
### Methods
- **play(volume=None, pitch=None, pan=None, block=True)**: Starts playback of the synthesized tone.
- **wait()**: Blocks execution until playback is finished.
- **stop()**: Stops playback immediately.
- **pause()**: Pauses playback.
- **resume()**: Resumes playback from a paused state.
- **is_playing()**: Returns `True` if the tone is currently playing, `False` otherwise.
### Request Example
```python
# Sine wave at 440 Hz, 500 ms, with 10 ms attack/decay
tone = Synth(osc='sine', freq=440, length=500, attack=10, decay=10, volume=0.8)
tone.play()
# Musical note notation
high_c = Synth(osc='square', freq='C5', length=200, volume=0.6)
high_c.play()
# White noise burst
noise = Synth(osc='white_noise', length=300, volume=0.4)
noise.play()
# Sawtooth feedback tone (error signal)
error_tone = Synth(osc='saw', freq='A3', length=400, attack=5, decay=20)
error_tone.play()
error_tone.wait()
```
```
--------------------------------
### VarStore - Experimental Variables
Source: https://context7.com/open-cogsci/opensesame/llms.txt
The `var` object provides read/write access to all experimental variables, including those defined in loop tables, built-in variables, and custom variables set in scripts.
```APIDOC
## VarStore — Experimental Variables (`var`)
### Description
Provides read/write access to all experimental variables. Variable references using `[bracket]` notation are resolved automatically.
### Usage
```python
# Set variables
var.condition = 'congruent'
var.soa = 500
var.correct_response = 'left'
# Get variables
print(f"Subject {var.subject_nr}")
# Get with a default value
speed = var.get('speed', default=1.0)
# Get with validation
order = var.get('order', valid=['random', 'sequential'])
# Check existence
if 'my_var' in var:
print('my_var is defined')
# Delete a variable
del var.soa
# Enumerate all variables
for name in var:
print(name, var.get(name, _eval=False))
# List all variable names
print(var.vars())
# List all (name, value) pairs
for name, value in var.items():
print(f" {name} = {value}")
```
```
--------------------------------
### Handle Missing Dependencies in Python
Source: https://context7.com/open-cogsci/opensesame/llms.txt
Use a try-except ImportError block to check for optional dependencies and raise a MissingDependency error if a required library is not found.
```python
try:
import psychopy
except ImportError:
raise MissingDependency('psychopy is required for this backend')
```
--------------------------------
### Retrieve Variables with VarStore.get()
Source: https://context7.com/open-cogsci/opensesame/llms.txt
Use `var.get()` for safe variable retrieval, supporting defaults, raw value access, and validation against a list of allowed values. Dynamic variable names can be set using `var.set()`.
```python
# Simple attribute-style access
condition = var.condition
# Get with default (no VariableDoesNotExist exception)
soa = var.get('soa', default=500)
# Get raw value without evaluating [variable] references
raw_label = var.get('label_text', _eval=False)
# Get with allowed-value validation
order = var.get('order', valid=['random', 'sequential'])
# Raises InvalidValue if var.order is not in the list
# In a loop inline_script, use var.set() for dynamic variable names
var_name = f'acc_block_{var.block_nr}'
var.set(var_name, responses.acc)
```
--------------------------------
### Manage Experimental Variables with VarStore
Source: https://context7.com/open-cogsci/opensesame/llms.txt
Access and modify experimental variables using the global `var` object. Variables can be set, retrieved with defaults or validation, checked for existence, deleted, and enumerated. Supports automatic type conversion for numeric strings.
```python
# Inside an inline_script item — `var` is available globally
# Set variables (type is auto-converted: numeric strings become int/float)
var.condition = 'congruent'
var.soa = 500
var.correct_response = 'left'
# Get variables
print(f"Subject {var.subject_nr}, parity={var.subject_parity}")
print(f"Condition: {var.condition}")
# Get with a default (no exception if missing)
speed = var.get('speed', default=1.0)
# Get with validation (raises InvalidValue if not in list)
order = var.get('order', valid=['random', 'sequential'])
# Check existence
if 'my_var' in var:
print('my_var is defined')
# Delete a variable
del var.soa
# Enumerate all variables
for name in var:
print(name, var.get(name, _eval=False))
# List all variable names
print(var.vars())
# List all (name, value) pairs
for name, value in var.items():
print(f" {name} = {value}")
```
--------------------------------
### Display Canvas for Fixed Duration and Blank Screen
Source: https://context7.com/open-cogsci/opensesame/llms.txt
Show a canvas for a specified duration using `clock.sleep()` and then clear the screen by displaying a blank canvas. This is useful for presenting stimuli for a set amount of time before proceeding.
```python
# Show canvas for a fixed duration, then blank
c.show()
clock.sleep(200)
Canvas().show() # blank canvas
```
--------------------------------
### Keyboard Response Collection
Source: https://context7.com/open-cogsci/opensesame/llms.txt
The `Keyboard` class collects key-press and key-release events. Response keywords like `keylist` and `timeout` can be set at construction or per-call. Returns `(key, timestamp)` tuples.
```python
# Wait for 'left' or 'right' arrow with 2000 ms timeout
kb = Keyboard(keylist=['left', 'right'], timeout=2000)
key, t_press = kb.get_key()
if key is None:
print('Timeout — no response')
elif key == 'left':
correct = (var.correct_response == 'left')
responses.add(response=key, correct=correct,
response_time=t_press - t_onset, item='my_trial')
else:
print(f'Pressed: {key}')
```
```python
# Key-release detection
key, t_release = kb.get_key_release(keylist=['space'], timeout=5000)
```
```python
# Override defaults per-call
kb2 = Keyboard()
kb2.keylist = ['a', 'b']
kb2.timeout = 3000
key1, t1 = kb2.get_key()
key2, t2 = kb2.get_key()
```
```python
# Check modifier keys (shift, ctrl, alt)
mods = kb2.get_mods()
print('Modifiers pressed:', mods)
```
```python
# Flush pending keypresses before a new trial
kb2.flush()
```
```python
# Full RT measurement pattern
c = Canvas()
c.fixdot()
t_onset = c.show()
kb3 = Keyboard(keylist=['z', 'm'], timeout=3000)
key, t_response = kb3.get_key()
rt = t_response - t_onset if key is not None else None
responses.add(response=key, correct=(key == var.correct_response),
response_time=rt, item='keyboard_trial')
```
--------------------------------
### Arrange Stimuli on a Grid
Source: https://context7.com/open-cogsci/opensesame/llms.txt
Use `xy_grid` to generate coordinates for placing items in a rectangular grid. The `Canvas` object is used to draw and display the stimuli.
```python
from libopensesame.python_workspace_api import xy_grid
c2 = Canvas()
for x, y in xy_grid(n=(4, 3), spacing=(80, 80)): # 4×3 grid
c2.circle(x, y, 20, fill=True)
c2.show()
```
--------------------------------
### Synth: Tone Synthesis
Source: https://context7.com/open-cogsci/opensesame/llms.txt
The `Synth` class synthesizes tones without requiring sound files, offering precise control over frequency and envelopes. It returns a `Sampler` object.
```python
# Sine wave at 440 Hz, 500 ms, with 10 ms attack/decay
tone = Synth(osc='sine', freq=440, length=500, attack=10, decay=10, volume=0.8)
tone.play()
```
```python
# Musical note notation
high_c = Synth(osc='square', freq='C5', length=200, volume=0.6)
high_c.play()
```
```python
# White noise burst
noise = Synth(osc='white_noise', length=300, volume=0.4)
noise.play()
```
```python
# Sawtooth feedback tone (error signal)
error_tone = Synth(osc='saw', freq='A3', length=400, attack=5, decay=20)
error_tone.play()
error_tone.wait()
```
--------------------------------
### Configure Loop Items for Experimental Designs
Source: https://context7.com/open-cogsci/opensesame/llms.txt
Modify loop tables using `DataMatrix` and control loop behavior with `loop.var.repeat` and `loop.var.order`. Live loop variables are accessible via `var.live_row`, and cycles can be repeated using `var.repeat_cycle`.
```python
# Accessing and modifying a loop table from an inline_script
from datamatrix import DataMatrix
loop = items['my_loop']
# Replace the loop table entirely
dm = DataMatrix(length=4)
dm.word = ['red', 'green', 'blue', 'yellow']
dm.ink_color = ['red', 'blue', 'red', 'green']
dm.correct = ['r', 'b', 'r', 'g']
loop.dm = dm
# Configure loop settings
loop.var.repeat = 3 # run each row 3 times
loop.var.order = 'random' # or 'sequential'
loop.var.break_if = 'never' # break condition expression
# Constraints (set in OpenSesame script, not Python API directly)
# constrain word maxrep=2 → no word repeats more than twice in a row
# constrain word mindist=3 → same word never within 3 trials
# Read live loop variables inside a trial
print(f"Trial {var.live_row}: word={var.word}, ink={var.ink_color}")
# Repeat the current cycle (e.g., after invalid response)
var.repeat_cycle = 1
```
--------------------------------
### Arrange Stimuli on a Circle
Source: https://context7.com/open-cogsci/opensesame/llms.txt
Use `xy_circle` to generate coordinates for placing items in a circular pattern. The `Canvas` object is used to draw and display the stimuli.
```python
from libopensesame.python_workspace_api import xy_circle
c = Canvas()
for x, y in xy_circle(n=6, rho=150, phi0=0): # 6 items on radius 150
c.rect(x-15, y-15, 30, 30, fill=True)
c.show()
```
--------------------------------
### Keyboard Response Collection
Source: https://context7.com/open-cogsci/opensesame/llms.txt
Collects key-press and key-release events. Response keywords (`keylist`, `timeout`) can be set at construction or per-call. Returns `(key, timestamp)` tuples where `key` is `None` on timeout.
```APIDOC
## Keyboard
### Description
Collects key-press and key-release events. Response keywords (`keylist`, `timeout`) can be set at construction or per-call. Returns `(key, timestamp)` tuples where `key` is `None` on timeout.
### Method
`Keyboard(keylist=None, timeout=None)`
### Parameters
#### Constructor Parameters
- **keylist** (list or tuple) - Optional - A list of keys to listen for.
- **timeout** (int) - Optional - The maximum time in milliseconds to wait for a response.
### Methods
- **get_key()**: Waits for a key press and returns `(key, timestamp)`.
- **get_key_release(keylist=None, timeout=None)**: Waits for a key release and returns `(key, timestamp)`.
- **get_mods()**: Returns a tuple indicating which modifier keys (shift, ctrl, alt) are pressed.
- **flush()**: Clears any pending keypresses.
### Request Example
```python
# Wait for 'left' or 'right' arrow with 2000 ms timeout
kb = Keyboard(keylist=['left', 'right'], timeout=2000)
key, t_press = kb.get_key()
if key is None:
print('Timeout — no response')
elif key == 'left':
correct = (var.correct_response == 'left')
responses.add(response=key, correct=correct,
response_time=t_press - t_onset, item='my_trial')
else:
print(f'Pressed: {key}')
# Key-release detection
key, t_release = kb.get_key_release(keylist=['space'], timeout=5000)
# Override defaults per-call
kb2 = Keyboard()
kb2.keylist = ['a', 'b']
kb2.timeout = 3000
key1, t1 = kb2.get_key()
key2, t2 = kb2.get_key()
# Check modifier keys (shift, ctrl, alt)
mods = kb2.get_mods()
print('Modifiers pressed:', mods)
# Flush pending keypresses before a new trial
kb2.flush()
# Full RT measurement pattern
c = Canvas()
c.fixdot()
t_onset = c.show()
kb3 = Keyboard(keylist=['z', 'm'], timeout=3000)
key, t_response = kb3.get_key()
rt = t_response - t_onset if key is not None else None
responses.add(response=key, correct=(key == var.correct_response),
response_time=rt, item='keyboard_trial')
```
```
--------------------------------
### Canvas - Visual Stimulus Presentation
Source: https://context7.com/open-cogsci/opensesame/llms.txt
`Canvas` is the primary drawing surface for presenting visual stimuli. Drawing methods return element names, and elements can be updated or removed efficiently.
```APIDOC
## Canvas — Visual Stimulus Presentation
### Description
The primary drawing surface for visual stimuli. Supports various shapes, text, images, and complex stimuli like Gabor patches. Elements persist across `show()` calls and can be updated by name.
### Usage
```python
from libopensesame.python_workspace_api import Canvas, FixDot, Text
# Basic canvas usage
c = Canvas(color='white', background_color='black', penwidth=2)
c.fixdot()
c.text('Hello world', y=-100)
c.rect(-50, -50, 100, 100, fill=True, color='red')
c.circle(0, 0, 40, fill=False, color='yellow')
c.line(-200, 0, 200, 0)
c.arrow(0, 100, 0, 200, body_length=0.8, head_width=25)
c.ellipse(-100, -50, 200, 100, fill=True, color='blue')
c.image(pool['face.png'], center=True, x=0, y=0, scale=0.5)
c.gabor(x=100, y=0, orient=45, freq=0.1, env='gaussian', size=96)
c.noise_patch(x=-100, y=0, env='gaussian', size=96)
t = c.show() # returns timestamp (ms) when canvas appeared on screen
# Named element access for dynamic updates
c = Canvas()
c['stim'] = Text('initial', color='white')
c['fix'] = FixDot()
c.show()
clock.sleep(500)
c['stim'].text = 'updated text' # modify in place
c['stim'].color = 'green'
del c['stim'] # remove element
c.show()
# Get element names at a specific position
names = c.elements_at(mouse_x, mouse_y)
# Show canvas for a fixed duration, then blank
c.show()
clock.sleep(200)
Canvas().show() # blank canvas
```
```
--------------------------------
### Reset Feedback Counters
Source: https://context7.com/open-cogsci/opensesame/llms.txt
Explains how to reset feedback counters, such as accuracy, between experimental blocks using `reset_feedback` or `responses.reset_feedback()`.
```python
# Reset feedback counters between blocks
from libopensesame.python_workspace_api import reset_feedback
reset_feedback()
# Equivalently:
responses.reset_feedback()
```
--------------------------------
### Repeat Trial if Response Time Exceeds Threshold
Source: https://github.com/open-cogsci/opensesame/blob/nightingale/opensesame_plugins/core/repeat_cycle/repeat_cycle.md
Use this condition in a `repeat_cycle` item to repeat trials where the response time is greater than 3000 ms. This is typically placed after a response item like `keyboard_response`.
```OpenSesame Script
[response_time] > 3000
```
--------------------------------
### Force Cycle Repetition with Inline Script
Source: https://github.com/open-cogsci/opensesame/blob/nightingale/opensesame_plugins/core/repeat_cycle/repeat_cycle.md
Programmatically force a cycle to repeat by setting the `repeat_cycle` variable to 1 within an `inline_script`. This provides explicit control over trial repetition.
```Python
var.repeat_cycle = 1
```
--------------------------------
### Embed Python Scripts with InlineScript
Source: https://context7.com/open-cogsci/opensesame/llms.txt
Use `InlineScript` items to run Python code during the prepare and run phases of an experiment. Workspace variables like `var`, `exp`, and `responses` are directly available.
```python
# --- PREPARE PHASE ---
# Pre-build stimuli to minimize run-phase overhead
import random
# Create two target canvases
c_congruent = Canvas()
c_congruent.text('[word]', color='[ink_color]') # bracket variables evaluated at run-time
c_congruent.fixdot(y=150)
c_incongruent = Canvas()
c_incongruent.text('[word]', color='[ink_color]')
# Pre-create the keyboard object
kb = Keyboard(keylist=['r', 'g', 'b'], timeout=2000)
# --- RUN PHASE ---
# Present stimuli and collect response
if var.condition == 'congruent':
t_onset = c_congruent.show()
else:
t_onset = c_incongruent.show()
key, t_response = kb.get_key()
rt = t_response - t_onset if key is not None else None
responses.add(
response=key,
correct=int(key == var.correct_response) if key else None,
response_time=rt,
item=self.name # self refers to the inline_script item
)
# Show blank ISI
Canvas().show()
clock.sleep(500)
```
--------------------------------
### Validate Form Input with Python
Source: https://context7.com/open-cogsci/opensesame/llms.txt
Use a try-except block to validate integer input from a form field and raise an error if it's out of the expected range.
```python
try:
age = int(var.age_input)
if not (18 <= age <= 99):
raise InvalidValue('Age must be between 18 and 99')
except (ValueError, InvalidValue) as e:
var.error_message = str(e)
```
--------------------------------
### Clock - Timing
Source: https://context7.com/open-cogsci/opensesame/llms.txt
The `clock` object is automatically available in all Python scripts and provides millisecond-accurate timing functions.
```APIDOC
## Clock
### Description
The `clock` object is automatically available in all Python scripts and provides millisecond-accurate timing functions.
### Methods
- **time()**: Returns the current time in milliseconds since the experiment started.
- **sleep(duration)**: Pauses execution for the specified duration in milliseconds.
### Request Example
```python
# Measure elapsed time between two events
t0 = clock.time()
clock.sleep(500)
t1 = clock.time()
print(f'Elapsed: {t1 - t0:.1f} ms') # ~500 ms
# Stimulus onset asynchrony (SOA) with accurate sleep
c1 = Canvas()
c1.fixdot()
t_fix = c1.show()
clock.sleep(500) # hold fixation for 500 ms
c2 = Canvas()
c2.text('Target', color='white')
t_stim = c2.show()
soa = t_stim - t_fix
print(f'Actual SOA: {soa:.1f} ms')
```
```
--------------------------------
### Mouse Response Collection
Source: https://context7.com/open-cogsci/opensesame/llms.txt
The `Mouse` class collects mouse-button clicks, releases, and cursor-position samples. Coordinates are center-referenced by default. Buttons are numbered 1 (left), 2 (middle), 3 (right), etc.
```python
# Wait for left or right click with timeout
my_mouse = Mouse(buttonlist=[1, 3], timeout=5000)
button, pos, t_click = my_mouse.get_click()
if button is None:
print('Timeout')
elif button == 1:
x, y = pos
print(f'Left click at ({x}, {y})')
```
```python
# Live cursor-tracking loop until click
my_mouse2 = Mouse()
c = Canvas()
while True:
button, pos, ts = my_mouse2.get_click(timeout=20)
if button is not None:
break
(mx, my_y), t = my_mouse2.get_pos()
c.clear()
c.fixdot(mx, my_y)
c.show()
```
```python
# Query which buttons are currently held
b1, b2, b3 = my_mouse2.get_pressed()
```
```python
# Show/hide cursor
my_mouse2.show_cursor(False)
```
```python
# Flush pending clicks before a new trial
my_mouse2.flush()
```
--------------------------------
### Draw Basic Shapes and Text on Canvas
Source: https://context7.com/open-cogsci/opensesame/llms.txt
Utilize the Canvas object to draw various visual elements including text (with HTML support), rectangles, circles, lines, arrows, ellipses, images, and Gabor patches. Coordinates are relative to the center (0,0). The show() method returns the timestamp when the canvas is displayed.
```python
# Basic canvas usage
c = Canvas(color='white', background_color='black', penwidth=2)
c.fixdot() # default fixation dot at center
c.text('Hello world', y=-100) # HTML tags supported
c.rect(-50, -50, 100, 100, fill=True, color='red')
c.circle(0, 0, 40, fill=False, color='yellow')
c.line(-200, 0, 200, 0)
c.arrow(0, 100, 0, 200, body_length=0.8, head_width=25)
c.ellipse(-100, -50, 200, 100, fill=True, color='blue')
c.image(pool['face.png'], center=True, x=0, y=0, scale=0.5)
c.gabor(x=100, y=0, orient=45, freq=0.1, env='gaussian', size=96)
c.noise_patch(x=-100, y=0, env='gaussian', size=96)
t = c.show() # returns timestamp (ms) when canvas appeared on screen
```
--------------------------------
### Conditional Execution with `sometimes`
Source: https://context7.com/open-cogsci/opensesame/llms.txt
Uses the `sometimes` function to probabilistically execute code blocks. This is useful for introducing randomness, such as assigning stimuli to the left or right side.
```python
# Probabilistic branching
from libopensesame.python_workspace_api import sometimes
if sometimes(p=0.5):
var.probe_side = 'left'
else:
var.probe_side = 'right'
```
--------------------------------
### Mouse Response Collection
Source: https://context7.com/open-cogsci/opensesame/llms.txt
Collects mouse-button clicks, releases, and cursor-position samples. Coordinates are center-referenced by default. Buttons: 1=left, 2=middle, 3=right, 4=scroll-up, 5=scroll-down.
```APIDOC
## Mouse
### Description
Collects mouse-button clicks, releases, and cursor-position samples. Coordinates are center-referenced by default. Buttons: 1=left, 2=middle, 3=right, 4=scroll-up, 5=scroll-down.
### Method
`Mouse(buttonlist=None, timeout=None)`
### Parameters
#### Constructor Parameters
- **buttonlist** (list or tuple) - Optional - A list of mouse buttons to listen for (1=left, 2=middle, 3=right, 4=scroll-up, 5=scroll-down).
- **timeout** (int) - Optional - The maximum time in milliseconds to wait for a response.
### Methods
- **get_click(buttonlist=None, timeout=None)**: Waits for a mouse button click and returns `(button, pos, timestamp)`.
- **get_pos(timeout=None)**: Returns the current cursor position `((x, y), timestamp)`.
- **get_pressed()**: Returns a tuple indicating which buttons are currently held down (e.g., `(b1, b2, b3)`).
- **show_cursor(show=True)**: Controls the visibility of the mouse cursor.
- **flush()**: Clears any pending mouse events.
### Request Example
```python
# Wait for left or right click with timeout
my_mouse = Mouse(buttonlist=[1, 3], timeout=5000)
button, pos, t_click = my_mouse.get_click()
if button is None:
print('Timeout')
elif button == 1:
x, y = pos
print(f'Left click at ({x}, {y})')
# Live cursor-tracking loop until click
my_mouse2 = Mouse()
c = Canvas()
while True:
button, pos, ts = my_mouse2.get_click(timeout=20)
if button is not None:
break
(mx, my_y), t = my_mouse2.get_pos()
c.clear()
c.fixdot(mx, my_y)
c.show()
# Query which buttons are currently held
b1, b2, b3 = my_mouse2.get_pressed()
# Show/hide cursor
my_mouse2.show_cursor(False)
# Flush pending clicks before a new trial
my_mouse2.flush()
```
```
--------------------------------
### Manage Canvas Elements by Name
Source: https://context7.com/open-cogsci/opensesame/llms.txt
Assign names to canvas elements for dynamic updates, removal, or modification. Elements can be accessed, modified in place (e.g., changing text or color), or deleted by their assigned name. This allows for efficient animation and state changes.
```python
# Named element access — efficient for dynamic updates
c = Canvas()
c['stim'] = Text('initial', color='white')
c['fix'] = FixDot()
c.show()
clock.sleep(500)
c['stim'].text = 'updated text' # modify in place
c['stim'].color = 'green'
del c['stim'] # remove element
c.show()
```
--------------------------------
### Polar to Cartesian Coordinate Conversion
Source: https://context7.com/open-cogsci/opensesame/llms.txt
Shows how to convert polar coordinates (rho, phi) to Cartesian coordinates (x, y) using `xy_from_polar`. This is useful for positioning elements based on distance and angle.
```python
# Polar ↔ Cartesian conversion
from libopensesame.python_workspace_api import (
xy_from_polar, xy_to_polar, xy_distance, xy_circle, xy_grid, xy_random
)
# Draw an X through the center
x1, y1 = xy_from_polar(rho=150, phi=45)
x2, y2 = xy_from_polar(rho=150, phi=-45)
c = Canvas()
c.line(x1, y1, -x1, -y1)
c.line(x2, y2, -x2, -y2)
c.show()
# Convert back to polar
rho, phi = xy_to_polar(x1, y1)
# Distance between two points
d = xy_distance(0, 0, 100, 100) # ≈ 141.4
# 8 items arranged in a circle
c = Canvas()
for x, y in xy_circle(n=8, rho=200, phi0=0):
c.circle(x, y, 20, fill=True)
c.fixdot()
c.show()
# 3×3 grid of stimuli
c = Canvas()
for x, y in xy_grid(n=3, spacing=120):
c.rect(x-30, y-30, 60, 60, fill=False)
c.show()
# 20 randomly placed circles, minimum 50 px apart
c = Canvas()
for x, y in xy_random(n=20, width=800, height=600, min_dist=50):
c.circle(x, y, 15, fill=True, color='yellow')
c.show()
```
--------------------------------
### Override Subject Number Mid-Experiment
Source: https://context7.com/open-cogsci/opensesame/llms.txt
Demonstrates how to programmatically change the subject number during an experiment using `set_subject_nr`. This can be useful for debugging or specific experimental designs.
```python
# Override subject number mid-experiment
from libopensesame.python_workspace_api import set_subject_nr
set_subject_nr(42)
print(f"subject_nr={var.subject_nr}, parity={var.subject_parity}")
```
=== COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.