Episode 3: Capturing Keystrokes
Capture keyboard events and integrate them into your pipelines as input signals or triggers. This episode demonstrates recording and forwarding keystrokes for use in annotations, experiment control, and real-time event handling.
Note
This page is still under development. Until we have the step-by-step instructions ready, please refer to the code example below.
File example_basic_keyboard.py – View file on GitHub
1"""
2Basic Keyboard Example - Interactive Event Markers and User Input
3
4This example demonstrates how to capture keyboard input and combine it with
5signal data to create interactive BCI experiments. It shows how to use the
6Keyboard node for real-time event marking and user interaction during data
7visualization.
8
9What this example shows:
10- Generating synthetic 8-channel EEG-like signals
11- Capturing keyboard input (arrow keys) as event markers
12- Combining signal data with keyboard events using Router
13- Real-time visualization with color-coded event markers
14- Interactive user input during signal processing
15
16Expected output:
17When you run this example, you'll see:
18- 8 channels of synthetic EEG signals in real-time
19- Event markers appearing when you press arrow keys:
20 * ↑ (Up): Red marker on channel 8
21 * → (Right): Green marker on channel 8
22 * ↓ (Down): Blue marker on channel 8
23 * ← (Left): Black marker on channel 8
24- Combined display of continuous signals and discrete events
25
26Interactive controls:
27Press arrow keys while the application is running to create event markers.
28Each key press generates a numerical code that appears as a colored spike
29in the display and gets combined with the signal data.
30
31Real-world applications:
32- BCI paradigm development and testing
33- Event-related potential (ERP) experiments
34- Motor imagery training with feedback
35- Interactive neurofeedback applications
36- Behavioral response recording during experiments
37- Real-time experimental control and annotation
38
39Technical details:
40- Router combines 8 signal channels + 1 event channel = 9 total channels
41- Keyboard events appear on channel 8 (last channel)
42- Event codes: Up=38, Right=39, Down=40, Left=37 (standard key codes)
43- Markers provide visual feedback for successful key presses
44- Real-time synchronization between signals and events
45
46Usage:
47 python example_basic_keyboard.py
48 Press arrow keys to create colored event markers
49 Close window to stop the application
50
51Note:
52 This example forms the basis for more complex interactive BCI paradigms
53 where user input needs to be synchronized with neural signal recording.
54"""
55import gpype as gp
56
57fs = 250 # Sampling frequency in Hz
58
59if __name__ == "__main__":
60 # Create the main application window
61 app = gp.MainApp()
62
63 # Create processing pipeline
64 p = gp.Pipeline()
65
66 # Generate synthetic 8-channel EEG-like signals
67 source = gp.Generator(
68 sampling_rate=fs,
69 channel_count=8, # 8 EEG channels
70 signal_frequency=10, # 10 Hz alpha rhythm
71 signal_amplitude=10, # Signal strength
72 signal_shape="sine", # Clean sine waves
73 noise_amplitude=10,
74 ) # Background noise
75
76 # Capture keyboard input as event markers
77 keyboard = gp.Keyboard() # Arrow keys -> numerical event codes
78
79 # Combine signal data (8 channels) + keyboard events (1 channel)
80 router = gp.Router(input_channels=[gp.Router.ALL, gp.Router.ALL])
81
82 # Define colored markers for visual feedback (values are key codes)
83 mk = gp.TimeSeriesScope.Markers
84 markers = [
85 mk(color="r", label="up", channel=8, value=38),
86 mk(color="g", label="right", channel=8, value=39),
87 mk(color="b", label="down", channel=8, value=40),
88 mk(color="k", label="left", channel=8, value=37),
89 ]
90
91 # Real-time visualization with interactive markers
92 scope = gp.TimeSeriesScope(
93 amplitude_limit=30, # Y-axis range
94 time_window=10, # 10 seconds history
95 markers=markers,
96 ) # Event visualization
97
98 # Connect processing chain: signals + events -> combined display
99 p.connect(source, router["in1"]) # Signal data -> Router input 1
100 p.connect(keyboard, router["in2"]) # Keyboard events -> Router input 2
101 p.connect(router, scope) # Combined data -> Display
102
103 # Add scope to application window
104 app.add_widget(scope)
105
106 # Start interactive signal processing
107 p.start() # Begin processing (press arrow keys for events)
108 app.run() # Show GUI and start main loop
109 p.stop() # Clean shutdown when window closes