Skip to content

JoseAlanis/lsl-trigger-debugger

Repository files navigation

LSL Trigger Debugger

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.

What it does

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.

Supported streams

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 Markers streams are accepted. To allow additional types, edit the [tool.lsl-debugger] section in pyproject.toml.

If you need to inspect continuous physiological data, use a dedicated tool like LabRecorder.

Primary use case

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.

Installation

Requires Python 3.10+.

Using uv (recommended)

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 | sh

Clone the repository and navigate to the project root:

git clone https://github.com/JoseAlanis/lsl-trigger-debugger.git
cd lsl-trigger-debugger

From the project root, install the dependencies:

uv sync

Using pip

Alternatively, install with pip:

pip install .

Usage

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
  1. The app auto-discovers LSL streams on launch. Click Refresh to re-scan if needed.
  2. Select a stream from the dropdown and click Connect.
  3. Triggers appear as red vertical lines on the timeline with their codes labeled above.
  4. Click Disconnect when done.

You should see something like this:

LSL Trigger Debugger demo

Options

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-plot

Testing without an experiment

A 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-debugger

The sender pushes random trigger codes (1, 2, 3, 4, 10, 20, 99, 100, 255) at 0.5 to 3 second intervals.

Dependencies

  • 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)

Project structure

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 usage disclosure

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.

About

A lightweight desktop tool for monitoring LSL trigger streams in real time.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages