Merge pull request #1 from jdpigeon/master
Updated lsl-viewer and minor updates to lab7
Esse commit está contido em:
+23
-17
@@ -1,17 +1,15 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
## code by Alexandre Barachant
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
from scipy.signal import butter, filtfilt
|
from scipy.signal import butter, lfilter, lfilter_zi
|
||||||
from time import time, sleep
|
from time import sleep
|
||||||
from pylsl import StreamInlet, resolve_byprop
|
from pylsl import StreamInlet, resolve_byprop
|
||||||
|
from optparse import OptionParser
|
||||||
import seaborn as sns
|
import seaborn as sns
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
|
||||||
sns.set(style="whitegrid")
|
sns.set(style="whitegrid")
|
||||||
|
|
||||||
from optparse import OptionParser
|
|
||||||
|
|
||||||
parser = OptionParser()
|
parser = OptionParser()
|
||||||
|
|
||||||
parser.add_option("-w", "--window",
|
parser.add_option("-w", "--window",
|
||||||
@@ -55,6 +53,7 @@ class LSLViewer():
|
|||||||
self.dejitter = dejitter
|
self.dejitter = dejitter
|
||||||
self.inlet = StreamInlet(stream, max_chunklen=buf)
|
self.inlet = StreamInlet(stream, max_chunklen=buf)
|
||||||
self.filt = True
|
self.filt = True
|
||||||
|
|
||||||
info = self.inlet.info()
|
info = self.inlet.info()
|
||||||
description = info.desc()
|
description = info.desc()
|
||||||
|
|
||||||
@@ -105,6 +104,9 @@ class LSLViewer():
|
|||||||
|
|
||||||
self.bf, self.af = butter(4, np.array([1, 40])/(self.sfreq/2.),
|
self.bf, self.af = butter(4, np.array([1, 40])/(self.sfreq/2.),
|
||||||
'bandpass')
|
'bandpass')
|
||||||
|
zi = lfilter_zi(self.bf, self.af)
|
||||||
|
self.filt_state = np.tile(zi, (self.n_chan, 1)).transpose()
|
||||||
|
self.data_f = np.zeros((self.n_samples, self.n_chan))
|
||||||
|
|
||||||
def update_plot(self):
|
def update_plot(self):
|
||||||
k = 0
|
k = 0
|
||||||
@@ -112,33 +114,37 @@ class LSLViewer():
|
|||||||
samples, timestamps = self.inlet.pull_chunk(timeout=1.0,
|
samples, timestamps = self.inlet.pull_chunk(timeout=1.0,
|
||||||
max_samples=12)
|
max_samples=12)
|
||||||
if timestamps:
|
if timestamps:
|
||||||
self.data = np.vstack([self.data, samples])
|
|
||||||
if self.dejitter:
|
if self.dejitter:
|
||||||
timestamps = np.float64(np.arange(len(timestamps)))
|
timestamps = np.float64(np.arange(len(timestamps)))
|
||||||
timestamps /= self.sfreq
|
timestamps /= self.sfreq
|
||||||
timestamps += self.times[-1] + 1./self.sfreq
|
timestamps += self.times[-1] + 1./self.sfreq
|
||||||
self.times = np.concatenate([self.times, timestamps])
|
self.times = np.concatenate([self.times, timestamps])
|
||||||
|
|
||||||
self.n_samples = int(self.sfreq * self.window)
|
self.n_samples = int(self.sfreq * self.window)
|
||||||
self.data = self.data[-self.n_samples:]
|
|
||||||
self.times = self.times[-self.n_samples:]
|
self.times = self.times[-self.n_samples:]
|
||||||
|
self.data = np.vstack([self.data, samples])
|
||||||
|
self.data = self.data[-self.n_samples:]
|
||||||
|
filt_samples, self.filt_state = lfilter(
|
||||||
|
self.bf, self.af,
|
||||||
|
samples,
|
||||||
|
axis=0, zi=self.filt_state)
|
||||||
|
self.data_f = np.vstack([self.data_f, filt_samples])
|
||||||
|
self.data_f = self.data_f[-self.n_samples:]
|
||||||
k += 1
|
k += 1
|
||||||
if k == self.display_every:
|
if k == self.display_every:
|
||||||
if self.filt:
|
|
||||||
data_f = filtfilt(self.bf, self.af, self.data, axis=0)
|
|
||||||
else:
|
|
||||||
data_f = self.data
|
|
||||||
data_f -= data_f.mean(axis=0)
|
|
||||||
|
|
||||||
|
if self.filt:
|
||||||
|
plot_data = self.data_f
|
||||||
|
elif not self.filt:
|
||||||
|
plot_data = self.data - self.data.mean(axis=0)
|
||||||
for ii in range(self.n_chan):
|
for ii in range(self.n_chan):
|
||||||
self.lines[ii].set_xdata(self.times[::subsample] -
|
self.lines[ii].set_xdata(self.times[::subsample] -
|
||||||
self.times[-1])
|
self.times[-1])
|
||||||
self.lines[ii].set_ydata(data_f[::subsample, ii] /
|
self.lines[ii].set_ydata(plot_data[::subsample, ii] /
|
||||||
self.scale - ii)
|
self.scale - ii)
|
||||||
|
impedances = np.std(plot_data, axis=0)
|
||||||
|
|
||||||
impedances = np.std(data_f, axis=0)
|
ticks_labels = ['%s - %.2f' % (self.ch_names[ii],
|
||||||
ticks_labels = ['%s - %.2f' %
|
impedances[ii])
|
||||||
(self.ch_names[ii], impedances[ii])
|
|
||||||
for ii in range(self.n_chan)]
|
for ii in range(self.n_chan)]
|
||||||
self.axes.set_yticklabels(ticks_labels)
|
self.axes.set_yticklabels(ticks_labels)
|
||||||
self.axes.set_xlim(-self.window, 0)
|
self.axes.set_xlim(-self.window, 0)
|
||||||
|
|||||||
+23
-17
@@ -1,17 +1,15 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
## code by Alexandre Barachant
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
from scipy.signal import butter, filtfilt
|
from scipy.signal import butter, lfilter, lfilter_zi
|
||||||
from time import time, sleep
|
from time import sleep
|
||||||
from pylsl import StreamInlet, resolve_byprop
|
from pylsl import StreamInlet, resolve_byprop
|
||||||
|
from optparse import OptionParser
|
||||||
import seaborn as sns
|
import seaborn as sns
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
|
||||||
sns.set(style="whitegrid")
|
sns.set(style="whitegrid")
|
||||||
|
|
||||||
from optparse import OptionParser
|
|
||||||
|
|
||||||
parser = OptionParser()
|
parser = OptionParser()
|
||||||
|
|
||||||
parser.add_option("-w", "--window",
|
parser.add_option("-w", "--window",
|
||||||
@@ -55,6 +53,7 @@ class LSLViewer():
|
|||||||
self.dejitter = dejitter
|
self.dejitter = dejitter
|
||||||
self.inlet = StreamInlet(stream, max_chunklen=buf)
|
self.inlet = StreamInlet(stream, max_chunklen=buf)
|
||||||
self.filt = True
|
self.filt = True
|
||||||
|
|
||||||
info = self.inlet.info()
|
info = self.inlet.info()
|
||||||
description = info.desc()
|
description = info.desc()
|
||||||
|
|
||||||
@@ -105,6 +104,9 @@ class LSLViewer():
|
|||||||
|
|
||||||
self.bf, self.af = butter(4, np.array([1, 40])/(self.sfreq/2.),
|
self.bf, self.af = butter(4, np.array([1, 40])/(self.sfreq/2.),
|
||||||
'bandpass')
|
'bandpass')
|
||||||
|
zi = lfilter_zi(self.bf, self.af)
|
||||||
|
self.filt_state = np.tile(zi, (self.n_chan, 1)).transpose()
|
||||||
|
self.data_f = np.zeros((self.n_samples, self.n_chan))
|
||||||
|
|
||||||
def update_plot(self):
|
def update_plot(self):
|
||||||
k = 0
|
k = 0
|
||||||
@@ -112,33 +114,37 @@ class LSLViewer():
|
|||||||
samples, timestamps = self.inlet.pull_chunk(timeout=1.0,
|
samples, timestamps = self.inlet.pull_chunk(timeout=1.0,
|
||||||
max_samples=12)
|
max_samples=12)
|
||||||
if timestamps:
|
if timestamps:
|
||||||
self.data = np.vstack([self.data, samples])
|
|
||||||
if self.dejitter:
|
if self.dejitter:
|
||||||
timestamps = np.float64(np.arange(len(timestamps)))
|
timestamps = np.float64(np.arange(len(timestamps)))
|
||||||
timestamps /= self.sfreq
|
timestamps /= self.sfreq
|
||||||
timestamps += self.times[-1] + 1./self.sfreq
|
timestamps += self.times[-1] + 1./self.sfreq
|
||||||
self.times = np.concatenate([self.times, timestamps])
|
self.times = np.concatenate([self.times, timestamps])
|
||||||
|
|
||||||
self.n_samples = int(self.sfreq * self.window)
|
self.n_samples = int(self.sfreq * self.window)
|
||||||
self.data = self.data[-self.n_samples:]
|
|
||||||
self.times = self.times[-self.n_samples:]
|
self.times = self.times[-self.n_samples:]
|
||||||
|
self.data = np.vstack([self.data, samples])
|
||||||
|
self.data = self.data[-self.n_samples:]
|
||||||
|
filt_samples, self.filt_state = lfilter(
|
||||||
|
self.bf, self.af,
|
||||||
|
samples,
|
||||||
|
axis=0, zi=self.filt_state)
|
||||||
|
self.data_f = np.vstack([self.data_f, filt_samples])
|
||||||
|
self.data_f = self.data_f[-self.n_samples:]
|
||||||
k += 1
|
k += 1
|
||||||
if k == self.display_every:
|
if k == self.display_every:
|
||||||
if self.filt:
|
|
||||||
data_f = filtfilt(self.bf, self.af, self.data, axis=0)
|
|
||||||
else:
|
|
||||||
data_f = self.data
|
|
||||||
data_f -= data_f.mean(axis=0)
|
|
||||||
|
|
||||||
|
if self.filt:
|
||||||
|
plot_data = self.data_f
|
||||||
|
elif not self.filt:
|
||||||
|
plot_data = self.data - self.data.mean(axis=0)
|
||||||
for ii in range(self.n_chan):
|
for ii in range(self.n_chan):
|
||||||
self.lines[ii].set_xdata(self.times[::subsample] -
|
self.lines[ii].set_xdata(self.times[::subsample] -
|
||||||
self.times[-1])
|
self.times[-1])
|
||||||
self.lines[ii].set_ydata(data_f[::subsample, ii] /
|
self.lines[ii].set_ydata(plot_data[::subsample, ii] /
|
||||||
self.scale - ii)
|
self.scale - ii)
|
||||||
|
impedances = np.std(plot_data, axis=0)
|
||||||
|
|
||||||
impedances = np.std(data_f, axis=0)
|
ticks_labels = ['%s - %.2f' % (self.ch_names[ii],
|
||||||
ticks_labels = ['%s - %.2f' %
|
impedances[ii])
|
||||||
(self.ch_names[ii], impedances[ii])
|
|
||||||
for ii in range(self.n_chan)]
|
for ii in range(self.n_chan)]
|
||||||
self.axes.set_yticklabels(ticks_labels)
|
self.axes.set_yticklabels(ticks_labels)
|
||||||
self.axes.set_xlim(-self.window, 0)
|
self.axes.set_xlim(-self.window, 0)
|
||||||
|
|||||||
+23
-17
@@ -1,17 +1,15 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
## code by Alexandre Barachant
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
from scipy.signal import butter, filtfilt
|
from scipy.signal import butter, lfilter, lfilter_zi
|
||||||
from time import time, sleep
|
from time import sleep
|
||||||
from pylsl import StreamInlet, resolve_byprop
|
from pylsl import StreamInlet, resolve_byprop
|
||||||
|
from optparse import OptionParser
|
||||||
import seaborn as sns
|
import seaborn as sns
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
|
||||||
sns.set(style="whitegrid")
|
sns.set(style="whitegrid")
|
||||||
|
|
||||||
from optparse import OptionParser
|
|
||||||
|
|
||||||
parser = OptionParser()
|
parser = OptionParser()
|
||||||
|
|
||||||
parser.add_option("-w", "--window",
|
parser.add_option("-w", "--window",
|
||||||
@@ -55,6 +53,7 @@ class LSLViewer():
|
|||||||
self.dejitter = dejitter
|
self.dejitter = dejitter
|
||||||
self.inlet = StreamInlet(stream, max_chunklen=buf)
|
self.inlet = StreamInlet(stream, max_chunklen=buf)
|
||||||
self.filt = True
|
self.filt = True
|
||||||
|
|
||||||
info = self.inlet.info()
|
info = self.inlet.info()
|
||||||
description = info.desc()
|
description = info.desc()
|
||||||
|
|
||||||
@@ -105,6 +104,9 @@ class LSLViewer():
|
|||||||
|
|
||||||
self.bf, self.af = butter(4, np.array([1, 40])/(self.sfreq/2.),
|
self.bf, self.af = butter(4, np.array([1, 40])/(self.sfreq/2.),
|
||||||
'bandpass')
|
'bandpass')
|
||||||
|
zi = lfilter_zi(self.bf, self.af)
|
||||||
|
self.filt_state = np.tile(zi, (self.n_chan, 1)).transpose()
|
||||||
|
self.data_f = np.zeros((self.n_samples, self.n_chan))
|
||||||
|
|
||||||
def update_plot(self):
|
def update_plot(self):
|
||||||
k = 0
|
k = 0
|
||||||
@@ -112,33 +114,37 @@ class LSLViewer():
|
|||||||
samples, timestamps = self.inlet.pull_chunk(timeout=1.0,
|
samples, timestamps = self.inlet.pull_chunk(timeout=1.0,
|
||||||
max_samples=12)
|
max_samples=12)
|
||||||
if timestamps:
|
if timestamps:
|
||||||
self.data = np.vstack([self.data, samples])
|
|
||||||
if self.dejitter:
|
if self.dejitter:
|
||||||
timestamps = np.float64(np.arange(len(timestamps)))
|
timestamps = np.float64(np.arange(len(timestamps)))
|
||||||
timestamps /= self.sfreq
|
timestamps /= self.sfreq
|
||||||
timestamps += self.times[-1] + 1./self.sfreq
|
timestamps += self.times[-1] + 1./self.sfreq
|
||||||
self.times = np.concatenate([self.times, timestamps])
|
self.times = np.concatenate([self.times, timestamps])
|
||||||
|
|
||||||
self.n_samples = int(self.sfreq * self.window)
|
self.n_samples = int(self.sfreq * self.window)
|
||||||
self.data = self.data[-self.n_samples:]
|
|
||||||
self.times = self.times[-self.n_samples:]
|
self.times = self.times[-self.n_samples:]
|
||||||
|
self.data = np.vstack([self.data, samples])
|
||||||
|
self.data = self.data[-self.n_samples:]
|
||||||
|
filt_samples, self.filt_state = lfilter(
|
||||||
|
self.bf, self.af,
|
||||||
|
samples,
|
||||||
|
axis=0, zi=self.filt_state)
|
||||||
|
self.data_f = np.vstack([self.data_f, filt_samples])
|
||||||
|
self.data_f = self.data_f[-self.n_samples:]
|
||||||
k += 1
|
k += 1
|
||||||
if k == self.display_every:
|
if k == self.display_every:
|
||||||
if self.filt:
|
|
||||||
data_f = filtfilt(self.bf, self.af, self.data, axis=0)
|
|
||||||
else:
|
|
||||||
data_f = self.data
|
|
||||||
data_f -= data_f.mean(axis=0)
|
|
||||||
|
|
||||||
|
if self.filt:
|
||||||
|
plot_data = self.data_f
|
||||||
|
elif not self.filt:
|
||||||
|
plot_data = self.data - self.data.mean(axis=0)
|
||||||
for ii in range(self.n_chan):
|
for ii in range(self.n_chan):
|
||||||
self.lines[ii].set_xdata(self.times[::subsample] -
|
self.lines[ii].set_xdata(self.times[::subsample] -
|
||||||
self.times[-1])
|
self.times[-1])
|
||||||
self.lines[ii].set_ydata(data_f[::subsample, ii] /
|
self.lines[ii].set_ydata(plot_data[::subsample, ii] /
|
||||||
self.scale - ii)
|
self.scale - ii)
|
||||||
|
impedances = np.std(plot_data, axis=0)
|
||||||
|
|
||||||
impedances = np.std(data_f, axis=0)
|
ticks_labels = ['%s - %.2f' % (self.ch_names[ii],
|
||||||
ticks_labels = ['%s - %.2f' %
|
impedances[ii])
|
||||||
(self.ch_names[ii], impedances[ii])
|
|
||||||
for ii in range(self.n_chan)]
|
for ii in range(self.n_chan)]
|
||||||
self.axes.set_yticklabels(ticks_labels)
|
self.axes.set_yticklabels(ticks_labels)
|
||||||
self.axes.set_xlim(-self.window, 0)
|
self.axes.set_xlim(-self.window, 0)
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
from scipy import signal, stats
|
||||||
|
import numpy as np
|
||||||
|
import pandas as pd
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import argparse
|
||||||
|
import sys
|
||||||
|
|
||||||
|
## sampling rate of ganglion is 200Hz
|
||||||
|
fs = 200.0
|
||||||
|
|
||||||
|
def extract_data(fname):
|
||||||
|
d = pd.read_csv(fname)
|
||||||
|
eeg = np.array(d.ix[:, 1:5])
|
||||||
|
tag = np.array(d.Marker)
|
||||||
|
start = np.where(tag == 1)[0][0]
|
||||||
|
end = np.where(tag == 2)[0][0]
|
||||||
|
eeg = eeg[start:end]
|
||||||
|
return eeg
|
||||||
|
|
||||||
|
## get data
|
||||||
|
eeg1 = extract_data(sys.argv[1])
|
||||||
|
eeg2 = extract_data(sys.argv[2])
|
||||||
|
|
||||||
|
## data may be off by a few samples, so need to align
|
||||||
|
N_samp = min(len(eeg1), len(eeg2))
|
||||||
|
eeg1 = eeg1[:N_samp]
|
||||||
|
eeg2 = eeg2[:N_samp]
|
||||||
|
|
||||||
|
## filter signal to remove noise
|
||||||
|
b, a = signal.butter(2, (2/(fs/2), 20/(fs/2)), btype='bandpass')
|
||||||
|
eeg1 = signal.filtfilt(b, a, eeg1, axis=0)
|
||||||
|
eeg2 = signal.filtfilt(b, a, eeg2, axis=0)
|
||||||
|
|
||||||
|
## advance window of 200 samples
|
||||||
|
## take correlation between signals across each sample
|
||||||
|
window = 200
|
||||||
|
step = 25
|
||||||
|
corr = []
|
||||||
|
times = []
|
||||||
|
|
||||||
|
for start in np.arange(0, N_samp, step):
|
||||||
|
end = start + window
|
||||||
|
w1 = eeg1[start:end]
|
||||||
|
w2 = eeg2[start:end]
|
||||||
|
|
||||||
|
## average the correlation across each channel
|
||||||
|
r = 0
|
||||||
|
for c in range(w1.shape[1]):
|
||||||
|
r += stats.pearsonr(w1[:, c], w2[:, c])[0]
|
||||||
|
r /= w1.shape[1]
|
||||||
|
|
||||||
|
mid = (start+end)/2 # middle sample
|
||||||
|
t = mid / fs # convert middle sample to time
|
||||||
|
|
||||||
|
|
||||||
|
times.append(t)
|
||||||
|
corr.append(r)
|
||||||
|
|
||||||
|
times = np.array(times)
|
||||||
|
corr = np.array(corr)
|
||||||
|
|
||||||
|
plt.figure(figsize=(14,4))
|
||||||
|
plt.plot(times, np.abs(corr))
|
||||||
|
plt.xlabel('Time (s)')
|
||||||
|
plt.ylabel('Correlation')
|
||||||
|
plt.title('Correlation across brains')
|
||||||
|
plt.show()
|
||||||
@@ -76,7 +76,9 @@
|
|||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 21,
|
"execution_count": 21,
|
||||||
"metadata": {},
|
"metadata": {
|
||||||
|
"collapsed": true
|
||||||
|
},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"## filter signal to remove noise\n",
|
"## filter signal to remove noise\n",
|
||||||
@@ -181,7 +183,7 @@
|
|||||||
"name": "python",
|
"name": "python",
|
||||||
"nbconvert_exporter": "python",
|
"nbconvert_exporter": "python",
|
||||||
"pygments_lexer": "ipython3",
|
"pygments_lexer": "ipython3",
|
||||||
"version": "3.6.0"
|
"version": "3.6.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nbformat": 4,
|
"nbformat": 4,
|
||||||
|
|||||||
@@ -1,17 +1,15 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
## code by Alexandre Barachant
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
from scipy.signal import butter, filtfilt
|
from scipy.signal import butter, lfilter, lfilter_zi
|
||||||
from time import time, sleep
|
from time import sleep
|
||||||
from pylsl import StreamInlet, resolve_byprop
|
from pylsl import StreamInlet, resolve_byprop
|
||||||
|
from optparse import OptionParser
|
||||||
import seaborn as sns
|
import seaborn as sns
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
|
||||||
sns.set(style="whitegrid")
|
sns.set(style="whitegrid")
|
||||||
|
|
||||||
from optparse import OptionParser
|
|
||||||
|
|
||||||
parser = OptionParser()
|
parser = OptionParser()
|
||||||
|
|
||||||
parser.add_option("-w", "--window",
|
parser.add_option("-w", "--window",
|
||||||
@@ -55,6 +53,7 @@ class LSLViewer():
|
|||||||
self.dejitter = dejitter
|
self.dejitter = dejitter
|
||||||
self.inlet = StreamInlet(stream, max_chunklen=buf)
|
self.inlet = StreamInlet(stream, max_chunklen=buf)
|
||||||
self.filt = True
|
self.filt = True
|
||||||
|
|
||||||
info = self.inlet.info()
|
info = self.inlet.info()
|
||||||
description = info.desc()
|
description = info.desc()
|
||||||
|
|
||||||
@@ -105,6 +104,9 @@ class LSLViewer():
|
|||||||
|
|
||||||
self.bf, self.af = butter(4, np.array([1, 40])/(self.sfreq/2.),
|
self.bf, self.af = butter(4, np.array([1, 40])/(self.sfreq/2.),
|
||||||
'bandpass')
|
'bandpass')
|
||||||
|
zi = lfilter_zi(self.bf, self.af)
|
||||||
|
self.filt_state = np.tile(zi, (self.n_chan, 1)).transpose()
|
||||||
|
self.data_f = np.zeros((self.n_samples, self.n_chan))
|
||||||
|
|
||||||
def update_plot(self):
|
def update_plot(self):
|
||||||
k = 0
|
k = 0
|
||||||
@@ -112,33 +114,37 @@ class LSLViewer():
|
|||||||
samples, timestamps = self.inlet.pull_chunk(timeout=1.0,
|
samples, timestamps = self.inlet.pull_chunk(timeout=1.0,
|
||||||
max_samples=12)
|
max_samples=12)
|
||||||
if timestamps:
|
if timestamps:
|
||||||
self.data = np.vstack([self.data, samples])
|
|
||||||
if self.dejitter:
|
if self.dejitter:
|
||||||
timestamps = np.float64(np.arange(len(timestamps)))
|
timestamps = np.float64(np.arange(len(timestamps)))
|
||||||
timestamps /= self.sfreq
|
timestamps /= self.sfreq
|
||||||
timestamps += self.times[-1] + 1./self.sfreq
|
timestamps += self.times[-1] + 1./self.sfreq
|
||||||
self.times = np.concatenate([self.times, timestamps])
|
self.times = np.concatenate([self.times, timestamps])
|
||||||
|
|
||||||
self.n_samples = int(self.sfreq * self.window)
|
self.n_samples = int(self.sfreq * self.window)
|
||||||
self.data = self.data[-self.n_samples:]
|
|
||||||
self.times = self.times[-self.n_samples:]
|
self.times = self.times[-self.n_samples:]
|
||||||
|
self.data = np.vstack([self.data, samples])
|
||||||
|
self.data = self.data[-self.n_samples:]
|
||||||
|
filt_samples, self.filt_state = lfilter(
|
||||||
|
self.bf, self.af,
|
||||||
|
samples,
|
||||||
|
axis=0, zi=self.filt_state)
|
||||||
|
self.data_f = np.vstack([self.data_f, filt_samples])
|
||||||
|
self.data_f = self.data_f[-self.n_samples:]
|
||||||
k += 1
|
k += 1
|
||||||
if k == self.display_every:
|
if k == self.display_every:
|
||||||
if self.filt:
|
|
||||||
data_f = filtfilt(self.bf, self.af, self.data, axis=0)
|
|
||||||
else:
|
|
||||||
data_f = self.data
|
|
||||||
data_f -= data_f.mean(axis=0)
|
|
||||||
|
|
||||||
|
if self.filt:
|
||||||
|
plot_data = self.data_f
|
||||||
|
elif not self.filt:
|
||||||
|
plot_data = self.data - self.data.mean(axis=0)
|
||||||
for ii in range(self.n_chan):
|
for ii in range(self.n_chan):
|
||||||
self.lines[ii].set_xdata(self.times[::subsample] -
|
self.lines[ii].set_xdata(self.times[::subsample] -
|
||||||
self.times[-1])
|
self.times[-1])
|
||||||
self.lines[ii].set_ydata(data_f[::subsample, ii] /
|
self.lines[ii].set_ydata(plot_data[::subsample, ii] /
|
||||||
self.scale - ii)
|
self.scale - ii)
|
||||||
|
impedances = np.std(plot_data, axis=0)
|
||||||
|
|
||||||
impedances = np.std(data_f, axis=0)
|
ticks_labels = ['%s - %.2f' % (self.ch_names[ii],
|
||||||
ticks_labels = ['%s - %.2f' %
|
impedances[ii])
|
||||||
(self.ch_names[ii], impedances[ii])
|
|
||||||
for ii in range(self.n_chan)]
|
for ii in range(self.n_chan)]
|
||||||
self.axes.set_yticklabels(ticks_labels)
|
self.axes.set_yticklabels(ticks_labels)
|
||||||
self.axes.set_xlim(-self.window, 0)
|
self.axes.set_xlim(-self.window, 0)
|
||||||
|
|||||||
Arquivo binário não exibido.
Arquivo binário não exibido.
Arquivo binário não exibido.
+23
-17
@@ -1,17 +1,15 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
## code by Alexandre Barachant
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
from scipy.signal import butter, filtfilt
|
from scipy.signal import butter, lfilter, lfilter_zi
|
||||||
from time import time, sleep
|
from time import sleep
|
||||||
from pylsl import StreamInlet, resolve_byprop
|
from pylsl import StreamInlet, resolve_byprop
|
||||||
|
from optparse import OptionParser
|
||||||
import seaborn as sns
|
import seaborn as sns
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
|
||||||
sns.set(style="whitegrid")
|
sns.set(style="whitegrid")
|
||||||
|
|
||||||
from optparse import OptionParser
|
|
||||||
|
|
||||||
parser = OptionParser()
|
parser = OptionParser()
|
||||||
|
|
||||||
parser.add_option("-w", "--window",
|
parser.add_option("-w", "--window",
|
||||||
@@ -55,6 +53,7 @@ class LSLViewer():
|
|||||||
self.dejitter = dejitter
|
self.dejitter = dejitter
|
||||||
self.inlet = StreamInlet(stream, max_chunklen=buf)
|
self.inlet = StreamInlet(stream, max_chunklen=buf)
|
||||||
self.filt = True
|
self.filt = True
|
||||||
|
|
||||||
info = self.inlet.info()
|
info = self.inlet.info()
|
||||||
description = info.desc()
|
description = info.desc()
|
||||||
|
|
||||||
@@ -105,6 +104,9 @@ class LSLViewer():
|
|||||||
|
|
||||||
self.bf, self.af = butter(4, np.array([1, 40])/(self.sfreq/2.),
|
self.bf, self.af = butter(4, np.array([1, 40])/(self.sfreq/2.),
|
||||||
'bandpass')
|
'bandpass')
|
||||||
|
zi = lfilter_zi(self.bf, self.af)
|
||||||
|
self.filt_state = np.tile(zi, (self.n_chan, 1)).transpose()
|
||||||
|
self.data_f = np.zeros((self.n_samples, self.n_chan))
|
||||||
|
|
||||||
def update_plot(self):
|
def update_plot(self):
|
||||||
k = 0
|
k = 0
|
||||||
@@ -112,33 +114,37 @@ class LSLViewer():
|
|||||||
samples, timestamps = self.inlet.pull_chunk(timeout=1.0,
|
samples, timestamps = self.inlet.pull_chunk(timeout=1.0,
|
||||||
max_samples=12)
|
max_samples=12)
|
||||||
if timestamps:
|
if timestamps:
|
||||||
self.data = np.vstack([self.data, samples])
|
|
||||||
if self.dejitter:
|
if self.dejitter:
|
||||||
timestamps = np.float64(np.arange(len(timestamps)))
|
timestamps = np.float64(np.arange(len(timestamps)))
|
||||||
timestamps /= self.sfreq
|
timestamps /= self.sfreq
|
||||||
timestamps += self.times[-1] + 1./self.sfreq
|
timestamps += self.times[-1] + 1./self.sfreq
|
||||||
self.times = np.concatenate([self.times, timestamps])
|
self.times = np.concatenate([self.times, timestamps])
|
||||||
|
|
||||||
self.n_samples = int(self.sfreq * self.window)
|
self.n_samples = int(self.sfreq * self.window)
|
||||||
self.data = self.data[-self.n_samples:]
|
|
||||||
self.times = self.times[-self.n_samples:]
|
self.times = self.times[-self.n_samples:]
|
||||||
|
self.data = np.vstack([self.data, samples])
|
||||||
|
self.data = self.data[-self.n_samples:]
|
||||||
|
filt_samples, self.filt_state = lfilter(
|
||||||
|
self.bf, self.af,
|
||||||
|
samples,
|
||||||
|
axis=0, zi=self.filt_state)
|
||||||
|
self.data_f = np.vstack([self.data_f, filt_samples])
|
||||||
|
self.data_f = self.data_f[-self.n_samples:]
|
||||||
k += 1
|
k += 1
|
||||||
if k == self.display_every:
|
if k == self.display_every:
|
||||||
if self.filt:
|
|
||||||
data_f = filtfilt(self.bf, self.af, self.data, axis=0)
|
|
||||||
else:
|
|
||||||
data_f = self.data
|
|
||||||
data_f -= data_f.mean(axis=0)
|
|
||||||
|
|
||||||
|
if self.filt:
|
||||||
|
plot_data = self.data_f
|
||||||
|
elif not self.filt:
|
||||||
|
plot_data = self.data - self.data.mean(axis=0)
|
||||||
for ii in range(self.n_chan):
|
for ii in range(self.n_chan):
|
||||||
self.lines[ii].set_xdata(self.times[::subsample] -
|
self.lines[ii].set_xdata(self.times[::subsample] -
|
||||||
self.times[-1])
|
self.times[-1])
|
||||||
self.lines[ii].set_ydata(data_f[::subsample, ii] /
|
self.lines[ii].set_ydata(plot_data[::subsample, ii] /
|
||||||
self.scale - ii)
|
self.scale - ii)
|
||||||
|
impedances = np.std(plot_data, axis=0)
|
||||||
|
|
||||||
impedances = np.std(data_f, axis=0)
|
ticks_labels = ['%s - %.2f' % (self.ch_names[ii],
|
||||||
ticks_labels = ['%s - %.2f' %
|
impedances[ii])
|
||||||
(self.ch_names[ii], impedances[ii])
|
|
||||||
for ii in range(self.n_chan)]
|
for ii in range(self.n_chan)]
|
||||||
self.axes.set_yticklabels(ticks_labels)
|
self.axes.set_yticklabels(ticks_labels)
|
||||||
self.axes.set_xlim(-self.window, 0)
|
self.axes.set_xlim(-self.window, 0)
|
||||||
|
|||||||
Referência em uma Nova Issue
Bloquear um usuário