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.pyView 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()