-
Notifications
You must be signed in to change notification settings - Fork 6
/
graph_matplotlib.py
171 lines (137 loc) · 4.8 KB
/
graph_matplotlib.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
from pylsl import StreamInlet, resolve_byprop, local_clock, TimeoutError
from pyqtgraph.Qt import QtGui,QtCore
import collections
import numpy as np
import pyqtgraph as pg
import time
import signal, sys, os, time, csv
import serial
import threading
import win32api as win
import matplotlib.pyplot as plt
#import matplotlib.axes as ax
numSamples = 0
#count = -1
graph = None
class Graph(object):
def __init__(self, size=(600,350)):
streams = resolve_byprop('name', 'bci', timeout=2.5)
try:
self.inlet = StreamInlet(streams[0])
except IndexError:
raise ValueError('Make sure stream name=bci is opened first.')
self.running = True
self.ProcessedSig = []
self.SecondTimes = []
self.count = -1
self.sampleCount = self.count
self.maximum = 0
self.minimum = 0
plt.ion()
plt.hold(False)
self.lineHandle = plt.plot(self.SecondTimes, self.ProcessedSig)
plt.title("Live Stream EEG Data")
plt.xlabel('Time (s)')
plt.ylabel('mV')
#plt.autoscale(True, 'y', tight = True)
plt.show()
#while(1):
#secondTimes.append(serialData[0]) #add time stamps to array 'timeValSeconds'
#floatSecondTimes.append(float(serialData[0])/1000000) # makes all second times into float from string
#processedSig.append(serialData[6]) #add processed signal values to 'processedSig'
#floatProcessedSig.append(float(serialData[6]))
def _graph_lsl(self):
while self.running:
# initial run
self.sample, self.timestamp = self.inlet.pull_sample(timeout=5)
#if self.timeBuffer[0] == 0.0:
# self.timeBuffer = collections.deque([self.timestamp] * self._bufsize, self._bufsize)
# time correction to sync to local_clock()
try:
if self.timestamp is not None and self.sample is not None:
self.timestamp = self.timestamp + self.inlet.time_correction(timeout=5)
except TimeoutError:
pass
self.SecondTimes.append(self.timestamp) #add time stamps to array 'timeValSeconds'
#print(abs(self.sample[3])/1000)
self.ProcessedSig.append(abs(self.sample[3])/1000) #add processed signal values to 'processedSig'
if(abs(self.sample[3]/1000) > self.maximum):
self.maximum = abs(self.sample[3]/1000)
if(abs(self.sample[3]/1000) < self.minimum):
self.minimum = abs(self.sample[3]/1000)
self.sampleCount = self.sampleCount + 1
self.count = self.count + 1
#plt.show()
if((self.count % 20 == 0) and (self.count != 0)): #every 20 samples (ie ~ 0.2 ms) is when plot updates. Change the sample number (ie 20) to modify frequency at which plot updates
#if(self.count == 20):
self.count = -1
self.lineHandle[0].set_ydata(self.ProcessedSig)
self.lineHandle[0].set_xdata(self.SecondTimes)
#plt.xlim(0, 5)
plt.xlim(self.SecondTimes[0], self.SecondTimes[-1])
plt.ylim(self.minimum - 0.75, self.maximum + 0.75)
#plt.ylim(0, 20)
#plt.ylim(0, 10)
#elf.ax.set_autoscaley_on(True)
#plt.autoscale(enable=True, axis='y', tight=True)
plt.pause(0.01)
if(self.sampleCount >= 511): #shows up to 2 seconds of data (512 samples = 2s of data given a 256 Hz sampling freq by the BCI)
self.ProcessedSig.pop(0)
self.SecondTimes.pop(0)
plt.pause(0.01)
print('closing graphing utility')
self.inlet.close_stream()
def start(self):
#self.lsl_thread = threading.Thread(target=self._graph_lsl)
#self.lsl_thread.start()
self._graph_lsl()
def stop(self):
self.running = False
self.lsl_thread.join(5)
def load(queue):
global graph
graph = Graph()
print('init graph')
def start():
graph.start()
#graph.app.exec_()
def stop():
graph.stop()
print('Stopping graphing.')
os._exit(0) # dirty, but it's ok because everything is already cleaned up
def sigint_handler(signal, frame):
stop()
def sigterm_handler(signal, frame):
stop()
def win_handler(dwCtrlType):
if dwCtrlType in (0,2,6):
return 1
def main():
signal.signal(signal.SIGINT, sigint_handler)
signal.signal(signal.SIGTERM, sigterm_handler)
load(queue=None)
start()
try:
signal.pause()
except AttributeError:
while True:
time.sleep(1)
stop()
def begin(queue, event=None):
signal.signal(signal.SIGINT, sigint_handler)
signal.signal(signal.SIGTERM, sigterm_handler)
if sys.platform == 'win32':
win.SetConsoleCtrlHandler(win_handler, 1)
load(queue)
start()
while True:
try:
signal.pause()
except AttributeError:
# signal.pause() not implemented on windows
while not event.is_set():
time.sleep(1)
print('event was set in graphing utility, stopping')
stop()
if __name__ == '__main__':
main()