Python client¶
The vstimd Python package is the reference client. It opens a ZMQ connection to a
server and exposes typed command namespaces, so you never touch protobuf or sockets
directly. For step-by-step walkthroughs see the tutorials;
this page is the reference for the client's shape.
Install¶
Requires Python ≥ 3.12 and uv:
See Installation for other options.
Connect¶
A Connection opens a ZMQ REQ socket and exposes the command namespaces. Use it as a
context manager so the socket is always closed:
from vstimd import Connection
with Connection() as conn: # default: tcp://localhost:5555
info = conn.system.query_server_info()
print(info.width, info.height, info.frame_rate)
Pass an address for a remote device: Connection("tcp://stimulus-pc:5555").
Every call is a synchronous round-trip: the client blocks until the server acknowledges, and a server error is raised as a typed exception (see Errors).
Namespaces¶
| Namespace | What it does | Key methods |
|---|---|---|
conn.stimuli |
Generic per-stimulus commands | set_position, set_orientation, set_fill_color, set_alpha, set_enabled, set_name, delete, query, bring_to_front, send_to_back, swap_draw_order |
conn.stimuli.shapes |
Create/mutate shapes | create_rect, create_circle, create_ellipse, set_rect_size, set_circle_radius, set_ellipse_size, set_draw_mode, set_outline_color, set_outline_width |
conn.stimuli.grating |
Create/mutate gratings | create_grating, set_phase, set_sf, set_contrast, set_waveform, set_mask, set_drift_speed, set_drift_angle, set_fore_color, … |
conn.stimuli.text |
Create/mutate text | create_text, set_text, set_text_color |
conn.system |
Scene-wide + queries | set_background, set_all_enabled, delete_all, set_deferred_mode, list_stimuli, query_server_info, wait_for_frames, wait_until |
conn.animations |
On-device animations | create_flash, create_flicker, create_move_along_path_2d, create_couple_visibility_to_trigger_line, arm, disarm, cancel, query, … |
conn.vtl |
Virtual Trigger Lines | set_line_name, set_line, toggle_line, list_lines |
conn.config |
Save/load scenes | save, load, list_configs, retrieve, upload |
The method list above is a map, not an exhaustive signature reference — the
authoritative signatures and docstrings live in the source under
client/python/vstimd/.
Stimulus types¶
Creating a stimulus returns a handle you pass to later commands. Positions are in pixels from the screen centre, Y up (see Coordinate system); colours are RGBA in 0–1.
| Type | Create with |
|---|---|
| Rectangle | conn.stimuli.shapes.create_rect(...) |
| Circle | conn.stimuli.shapes.create_circle(...) |
| Ellipse | conn.stimuli.shapes.create_ellipse(...) |
| Grating | conn.stimuli.grating.create_grating(...) |
| Text | conn.stimuli.text.create_text(...) |
from vstimd import Connection
from vstimd.stimuli import Vec2, Color
with Connection() as conn:
rect = conn.stimuli.shapes.create_rect(
pos=Vec2(0, 0), width=300, height=150, color=Color(1.0, 0.0, 0.0),
)
conn.stimuli.set_position(rect, Vec2(-200, 100))
conn.stimuli.set_enabled(rect, True)
print(conn.stimuli.query(rect)) # full current state
Errors¶
Each non-OK server response is raised as a subclass of VstimdError:
| Exception | Raised when |
|---|---|
HandleNotFoundError |
The stimulus handle does not exist |
WrongStimulusTypeError |
A mutation does not apply to this stimulus type |
WrongTargetError |
A system command was sent to a stimulus handle (or vice versa) |
CreationFailedError |
The server could not create the stimulus |
InvalidArgumentError |
A field value is out of range or invalid |
NotSupportedError |
The command is not supported in this build/config |
NotReadyError |
Server still initialising — retry after the first frame |
ConfigNotFoundError, ConfigIoError, ConfigFormatError, ConfigVersionError, ConfigAlreadyExistsError |
Config save/load failures |
UnknownServerError |
Unexpected server-side error |
from vstimd.exceptions import HandleNotFoundError
try:
conn.stimuli.set_enabled(bad_handle, True)
except HandleNotFoundError:
...
PsychoPy compatibility¶
The vstimd.psychopy layer mirrors psychopy.visual on top of the command API —
often a one-line import swap:
# from psychopy import visual
from vstimd.psychopy import visual
win = visual.Window(address="tcp://stimulus-pc:5555")
rect = visual.Rect(win, width=0.5, height=0.25, fillColor="red")
rect.draw()
win.flip()
Timing note
The PsychoPy-compatible layer drives updates through Python round-trips and does not expose the animation or VTL systems. For timing-critical reactions, use the command API directly and move them into animations.
Examples¶
Runnable scripts live in
client/python/examples/:
cd client/python
uv run examples/flash_rects.py # flashing rectangles
uv run examples/interactive_grating.py # live grating controls
uv run examples/text_demo.py # text rendering
Other clients¶
- C# / Bonsai — supported over the same wire protocol.
- MATLAB — planned; not yet available (see
client/matlab/). - Roll your own — any language that can speak ZMQ + protobuf works; see the wire protocol.