Episode 3: Auditory Evoked Potentials
Learn how to record Auditory Evoked Potentials (AEPs) with g.Pype. This episode demonstrates how to run AEP paradigms and synchronize auditory stimuli with EEG acquisition for precise event-related potential analysis.
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_paradigm_aep_single_stim.py – View file on GitHub
1from pathlib import Path
2import os
3
4import gpype as gp
5
6parent_dir = os.path.dirname(os.path.abspath(__file__))
7paradigm = os.path.join(parent_dir, "paradigms", "AEPSingleStim.xml")
8sampling_rate = 250
9channel_count = 8
10
11if __name__ == "__main__":
12
13 # Create main application & pipeline
14 app = gp.MainApp()
15 p = gp.Pipeline()
16
17 # Amplifier: BCI Core-8 (uncomment if you want to use it)
18 # amp = gp.BCICore8()
19
20 # Amplifier: g.Nautilus (uncomment if you want to use it)
21 # amp = gp.GNautilus(sampling_rate=sampling_rate,
22 # channel_count=channel_count)
23
24 # Signal generator (uncomment if you want to use it)
25 amp = gp.Generator(
26 sampling_rate=sampling_rate,
27 channel_count=channel_count,
28 signal_frequency=10,
29 signal_amplitude=15,
30 signal_shape="sine",
31 noise_amplitude=10,
32 )
33
34 # Bandpass from 1 to 30 Hz
35 bandpass = gp.Bandpass(f_lo=1, f_hi=30)
36
37 # Bandstop (notch) filter for 50 and 60 Hz
38 notch50 = gp.Bandstop(f_lo=48, f_hi=52)
39 notch60 = gp.Bandstop(f_lo=58, f_hi=62)
40
41 # Presenter trigger receiver
42 trig_receiver = gp.UDPReceiver()
43
44 # Trigger data
45 trig_node = gp.Trigger(time_pre=0.2, time_post=0.7, target=1)
46
47 # Keyboard capture
48 key_capture = gp.Keyboard()
49
50 # Time series scope
51 mk = gp.TimeSeriesScope.Markers
52 markers = [
53 mk(color="#ff0000", label="Stim", channel=channel_count, value=1),
54 mk(
55 color="#0000ff", label="M Key", channel=channel_count + 1, value=77
56 ),
57 ]
58 scope = gp.TimeSeriesScope(
59 amplitude_limit=50, time_window=10, markers=markers
60 )
61
62 # Trigger scope
63 trig_scope = gp.TriggerScope(amplitude_limit=5)
64
65 # Merge signals for scope and data saving
66 router_scope = gp.Router(
67 input_channels=[gp.Router.ALL, gp.Router.ALL, gp.Router.ALL]
68 )
69 router_raw = gp.Router(
70 input_channels=[gp.Router.ALL, gp.Router.ALL, gp.Router.ALL]
71 )
72
73 # File writer
74 filename = Path(paradigm).stem
75 writer = gp.CsvWriter(file_name=f"{filename}.csv")
76
77 # connect amplifier to filter nodes
78 p.connect(amp, bandpass)
79 p.connect(bandpass, notch50)
80 p.connect(notch50, notch60)
81
82 # merge scope data
83 p.connect(notch60, router_scope["in1"])
84 p.connect(trig_receiver, router_scope["in2"])
85 p.connect(key_capture, router_scope["in3"])
86
87 # merge raw data
88 p.connect(amp, router_raw["in1"])
89 p.connect(trig_receiver, router_raw["in2"])
90 p.connect(key_capture, router_raw["in3"])
91
92 # connect inputs of time series scope and file writer
93 p.connect(router_scope, scope)
94 p.connect(router_raw, writer)
95
96 # connect trigger node and scope
97 p.connect(notch60, trig_node[gp.Constants.Defaults.PORT_IN])
98 p.connect(trig_receiver, trig_node[gp.Trigger.PORT_TRIGGER])
99 p.connect(trig_node, trig_scope)
100
101 # Create main app and add widgets
102 presenter = gp.ParadigmPresenter(paradigm)
103 app.add_widget(presenter)
104 app.add_widget(scope)
105 app.add_widget(trig_scope)
106
107 # start pipeline and main app
108 p.start()
109 app.run()
110 p.stop()