So you want to read minds?

You can't (yet), but we'll talk about what you can do...

Today

  1. Introduction to EEG
  2. Walk through EEG terms and technology using OpenVibe
  3. Given enough pointers for people trying their own experiments

Hi!

Patrick Coleman

Intro: What are brains?

Very abstractly...a giant connected information network.
  • Nodes = Neurons, ~100 billion (?)
  • Edges = Synapses, ~100 trillion (?)
  • Signal = electrical current


plus lots of other things (glial cells, neurotransmitters, blood, ...)

What is EEG?

Sensors to read electrical signal.
  • Non-invasive!
  • Good temporal resolution: Fast
  • Bad spatial resolution: measure voltage on scalp
  • Lots of research into what can be identified.
  • Sensitive: voltage is around µV, susceptible to movement, ...

Example!

  • X axis = Time
  • Y axis = Voltage, one row per sensor
How to measure? How to process? ...

Measure example: OpenBCI

Hardware and software for running your own EEG system.

Process example: OpenVibe

Software specializing in real-time processing of brain signals.
Good for prototyping (and explaining) things!

Installing OpenVibe...

  • Visit the OpenVibe website downloads page
  • At time of writing, v1.3.0 supports windows and linux

...Run the Designer

~/openvibe$ ./dist/openvibe-designer.sh

...What is going on‽‽

Noise generator: Generate fake EEG time series.
Signal display: Display the time series.
Now play with some settings!

Option: use existing data

Some public EEG data sets exist - UCSD has a good collection. We'll use the 2015 Music BCI data set available from BCNI Horizon (set #15), with paper describing the data from TU Berlin.

Warning: 554Mb! EEG data is big...

Load and Visualize


Lots of data formats, chances are you'll need some processing...



A bunch are supported (see the list),
for now we'll use the CSV Reader and some python.

Rewrite signal values into CSV format

  import scipy.io as sio
  import csv

  SUBJECT = 'aak'
  IN_FILE = 'data/musicbci_VP%s.mat' % SUBJECT
  OUT_FILE = 'dataCSV/%s_signal.csv' % SUBJECT

  print "Loading matlab file %s..." % IN_FILE
  data = sio.loadmat(IN_FILE)
  readings = data['data'][0]['X'][0]

  # First line: Row count, then channel names, then sample rate
  channelNames = [str(c[0]) for c in data['data'][0]['clab'][0][0]]
  sampleRate = data['data'][0]['fs'][0][0][0]

  print "# Readings: %d" % readings.shape[0]
  print "# Channels: %d" % len(channelNames)
  print "Sample rate: %d hz" % sampleRate

  # sampleRate samples/sec = 1000 / sampleRate ms/sample
  secPerSample = 1.0 / sampleRate

  print "Writing to %s..." % OUT_FILE
  with open(OUT_FILE, 'wb') as csvfile:
      writer = csv.writer(csvfile)
      writer.writerow(['Time (s)'] + channelNames + ['Sampling Rate'])
      # First row has extra rate:
      writer.writerow([0.0] + readings[0].tolist() + [sampleRate])
      for r in range(1, readings.shape[0]):
          writer.writerow([r * secPerSample] + readings[r].tolist())

  print "Done!"
Also available on github

Run conversion...

~/openvibe/musicbci$ time python signalToCSV.py
Loading matlab file data/musicbci_VPaak.mat...
# Readings: 2277240
# Channels: 64
Sample rate: 200 hz
Writing to dataCSV/aak_signal.csv...
Done!

real	2m30.080s
user	2m25.902s
sys	0m3.841s

View in Designer

Enable unstable boxes to use CSVFileReader.

Concept: Frequency Analysis

Different frequencies in the signal are correlated to different things:
TypeFrequencyAssociation (ish...)
Delta0.1 - 3HzSleep, Healing
Theta4 - 7HzMeditation, Memory
Alpha8 - 15HzRelaxation, Creativity
Beta16 - 30HzAlertness, Cognition
Gamma31 - 100HzFocus, Consciousness

Power bands in designer

To set it up...
  1. Read signal from CSV, as before.
  2. Use Channel selector box to pick some channels.
  3. Convert to frequencies with Spectral Analysis (FFT)
  4. Draw to screen with Power spectrum display

Result

