-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP: Realtime decoding #615
Closed
Closed
Changes from 80 commits
Commits
Show all changes
82 commits
Select commit
Hold shift + click to select a range
26a2424
Initial MNE real-time commit
chdinh 939214c
[cleanup]
chdinh 7a0a6a0
read real-time header info
chdinh 77ba0dd
set alias
chdinh 9992248
cleanup and some coding python guide lines
chdinh bda771b
read meas info
chdinh 5cb2481
almost - read raw buffer doesn't receive all data jet
chdinh 42f3713
working raw buffer reading
chdinh 300a0fb
code style
chdinh 9bab472
cleanup
chdinh c4b00ce
WIP: realtime
mluessi 975293e
BaseEpochs, various enh
mluessi 0e24371
rt rebase, fixes, example
mluessi d3dac3d
update setup
mluessi a7a9793
Small example for real-time decoding
jasmainak 415d3d0
Added missing coma in setup.py
jasmainak 817aa10
Simplified the example a lot. The real-time plot remains
jasmainak 86a63e9
Added real-time plotting to example real-time decoding script
jasmainak dab8274
Fixed issue of accessing private function by using list comprehension…
jasmainak 6b77d04
Removed redundant variable
jasmainak 81a16c1
Some thoughts to how the real-time decoding can be structured
jasmainak c837a09
Trying to convert the newly created example into class/method format.…
jasmainak 3b2e130
Fixed PEP8 for compute_rt_decoder.py and now plotting only last 5 poi…
jasmainak 359d21b
Misc. changes - added new name to __init__.py and comment for waitfor…
jasmainak f296bdd
Modified classifier.py so that it is general enough to take clf from …
jasmainak 989ce13
Added iter_evoked() method to class _BaseEpochs. This will allow Evok…
jasmainak 1f12421
Modified iterate_evoked() function to allow iterating over RtEpochs a…
jasmainak f907eed
Added a keyword argument return_event_id=False to next() in RtEpochs …
jasmainak 0b79bdd
Modified the code to return actual event-ids rather than the dictiona…
jasmainak 9117d41
Always return event_id in _pop_epoch()
jasmainak 582314b
Modified classifier.py to add the Scaler class which subtracts the me…
jasmainak 16b96f1
Fix small bug in Scaler class
jasmainak 15ed925
Added PSDEstimator class to classifier.py
jasmainak 5c39300
Added FilterEstimator (which won't work as of now). Will have to figu…
jasmainak 968813c
Added a class to concatenate time-series across channels
jasmainak d622b8a
Added file for testing pipeline and also added TODOs to the classifie…
jasmainak c42de91
Testing reshaping of 3d epochs into 2d epochs
jasmainak 7cca9fc
3d array to 2d array reshaping verified
jasmainak 959c0ec
Corrected concatenation of channels. transpose is not required. Also,…
jasmainak 444ab7b
Uses iter_evoked() method in epochs that was newly introduced and pip…
jasmainak c9f9ced
Remove confusing duplicate of decoding example
jasmainak ef92821
Modified real-time decoding example to show standard deviation across…
jasmainak 4f0035b
Removed redundant variables trnum and tsnum
jasmainak fed2fad
The only option for the FilterEstimator class seems to be to duplicat…
jasmainak bb687b4
Misc. fixes to FilterEstimator
jasmainak 4432a14
Added docstrings to FilterEstimator and also updated the example to i…
jasmainak ff71dcd
Updated docstrings
jasmainak 11c11bf
Small fixes
jasmainak 02b3097
Removed offline_testing folder
jasmainak 5b98f7e
Updated Scaler class to have division by std. deviation as well
jasmainak a2c9d36
Added more structure to PSDEstimator class and also fit_transform met…
jasmainak b20c6dd
Commit to save changes before attempting a rebase w.r.t. to master
jasmainak 54fda72
FIXES
34b3d09
FIXES 2
c209354
FIX 3
75ffaa8
FIX 4
6f89571
Implementation of MockRtClient together with modified examples
jasmainak 15ce5b1
Misc. fixes and change in API for sending buffers from mock rt_client
jasmainak 46808c7
Added TransformerMixin to MNE-Python
jasmainak 609c1bc
Use tmin instead of tmin_samp as argument to send_data() in RtMockClient
jasmainak 65bfd9b
Added unit test for mock client, but the test doesn't work yet
jasmainak ebd0e45
Modified the test to directly check if the epoch_queue is the same as…
jasmainak c67ab1c
Reverted to checking equality of epochs. Some issue with calibration …
jasmainak 30ac8f3
Addressing @agramfort 's comments and adding test_Scaler(). More test…
jasmainak 35b7729
Unit tests + fixes
jasmainak 6655885
PSDEstimator Unit test works, but mockclient still has problems
jasmainak 1d9e910
Calibration + Unit tests
jasmainak 22c86b1
Unit tests pass
jasmainak 248d79e
Added test for iter_evoked()
jasmainak 0269e98
MISC : cleanup in realtime
agramfort 97bbb69
MISC : rename examples so they get plotted in the examples gallery
agramfort 6331f2f
API : simplify RtEpochs (no consume_epochs, max n_epochs but just a t…
agramfort 57d8fd2
addressing mainak's remarks
agramfort abad851
Merge pull request #1 from agramfort/realtime
jasmainak a5792ff
Remove redundant n_epochs from moving average example
jasmainak e6aed0c
Created decoding module
jasmainak 23eb2f4
Updated authors list
jasmainak 4669780
Updated whats_new.rst
jasmainak 146f4f1
Modified realtime examples for sphinx docs
jasmainak 62a1fd0
Python Reference + Fix
jasmainak 49f40f3
Addressing @agramfort's comments
jasmainak a68c208
Forgotten tests folder
jasmainak File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
Real-time M/EEG Acquisition | ||
--------------------------- | ||
|
||
Receive data from an MNE Real-time server (mne_rt_server, part of MNE-CPP), | ||
compute real-time moving averages, etc. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
""" | ||
======================================================== | ||
Compute real-time evoked responses using moving averages | ||
======================================================== | ||
|
||
This example demonstrates how to connect to an MNE Real-time server | ||
using the RtClient and use it together with RtEpochs to compute | ||
evoked responses using moving averages. | ||
|
||
Note: The MNE Real-time server (mne_rt_server), which is part of mne-cpp, | ||
has to be running on the same computer. | ||
""" | ||
|
||
print __doc__ | ||
|
||
# Authors: Martin Luessi <mluessi@nmr.mgh.harvard.edu> | ||
# Mainak Jas <mainak@neuro.hut.fi> | ||
# | ||
# License: BSD (3-clause) | ||
|
||
import time | ||
|
||
import mne | ||
from mne.datasets import sample | ||
from mne.realtime import RtEpochs, MockRtClient | ||
|
||
# Fiff file to simulate the realtime client | ||
data_path = sample.data_path() | ||
raw_fname = data_path + '/MEG/sample/sample_audvis_filt-0-40_raw.fif' | ||
raw = mne.fiff.Raw(raw_fname, preload=True) | ||
|
||
# select gradiometers | ||
picks = mne.fiff.pick_types(raw.info, meg='grad', eeg=False, eog=True, | ||
stim=True, exclude=raw.info['bads']) | ||
|
||
# select the left-auditory condition | ||
event_id, tmin, tmax = 1, -0.2, 0.5 | ||
|
||
# create the mock-client object | ||
rt_client = MockRtClient(raw) | ||
|
||
# create the real-time epochs object | ||
rt_epochs = RtEpochs(rt_client, event_id, tmin, tmax, picks=picks, | ||
decim=1, reject=dict(grad=4000e-13, eog=150e-6)) | ||
|
||
# start the acquisition | ||
rt_epochs.start() | ||
|
||
# send raw buffers | ||
rt_client.send_data(rt_epochs, picks, tmin=0, tmax=150, buffer_size=1000) | ||
|
||
evoked = None | ||
|
||
for ii, ev in enumerate(rt_epochs.iter_evoked()): | ||
|
||
print "Just got epoch %d" % (ii + 1) | ||
|
||
if evoked is None: | ||
evoked = ev | ||
else: | ||
evoked += ev | ||
|
||
evoked.plot() | ||
time.sleep(0.1) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
""" | ||
======================= | ||
Decoding real-time data | ||
======================= | ||
|
||
Supervised machine learning applied to MEG data in sensor space. | ||
Here the classifier is updated every 5 trials and the decoding | ||
accuracy is plotted | ||
""" | ||
# Authors: Mainak Jas <mainak@neuro.hut.fi> | ||
# | ||
# License: BSD (3-clause) | ||
|
||
print __doc__ | ||
|
||
import time | ||
|
||
import mne | ||
from mne.realtime import MockRtClient, RtEpochs | ||
from mne.datasets import sample | ||
|
||
import numpy as np | ||
import pylab as pl | ||
|
||
# Fiff file to simulate the realtime client | ||
data_path = sample.data_path() | ||
raw_fname = data_path + '/MEG/sample/sample_audvis_filt-0-40_raw.fif' | ||
raw = mne.fiff.Raw(raw_fname, preload=True) | ||
|
||
tmin, tmax = -0.2, 0.5 | ||
event_id = dict(aud_l=1, vis_l=3) | ||
|
||
tr_percent = 60 # Training percentage | ||
min_trials = 10 # minimum trials after which decoding should start | ||
|
||
# select gradiometers | ||
picks = mne.fiff.pick_types(raw.info, meg='grad', eeg=False, eog=True, | ||
stim=True, exclude=raw.info['bads']) | ||
|
||
# create the mock-client object | ||
rt_client = MockRtClient(raw) | ||
|
||
# create the real-time epochs object | ||
rt_epochs = RtEpochs(rt_client, event_id, tmin, tmax, picks=picks, decim=1, | ||
reject=dict(grad=4000e-13, eog=150e-6)) | ||
|
||
# start the acquisition | ||
rt_epochs.start() | ||
|
||
# send raw buffers | ||
rt_client.send_data(rt_epochs, picks, tmin=0, tmax=90, buffer_size=1000) | ||
|
||
# Decoding in sensor space using a linear SVM | ||
n_times = len(rt_epochs.times) | ||
|
||
from sklearn import preprocessing | ||
from sklearn.svm import SVC | ||
from sklearn.pipeline import Pipeline | ||
from sklearn.cross_validation import cross_val_score, ShuffleSplit | ||
|
||
from mne.decoding.classifier import ConcatenateChannels, FilterEstimator | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. from mne.decoding import ConcatenateChannels, FilterEstimator should be enough |
||
|
||
scores_x, scores, std_scores = [], [], [] | ||
|
||
filt = FilterEstimator(rt_epochs.info, 1, 40) | ||
scaler = preprocessing.StandardScaler() | ||
concatenator = ConcatenateChannels() | ||
clf = SVC(C=1, kernel='linear') | ||
|
||
concat_classifier = Pipeline([('filter', filt), ('concat', concatenator), | ||
('scaler', scaler), ('svm', clf)]) | ||
|
||
for ev_num, ev in enumerate(rt_epochs.iter_evoked()): | ||
|
||
print "Just got epoch %d" % (ev_num + 1) | ||
|
||
if ev_num == 0: | ||
X = ev.data[None, ...] | ||
y = int(ev.comment) | ||
else: | ||
X = np.concatenate((X, ev.data[None, ...]), axis=0) | ||
y = np.append(y, int(ev.comment)) | ||
|
||
if ev_num >= min_trials: | ||
|
||
cv = ShuffleSplit(len(y), 5, test_size=0.2, random_state=42) | ||
scores_t = cross_val_score(concat_classifier, X, y, cv=cv, | ||
n_jobs=1) * 100 | ||
|
||
std_scores.append(scores_t.std()) | ||
scores.append(scores_t.mean()) | ||
scores_x.append(ev_num) | ||
|
||
# Plot accuracy | ||
pl.clf() | ||
|
||
pl.plot(scores_x[-5:], scores[-5:], '+', label="Classif. score") | ||
pl.hold(True) | ||
pl.plot(scores_x[-5:], scores[-5:]) | ||
pl.axhline(50, color='k', linestyle='--', label="Chance level") | ||
hyp_limits = (np.asarray(scores[-5:]) - np.asarray(std_scores[-5:]), | ||
np.asarray(scores[-5:]) + np.asarray(std_scores[-5:])) | ||
pl.fill_between(scores_x[-5:], hyp_limits[0], y2=hyp_limits[1], | ||
color='b', alpha=0.5) | ||
pl.xlabel('Trials') | ||
pl.ylabel('Classification score (% correct)') | ||
pl.ylim([30, 105]) | ||
pl.title('Real-time decoding') | ||
pl.show() | ||
|
||
time.sleep(0.1) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
from .classifier import Scaler, FilterEstimator | ||
from .classifier import PSDEstimator, ConcatenateChannels | ||
from .mixin import TransformerMixin | ||
from .csp import CSP |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mne.decoding import CSP
should be enough