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