NB: Historgram looks bad :( One place where OpenVibe isn't great.
The display from OpenBCI is much nicer...

Example: Alpha Waves

  • Add Temporal filter to restrict to 8-15Hz
  • Display the result with the usual signal display
  • Also add a Spectrum average and display with Matrix display

Concept: Events

Some applications for EEG look at signal after an event happens.
OpenVibe calls these 'stimulations'. BUT: You need timings for events

Rewrite CSV format


  import scipy.io as sio
  import csv

  SUBJECT = 'aak'
  IN_FILE = 'data/musicbci_VP%s.mat' % SUBJECT
  OUT_FILE = 'dataCSV/%s_events.csv' % SUBJECT

  print "Loading matlab file %s..." % IN_FILE
  data = sio.loadmat(IN_FILE)

  trials = data['data'][0]['trial'][0]
  values = data['data'][0]['y'][0]
  assert trials.shape == values.shape

  eventCount = trials.shape[1]
  sampleRate = int(round(data['data'][0]['fs'][0][0][0]))
  print "# Events: %d" % eventCount

  print "Writing to %s..." % OUT_FILE
  with open(OUT_FILE, 'wb') as csvfile:
  writer = csv.writer(csvfile)
  writer.writerow(['Time (s)', 'Identifier', 'Duration'])
  # First row has extra rate:
  for i in range(eventCount):
  msOffset = int(round(trials[0, i])) * 1000 / sampleRate
  # eID = values[0, i]
  eID = 33024 + values[0, i] # HACK: http://openvibe.inria.fr/stimulation-codes/
  writer.writerow([msOffset / 1000.0, eID, 1])

  print "Done!"
Also available on github

In Designer

CSV File Reader
  • Right-Click 🡺 Modify Outputs 🡺 Output Stream 🡺 Stimulations
  • Purple arrow = correct (see here)

Concept: Event Related Potentials (ERPs)

Lots of research into what is expected after certain stimuli!
e.g. P300 is fairly stable, and can be decoded with Muse.
  • P = Positive voltage (= down...)
  • 300 = 300 milliseconds after stimulus
N.B: This is an average 'epoch' = segment of signal.
A bit more involved...
  • Two CSV readers, load signal and events
  • Filter for some channels (for simplicity)
  • Stimulation-based epoching
  • Draw with signal display, plus ERP plot

Extra

  • Epoch Variance box allows the calculation of the mean and variance across multiple epochs.
  • ERP plot can also save the result to file on a particular signal.

Concept: ICA

Independant Component Analysis is where multiple signals can be separated out into independant parts. Useful for:
  • Noise reduction: find the 'blink' component, and remove it
  • Virtual channels: e.g. reduce to 'frontal' signal, 'left hemisphere', ...

Localization

There is a standard '10-20' placement system:
For this example, we'll look at F7/F9, and P8/P10.

In Designer

  • Apply channel selection for P8;P10;F7;F9
  • Run through Independant Component Analysis box
IC1 ~ front left, IC2 ~ back right.

Concept: Localization

Given positions of sensors on the scalp, can we convert them back to find signal strength at locations internally?
LOTS of techniques (Dipole modelling, Beam forming, Bayesian MAP, sLORETA), ...no clear winner.

In Designer, 2D

  • Load data from CSV, as before, and exclude "EOGvu" (reference).
  • Load locations from .txt, using localization file reader.
  • Display with 2D Topographic Map.

Bonus! '3D'

N.B: You should create your own locations, but see openvibe/dist/share/openvibe/electrode_sets for an example.

Live streaming!

We can process from old files, can we process from new live data?
OpenVibe supports live data too, using the Acquisition server.

Acquisition Server

Used to input data live from device, but can also read from file or make random signal.
~/openvibe$ ./dist/openvibe-acquisition-server.sh

Muse (via LSL)

To get Muse working with OpenVibe, the simplest way is to get them both talking the LSL format (= Lab Streaming Layer).

1) Muse -> LSL

$~/muse$ muse-io --device DEVICE_ID --lsl-eeg muse 
Enter your Muse bluetooth ID for DEVICE_ID, for example mine is 00:06:66:68:9F:96
N.B: With newer Muse, you'll want the muse-lsl library.

2) LSL -> Aquisition Server

  1. Select signal stream to the name above, and marker to None.
  2. Connect to your device, make sure it's successful
  3. Play to start the streaming

View in designer

  • Acquisition client box to read from the server
  • Connect to the stream visualizer (or whatever you like)

OpenBCI

OpenBCI makes this even easier,
with the Acquisition server supporting it by default.

1) OpenBCI to 'PC' mode and plug in USB

2) Aquisition server:

Saving...

🢂

N.B.: Need to set the types to Signal

More on OpenVibe...


Some extra stuff that wasn't covered, but for those interested...

  • Connectivity box for synchronicity between various parts of the brain.
  • Automatic Classification trainer and processor: use machine learning techniques (SVM, LDA) to learn how to identify various events, if possible

Thanks!

padsterpat@gmail.com
https://github.com/padster

More on NeuroTechX...

International non-profit building a community of neuro technology enthusiasts.