Tutorial EEG Workflow (APEX)#

This tutorial provides a step-by-step guide on running the example_EEG_workflow.py located inside the examples_APEX folder.

Adding the correct directory of files#

To recognize the TMSi Python interface folder, which is necessary for running the examples, your Python interpreter needs to know the corresponding path. Therefore, the first lines of code add this information. If you wish to store the recordings in a different folder than the default one, you can change the directory given in line 43.

38import sys
39import time
40from os.path import join, dirname, realpath
41Example_dir = dirname(realpath(__file__)) # directory of this file
42modules_dir = join(Example_dir, '..') # directory with all modules
43measurements_dir = join(Example_dir, '../measurements') # directory with all measurements
44configs_dir = join(Example_dir, '../TMSiSDK\\tmsi_resources') # directory with configurations
45sys.path.append(modules_dir)

Importing the required classes and functions from TMSi SDK#

These are the libraries which are implemented by TMSi and are required for the example script to work. They are used for purposes such as handling errors, writing recording files on PC, and plotting incoming data.

47from TMSiSDK.tmsi_sdk import TMSiSDK, DeviceType, DeviceInterfaceType, DeviceState
48from TMSiSDK.tmsi_errors.error import TMSiError
49from TMSiFileFormats.file_writer import FileWriter, FileFormat
50
51from TMSiGui.gui import Gui
52from TMSiPlotterHelpers.impedance_plotter_helper import ImpedancePlotterHelper
53from TMSiPlotterHelpers.signal_plotter_helper import SignalPlotterHelper

Finding connected devices#

It’s possible to have more than one device connected. The Python interface can be used to discover each device. Therefore, it’s necessary to specify the type of connected device as well as the interface via which the device is connected to PC (line 58). For APEX it can be either usb or bluetooth. Next, a list of connected devices (device type has already been specified) can be stored inside variable discoveryList. The next line of code (line 61) is a check to ensure that at least one device has been discovered. When one or multiple devices are found, the first device is opened. The handle to this discovered device is stored in the variable dev. The dev.open() command opens a connection to APEX.

57    # Execute a device discovery. This returns a list of device-objects for every discovered device.
58    TMSiSDK().discover(DeviceType.apex, DeviceInterfaceType.usb)
59    discoveryList = TMSiSDK().get_device_list(DeviceType.apex)
60
61    if (len(discoveryList) > 0):
62        # Get the handle to the first discovered device.
63        dev = discoveryList[0]
64        
65        # Open a connection to APEX
66        dev.open()

Loading desired device configuration#

As shown in the beginning, the pre-defined configuration files are located inside the configs folder of the TMSi Python interface (TMSiSDKtmsi_resources). It is also possible to create custom configurations and save these as .xml files. In this example, a 32-channel configuration with EEG labeling is loaded to the device (line 75). Please make sure to load the device configuration after opening a connection to the device.

68        if dev.get_num_channels()<32:
69            # Load the EEG channel set and configuration
70            print("load EEG config 24")
71            dev.import_configuration(join(configs_dir, 'APEX_config_EEG24.xml'))
72        else:
73            # Load the EEG channel set and configuration
74            print("load EEG config 32")
75            dev.import_configuration(join(configs_dir, 'APEX_config_EEG32.xml'))

Initializing impedance plotter#

In most EEG measurements, it is common to monitor impedances prior to signal acquisition. Therefore, once the device configuration is set, a real-time plotter is initialized. As shown, the required graphical user interface (GUI) and plotter helper were initially imported from TMSiGui and TMSiPlotterHelpers. The plotter helper defines which plotter is shown by the GUI (for more information about the plotters, please read the Plotters Tutorial). In this case, the ImpedancePlotterHelper is initialized in line 85. Three parameters can be specified for the impedance plotter. The first parameter is the device that is passed to the Helper. The second variable, the layout variable, defines if the electrode impedances should be visualized as a head (for EEG) or in a Grid form (for HD-EMG). Finally, the impedances can be stored in a file: the third parameter defines the location and name of the file.

77        # Check if there is already a plotter application in existence
78        app = QApplication.instance()
79        
80        # Initialise the plotter application if there is no other plotter application
81        if not app:
82            app = QApplication(sys.argv)
83        
84        # Initialise the helper
85        plotter_helper = ImpedancePlotterHelper(device=dev,
86                                                 is_head_layout=True, 
87                                                 file_storage = join(measurements_dir,"example_impedance_plot"))
88        # Define the GUI object and show it 
89        gui = Gui(plotter_helper = plotter_helper)
90         # Enter the event loop
91        app.exec_()

Initializing file writer#

The TMSi Python interface allows to record data in either .XDF or .Poly5 format. Therefore, the user is asked to provide a desired file format (line 98). Line 101 - 107 ensures that the specified file format is initialized. Here, it is also possible to specify the directory in which the recordings are stored. The default is set to the measurement_dir (defined earlier) located inside the TMSi Python interface folder. Please note, if neither .XDF nor .Poly5 is given as input, the data will be saved as .XDF (lines 105 - 107). Moreover, it is required for the file_writer to get a handle to the device specified in the discoveryList, which is done in line 110. The default file name is example_EEG_workflow. If the user wishes to change the file name, lines 101-107 can be edited.

 97        # Ask for desired file format
 98        file_format=input("Which file format do you want to use? (Options: xdf or poly5)\n")
 99        
100        # Initialise the desired file-writer class and state its file path
101        if file_format.lower()=='poly5':
102            file_writer = FileWriter(FileFormat.poly5, join(measurements_dir,"example_EEG_workflow.poly5"))
103        elif file_format.lower()=='xdf':
104            file_writer = FileWriter(FileFormat.xdf, join(measurements_dir,"example_EEG_workflow.xdf"), add_ch_locs=True)
105        else:
106            print('File format not supported. File is saved to XDF-format.')
107            file_writer = FileWriter(FileFormat.xdf, join(measurements_dir,"example_EEG_workflow.xdf"), add_ch_locs = True)
108        
109        # Define the handle to the device
110        file_writer.open(dev)

Initializing signal plotter#

This step is very similar to initializing the impedance plotter. As plotting the real-time signal (instead of impedances) is desired, the SignalPlotterHelper is needed. The SignalPlotterHelper only needs the device as input parameter. The GUI is initialized based on the correct Helper and the GUI’s event loop is started by line 117.

As soon as the GUI is closed by the user, it is crucial to stop the file_writer and then close the connection to the device.

For simplicity, the explanation of try…except statement was skipped in this tutorial.

112        # Initialise the new plotter helper
113        plotter_helper = SignalPlotterHelper(device=dev)
114        # Define the GUI object and show it 
115        gui = Gui(plotter_helper = plotter_helper)
116         # Enter the event loop
117        app.exec_()
118        
119        # Close the file writer after GUI termination
120        file_writer.close()
121        
122        # Close the connection to the device
123        dev.close()

Summary#

To wrap it up, assuming that the device driver is installed, recording data in Python using a TMSi amplifier is done by following the steps below. You can use the same flow to write your own script.

../_images/summary_eeg_emg_tutorials.png

Figure 1: Overview of the general worflow to record data with a TMSi amplifier in Python#