ohbm / hackathon2019

Website and projects for the OHBM Hackathon in Rome 2019
https://ohbm.github.io/hackathon2019
82 stars 61 forks source link

Neurofeedback in Python #77

Open jnvandermeer opened 5 years ago

jnvandermeer commented 5 years ago

Neurofeedback in Python - the need for speed

Background

In EEG neurofeedback timing is perhaps not always so cricial that feedback needs to happen within < 1 miliseconds (for that you'd need real-time Operating systems), but it's still impotant enough that the "Neurofeedback Loop" need to happen relatively fast - and consistent, and in pace with the data acquisition. Lag is unavoidable and acceptable, within limits. Lag can be introduced because you need to do some mathematical operation (filtering especially), or because of Input/Output 'clogging'. Acceptable lag in EEG NF is in the order of 150-200 miliseconds, but the faster the better.

Programming in C will more likely give you that kind of speed, but making (and compiling) things in Python makes it a bit harder to communicate with the Python community, and Python should (in principle) be fast enough also for Neurofeedback purposes. There are currently (as far as I know) two main repositories of Python-based Neurofeedback software: Pyff/Wyrm, made by Bastian Venthur in 2010 (and since more-or-less abandoned). And nfb (see REF PAPER).

Issues

The issue is Lag. In python, one type of lag is due to the Global Interpreter Lock. Basically it means that python interpreter can read & interpret only one python line at a time, so all other lines have to wait their turn. So that means if you have something else that needs to be done in the neurofeedback loop - writing a file, updating your screen, keeping track of parameters, or doing an analysis while the NF loop is running, the Neurofeeback loop has to stop - or you delegate work to another python interpreter.

Delegation is by python's multiprocessing module. There are other ways to do parallel evaluations with threading and asynchronous programming, but the also need to obey the GIL. Basically you start another Python session (and interpreter) - that can run on a separate core and do stuff while the main process hanles the neurofeedback loop, thereby reducing the Lag. The two processes communicate via files (bad), pipes/queues (preferred), or shared memory (probably the fastest, but care is needed).

However... starting a Process takes time. And also, putting stuff into a queue and picking stuff out of a queue ALSO takes time. The bigger the data exchanged the longer it takes. The project I propose is to do some benchmarking/stress testing and measure how long it takes to start up a process, and how much data can you move around at what speeds, in the contesxt of some Neurofeedback and real-time processing that i've been working on. Ideally, the speed should be infinite and the lag 0 of such operations. A lag of more than 30-50 miliseconds can already tamper with the consistency of the Neurofeedback loop.

Aims

Knowledge

Multiprocessing, Queues, GIL

Github Repository

https://github.com/jnvandermeer/nf-rtime-preview