Episode 3: Auditory Evoked Potentials
In this episode, you learn how to record Auditory Evoked Potentials (AEPs) using g.Pype.
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_selector=[gp.Router.ALL, gp.Router.ALL, gp.Router.ALL]
68 )
69 router_raw = gp.Router(
70 input_selector=[gp.Router.ALL, gp.Router.ALL, gp.Router.ALL]
71 )
72
73 # File writer
74 filename = Path(paradigm).stem
75 writer = gp.FileWriter(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()