Detection and visualization of brainwaves using Python, D3 and Bootstrap

Mohit Jain
8 min readSep 26, 2020

Brainwaves are electrical signals produced when neurons within the brain communicate with each other, which leads to emotions, consciousness, and behavior. These brainwaves can be detected using a technique called Electroencephalography (EEG). During EEG, electrodes are placed on certain locations of scalp to detect these electrical impulses. Just from a magnitude perspective the electrical potential (voltage) generated by these electrical impulses have amplitude of only around 100 microvolts, which leads to very weak signals.

The brainwaves are typically divided into certain bands, based on the frequency range, to determine various states of the brain. Below is the brief description of the various bands:

Delta Waves (0.5–3 Hz): These waves have the lowest frequency and typically associated with dreamless sleep or a deep state of meditation.

Theta Waves (3–8 Hz): These waves are typically present during light sleep, which also includes rapid eye movement (REM) state. They are also present during deep meditation or spiritual awareness and can reflect subconscious state of mind.

Alpha Waves (8–12 Hz): Alpha waves are associated with the resting state of mind and typically observed during when thinking quietly or in some stages of meditation.

Beta Waves (12–38 Hz): These waves are related to ‘fast’ activity of brain and associate with an alert brain or when we have our eyes open. Since these waves have a large range, they are further divided into three categories: Low-Beta (12- 15 Hz) — musing, Mid-Beta (15 -1 8Hz) — high engagement, and High-Beta (18 -30 Hz) — high anxiety or excitement.

Gamma (38–42 Hz): These are the highest frequency waves and associated with burst of insight and high -level information processing.

While a professional EEG detector can cost hundreds to thousands of dollars, I decided to use a relatively cheap (< $50) TGAM brainwave sensor manufactured by NeuroSky. While the expensive sensors have multiple electrodes, TGAM has only one electrode, which is placed on the forehead. Hence the sensitivity of this sensor is not that great, but it is good enough to get some experience in EEG analysis. Another advantage is that it works with dry electrode, so no gel is needed.

Figure 1 shows the picture of the sensor I used. It has four major components: (1) TGAM module; (2) Bluetooth module; (3) Stainless steel electrode; and (4) Battery pack (2 AAA batteries). You can buy the modules separately and solder the connections and electrode. However, soldering stainless steel is not an easy task, hence I opted for a pre-assembled unit. This unit can easily be purchased from eBay.

Figure 1: Photograph of the brainwave sensor, based on TGAM module. (Image by author)

The operating system I used to write the python code and connecting to the sensor was Ubuntu 18.04. While there are various python libraries that can be used to automatically search for Bluetooth device and connect to it, I found that it is much more reliable and easier to just manually connect the Bluetooth of the brainwave sensor to the serial port of the computer using serial python library. Instead of using default Bluetooth utility provided by Ubuntu, I opted to use blue man package. Instructions on how to install this package can be found here . I used ZEXMTE Bluetooth USB adapter.

The data was visualized on web browser using D3, which is a data visualization library written in JavaScript. You can learn more about D3 here. A good link to learn D3 quickly can be found here . To create the web page, I used Bootstrap , which is a front-end open source toolkit.

Connecting TGAM module to the computer

Figure 2 shows the screenshots to connect TGAM, using Bluetooth, to the serial port of the computer. Once connected we get the port information, in this case ‘/dev/rfcomm7’. We will use this port information to receive data for further processing using the python code.

Figure 2: Screenshots of connecting TGAM module using Bluetooth (Image by author)

TGAM Module Communication Information

A detailed description of the data communication protocol used for TGAM module can be found here and TGAM data sheet can be found here .

Figure 3 shows codes for the data transmitted by TGAM module. Two of the most important codes, which we will utilize are 0x02 and 0x80. The code 0x02 will let us know the signal quality. It is a single-byte code and has value between 0 -255, and updated every second. Any value above 5 will be treated as noisy signals coming from the sensor. The value 200 for this code also tells us if the electrode is touching the skin. The multi-byte code 0x80 gives us the raw value of the signals. It is 16-bit code and has value between -32768 and 32767 and updated every 2 ms(512 samples/second). We will also record code 0x04 (Attention), 0x05 (Meditation), and 0x83 (Brainwave Bands) but will not use them for visualization.

Figure 3: Code definitions for TGAM module (reproduced from TGAM datasheet)

