Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ build/
.pytest_cache/
.DS_Store
temp.txt
*.pyc
*.pyc
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,9 @@
[prefix (default: /rtbio)]
--filename [filename]
[filename (default: temp.txt)]


To run from Python:
- You can use the `art-bio.yaml` file to intitialize the Anaconda environment with the necessary packages
- Run from terminal with for example the command `python art-bio.py -d biosignalsplux -c recg ws` to try the banana demo
- The biosignalsplux library files for Win64/Python 3.8 are included by default, for other platforms copy the files from the corresponding folder at [https://github.com/biosignalsplux/python-samples/tree/master/PLUX-API-Python3](https://github.com/biosignalsplux/python-samples/tree/master/PLUX-API-Python3) to the `devices/pluxlib` folder.
10 changes: 9 additions & 1 deletion argparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,21 @@ def getSamplingFrequency(args):

def getFilename(args):
if '--filename' in args:
index = next(i for i, arg in enumerate(args) if arg == '--filename' or arg == '-f')
index = next(i for i, arg in enumerate(args) if arg == '--filename')
try:
return args[index+1]
except IndexError:
raise ValueError('filename is empty')
return None

def getPort(args):
if '--port' in args:
index = next(i for i, arg in enumerate(args) if arg == '--port')
try:
return args[index+1]
except IndexError:
raise ValueError('port is empty')
return None


source_types = ['ecg', 'eda', 'eeg', 'emg']
Expand Down
43 changes: 41 additions & 2 deletions art-bio.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# coding=UTF-8
readme = '''
🐍 rt-bio : A Real-Time BIOsignal feature extraction tool 🦆
https://github.com/vatte/rt-bio
Expand Down Expand Up @@ -42,6 +43,7 @@

import argparser as parser
from devices import *
from devices.Biosignalsplux import Biosignalsplux
from init_sources import init_sources
from router import Router

Expand All @@ -58,6 +60,7 @@
router.osc_address = '127.0.0.1:4810'
router.osc_prefix = '/rtbio'
router.filename = 'temp.txt'
router.ws_port = 5678

args = sys.argv

Expand All @@ -82,6 +85,10 @@
device_list = OpenBCI.list_devices(None)
for i, dev in enumerate(device_list):
print('[{}] {}'.format(i, dev))
elif(device_name == 'biosignalsplux'):
device_list = Biosignalsplux.list_devices(None)
for i, dev in enumerate(device_list):
print('[{}] {}'.format(i, dev))
else:
raise ValueError('No such device: ' + device_name)
print('exiting...')
Expand All @@ -102,6 +109,11 @@
if filename_arg:
router.filename = filename_arg

#get ws port from args
port_arg = parser.getPort(args)
if port_arg:
router.ws_port = port_arg


#get sampling_frequency from args
sampling_frequency_arg = parser.getSamplingFrequency(args)
Expand Down Expand Up @@ -134,6 +146,14 @@
def noDigital():
raise ValueError('openbci has no digital output defined')
router.digital_out_func = noDigital
elif device_name == 'biosignalsplux':
device = Biosignalsplux(device_index)
if 'biosignalsplux' in config:
channels = {}
for k in config['biosignalsplux']:
channels[k] = [ int(c) for c in config['biosignalsplux'][k].split(',') ]
device.channel_map = channels

else:
raise ValueError('No such device: ' + device_name)

Expand All @@ -145,15 +165,34 @@ def noDigital():
#start streaming
device.start(sampling_frequency, sources.keys())

## filter experiment here for powerline
# from scipy import signal

# b,a = signal.iirnotch(50, 25, 100)

# print("B: " + str(b) + "A: " + str(a))

# z = [0, 0, 0, 0, 0, 0, 0, 0]
# for i, zz in enumerate(z):
# z[i] = signal.lfilter_zi(b, a)

try:
while True:
# Read samples
samples = device.read()
#print(samples)
for source in samples.keys():
features = []
for i, channel in enumerate(samples[source]):
features.append(sources[source][i].add_data(channel))
#for j, s in enumerate(channel):
#y, z[i] = signal.lfilter(b,a,[s], zi = z[i])
#channel[j] = y[0]
if source != 'unknown' and source in sources:
features.append(sources[source][i].add_data(channel))
router.route_data(source, connections, features, samples[source])

except KeyboardInterrupt:
except (Exception, KeyboardInterrupt) as e:
device.close()
if router.ws_server:
router.ws_server.stop()
raise(e)
31 changes: 31 additions & 0 deletions art-bio.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: art-bio
channels:
- defaults
dependencies:
- blas=1.0=mkl
- ca-certificates=2021.10.26=haa95532_2
- certifi=2021.10.8=py38haa95532_0
- icc_rt=2019.0.0=h0cc432a_1
- intel-openmp=2021.4.0=haa95532_3556
- mkl=2021.4.0=haa95532_640
- mkl-service=2.4.0=py38h2bbff1b_0
- mkl_fft=1.3.1=py38h277e83a_0
- mkl_random=1.2.2=py38hf11a4ad_0
- numpy=1.21.2=py38hfca59bb_0
- numpy-base=1.21.2=py38h0829f74_0
- openssl=1.1.1l=h2bbff1b_0
- pip=21.0.1=py38haa95532_0
- pyserial=3.5=py38haa95532_0
- python=3.8.12=h6244533_0
- scipy=1.7.1=py38hbe87c03_2
- six=1.16.0=pyhd3eb1b0_0
- sqlite=3.36.0=h2bbff1b_0
- vc=14.2=h21ff451_1
- vs2015_runtime=14.27.29016=h5e58377_2
- wheel=0.37.0=pyhd3eb1b0_1
- wincertstore=0.2=py38haa95532_2
- pip:
- bitalino==1.2.1
- python-osc==1.8.0
- setuptools==57.5.0
- websockets==10.1
5 changes: 5 additions & 0 deletions biosignals.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@ECHO on
call C:\Users\MTG-user\anaconda3\Scripts\activate.bat activate art-bio
cd C:\Users\MTG-user\Desktop\art-bio-biosignalsplux
python art-bio.py -d biosignalsplux -c reeg ws -c recg ws -c reda ws -c reeg file -c recg file -c reda file --filename readings.txt
PAUSE
9 changes: 7 additions & 2 deletions config.ini
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
#bitalino channel configuration for custom setups
#analog inputs are starting with index 0
[bitalino]
emg: 0
emg: 0,4
ecg: 1
eda: 2
eeg: 3
eeg: 3

[biosignalsplux]
eeg: 0,1
ecg: 2
eda: 3
133 changes: 133 additions & 0 deletions devices/Biosignalsplux.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# biosignalsplux

import glob
import sys
import platform
import time

from threading import Thread

sys.path.append('devices/pluxlib') #add the plux library for your platform to this folder
import plux

from .Device import Device

class Biosignalsplux(Device):

def __init__(self, dev_i = 0):

#default channel numbers for biosignalsplux
self.channel_map = {
'emg': [0],
'ecg': [1],
'eda': [2],
'eeg': [3]
}

# find device
print('Looking for biosignalsplux device')
retries = 0
self.device_list = []

while retries < 3 and len(self.device_list) == 0:
self.device_list = self.list_devices()

if len(self.device_list) == 0:
raise Exception('No biosignalsplux device found')

try:
device_address = self.device_list[dev_i]
except IndexError:
raise Exception('No biosignalsplux found with index ' + str(dev_i))

print("Connecting to " + device_address)

class PluxDevice(plux.SignalsDev):
def __init__(self, address):
plux.MemoryDev.__init__(address)
self.started = True
self.in_samples = []

def onRawFrame(self, nSeq, data): # onRawFrame takes three arguments
self.in_samples.append(data)
if not self.started:
return True
return False

# Connect to biosignalsplux
self.device = PluxDevice(device_address)

#find all devices
def list_devices(self):
devices = []
for mac in plux.BaseDev.findDevices():
devices.append(mac[0])
return devices

#start streaming
def start(self, fs, channels):
self.fs = fs
self.channels = []
chans = []
#order channels for biosignalsplux
for c in self.channel_map.keys():
if c in channels:
for index in self.channel_map[c]:
chans.append(index)
chans.sort()
self.n_chans = chans[-1] + 1
for c in range(self.n_chans):
found = False
for k in self.channel_map:
if c in self.channel_map[k]:
self.channels.append(k)
found = True
break
if not found:
self.channels.append('unknown')
print(self.channels)

codes = [ 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF] #codes for biosignalsplux device for different n_chans

# Start Acquisition
self.started = True
self.device.started = True
self.device.start(fs, codes[self.n_chans-1], 16)

def myfunc():
self.device.loop()

t = Thread(target=myfunc)
t.start()



#read samples (blocking)
def read(self):
samples = {}

while len(self.device.in_samples) == 0:
time.sleep(0.01)

for i, c in enumerate(self.channels):
if not c in samples:
samples[c] = []
samples[c].append([s[i] for s in self.device.in_samples])
#if 'eeg' in samples:
# samples['eeg'] = [ [ [samples['eeg'][i][j] for i in range(len(samples['eeg'])) ] for j in range(len(samples['eeg'][0]))] ]
#print(samples)
self.device.in_samples = [] # clear the sample buffer
return samples

#stop streaming
def stop(self):
# Stop acquisition
self.started = False
self.device.started = False

#close connection
def close(self):
if self.started:
self.started = False
self.device.started = False

Binary file added devices/pluxlib/LibFT4222-64.dll
Binary file not shown.
Binary file added devices/pluxlib/LibFT4222AB-64.dll
Binary file not shown.
Binary file added devices/pluxlib/msvcp100.dll
Binary file not shown.
Binary file added devices/pluxlib/msvcr100.dll
Binary file not shown.
Binary file added devices/pluxlib/plux.pyd
Binary file not shown.
Binary file added examples/banana_demo/banana.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/banana_demo/banana.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/banana_demo/heart.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/banana_demo/lungs1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/banana_demo/superbanana.wav
Binary file not shown.
Binary file added examples/banana_demo/superbanana2.wav
Binary file not shown.
Loading