A small desktop utility for monitoring trigger codes sent via Lab Streaming Layer in real time. The goal of the debugger is to help verify that event markers (stimulus onsets, keyboard responses, etc.) are correctly being sent during psychological / neuroscientific experiments (e.g., using PsychoPy or similar experimental control tools). It is often useful to test trigger functionality when using electroencephalography or other brain imaging or physiological recordings. Typically, this can be done by recording "test data" or letting some acquisition software run without actually recording data. This can be tedious because it requires connecting recording equipment and making preparations that are not actually needed, or using the devices (e.g., battery life) even though, at early piloting stages, this is actually not necessary. This tool solves that problem by providing a lightweight, easy-to-use framework for testing trigger functionality in a dedicated environment in real time. The debugger provides visualizations of how the triggers "would look like" in the real acquisition software and the ability to browse through the trigger stream.
The app connects to an LSL stream and displays incoming triggers on a scrolling timeline:
- Stream discovery: Automatically finds available LSL streams on the network at launch. Marker streams are sorted to the top of the dropdown.
- Stream info panel: Shows metadata about the connected stream (name, type, source ID, channel count, sample rate, format).
- Real-time timeline: A horizontal baseline with vertical red lines for each trigger. Each line is annotated with the trigger code (integer) or label (string). The timeline auto-scrolls to follow incoming events.
The debugger is designed for single-channel, low-rate marker streams (irregular or up to 10 Hz), the kind typically used to send event codes in experimental paradigms. All discovered LSL streams are shown in the dropdown for transparency, but the app will reject streams that are not suitable for trigger viewing:
- Multichannel streams (e.g., EEG with 64 channels) are rejected because the timeline can only display one value per sample.
- High-rate continuous streams (> 10 Hz) are rejected because they would flood the timeline with thousands of markers per second.
- Unrecognized stream types are rejected based on a configurable allowlist. By default only
Markersstreams are accepted. To allow additional types, edit the[tool.lsl-debugger]section inpyproject.toml.
If you need to inspect continuous physiological data, use a dedicated tool like LabRecorder.
Testing trigger codes sent from PsychoPy experiments. A typical PsychoPy setup creates a Markers stream with int32 format and pushes integer trigger codes via outlet.push_sample([trigger_code]). This debugger lets you verify those codes arrive correctly before or during a recording session.
Requires Python 3.10+.
uv is a Python package manager. If you don't have it, it can be installed via command line:
# Windows (PowerShell)
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | shClone the repository and navigate to the project root:
git clone https://github.com/JoseAlanis/lsl-trigger-debugger.git
cd lsl-trigger-debuggerFrom the project root, install the dependencies:
uv syncAlternatively, install with pip:
pip install .Start the debugger:
# If installed via uv sync or pip install
lsl-trigger-debugger
# Or run directly
uv run lsl-trigger-debugger
# Or via python module
python -m lsl_trigger_debugger- The app auto-discovers LSL streams on launch. Click Refresh to re-scan if needed.
- Select a stream from the dropdown and click Connect.
- Triggers appear as red vertical lines on the timeline with their codes labeled above.
- Click Disconnect when done.
You should see something like this:
| Flag | Default | Description |
|---|---|---|
--interactive-plot |
off | Enable plot controls (pan, zoom, right-click menu) |
By default, the timeline is a clean, non-interactive display. Pass --interactive-plot if you want to manually pan/zoom or access the pyqtgraph context menu:
lsl-trigger-debugger --interactive-plotA sender simulation script is included that mimics a PsychoPy-like marker stream:
# Terminal 1: start the fake sender
python simulate_sender.py
# Terminal 2: start the debugger
lsl-trigger-debuggerThe sender pushes random trigger codes (1, 2, 3, 4, 10, 20, 99, 100, 255) at 0.5 to 3 second intervals.
- pylsl - Python bindings for Lab Streaming Layer
- PyQt6 - GUI framework
- pyqtgraph - Fast real-time 2D plotting
- numpy - Array operations (used by pyqtgraph)
- tomli - TOML parser (only on Python < 3.11; 3.11+ uses the stdlib
tomllib)
src/lsl_trigger_debugger/
__init__.py - Package marker
__main__.py - Enables `python -m lsl_trigger_debugger`
app.py - Entry point, argument parsing, config loading
debugger.py - All app logic: MainWindow, LSLWorker, timeline rendering
simulate_sender.py - Script that simulates an LSL marker stream for testing
pyproject.toml - Project config, dependencies, and CLI entry point
AI tools were used during the development of this project:
- Claude Opus 4.6 (Anthropic), was used mostly for brainstorming features, implementations, and bug fixes.
- Codex 5.4 (OpenAI), was used for support during code review and auditing edge cases.
Suggested changes were implemented after testing locally and verifying that issues are solved without side effects.