Figure 4 shows the sample data, reproduced from TGAM module datasheet:

Figure 4: Example sample data (reproduced from TGAM datasheet)

Figure 5 shows a snippet of raw data received from the sensor.

Figure 5: Snippet of data from TGAM

Processing and Visualizing Data from TGAM Module

Figure 6 shows the simple function to read the data, using serial port. One thing to keep in mind is to make sure that the baud rate is 57600, as we get raw value data only at these high baud rates.

Figure 6: Function to read data from the sensor

Once the data is read, we take advantage of python’s generator function to read each byte at a time and perform processing based on the type of data received. For example, if the data is for raw values (code: 0x80) we read two bytes, and when the data is for poor signals (code: 0x02) we read single byte. Figure 7 shows a code snippet where we read raw values data. We need to perform bit shifting to read both bytes to get the whole value. Once we have read 512 values (~1 second worth of data), we save them in a temporary JSON file.

Figure 7: Code snippet to read raw wave values.

The first thing we do after saving the data is to normalize the data so that all the values are between -1 and 1, using the equation below:

Normalized_Value = 2*(Absolute_Value — Minimum_Value)/ (Maximum_Value — Minimum_Value) -1

Figure 8 shows the normalized brainwave data chart generated using D3.

Figure 8: Normalized brainwave data (Image by author)

Determining Brainwave Bands

Subsequently, I used normalized brainwave data, collected for 1 second, and applied Welch’s method to determine spectral density of the wave. This allowed us to calculate power of a signal at different frequencies. It was further used to determine the signal strength for each brain wave type. We used Signal library of the SciPy library. Figure 9 shows the code snippet to perform this analysis. We get frequencies and associated power density signals using the code shown in Figure 9. Figure 10 show shows the visual created using this data.

Figure 9: Code snippet to perform to use Welch’s method for power density estimation
Figure 10: Welch’s Periodogram of the brainwaves (Image by author)

The data derived from Welch’s periodogram was further analyzed to determine the specific brainwave bands. This was achieved by determining the area-under-the-curve within the frequency range allocated to the band. Subsequently the total area-under-the-curve was also calculated and the area for the bands was normalized. We applied Simpson’s rule using scipy.integrate.sims library to calculate the area-under-the-curve. Details about Simpson’s rule to calculate area can be found here. Figure 12 shows the strength of each type of brainwave.

Figure 11: Code snippet showing range of various bands used for calculation
Figure 12: Various brainwave bands calculated from the raw brainwave data (Image by author)

If you are interested in additional details on determining bands, you can read here.

We can also drive a spectrogram from the raw wave data. This allows us to visualize the strength of brainwave signals at various frequencies over a period of time. You can learn more about spectrogram here . Figure 13 shows the spectrogram, which demonstrate a heat map of frequency vs. time. We used build-in function of matplotlib python library for this. You can also use python Librosa library to generate the spectrogram.

Figure 13: Brainwave spectrogram (Image by author)
Figure 14: Code snippet to generate spectrogram

The final part is to generate an imaginary scenario, where we can hear the brainwaves. This entails transforming the brainwave into acoustic waves. This was achieved using amplitude modulation (AM). Details on how to perform amplitude modulation can be found here . In essence we need to select a carrier wave and information signal. In our case the information signal is the normalized brainwave data. We selected a carrier frequency of 500 Hz, but you can select based on your preference. Higher the frequency you select, higher the pitch in the sound you will hear. We selected the sample rate of 22,050. This should not be confused with the sample rate used in the TGMA chip, which is only 512 Hz. Below is the code snippet. The carrier signal modulation and amplitude can be adjusted, as desired. Basically, we generate extra data points from the raw brainwave signal using NumPy interpolation library, and use that to create the sound wave. Finally, the data was saved as a MP3 file using scipy.io.wavfile write module. Figure 15 shows the visualization of the sound wave, generated using the raw brainwave and the carrier wave.

Figure 15: Brainwave visualized as sound wave (Image by author)
Figure 16: Code to transform brainwave to sound wave

Figure 17 shows the widget to play the corresponding MP3 file on the webpage, created using HTML5 audio element.

Figure 17: Widget to hear simulated sound of the brainwave (Image by author)

The code for both data processing in python and data visualization using D3 and Bootstrap can be found here .

Disclaimer: Do not use the work described in this article and the associated code for medical research. This is just to get some familiarity with brainwaves.

--

--