Skip to content

Commit 67eea59

Browse files
committed
- Modified plotting classes so that they no longer use setPos to scroll the plot and instead implement the scrolling by modifying the plotted data. The previous method no longer worked in pyqtgraph versions > 0.11.0.
- Changed the default update interval for the GUI to 10ms to give smoother plot scrolling at the cost of somewhat higher CPU usage.
1 parent dbc453d commit 67eea59

File tree

2 files changed

+14
-27
lines changed

2 files changed

+14
-27
lines changed

config/gui_settings.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
VERSION = '1.6'
44

5-
update_interval = 20 # Interval between calls to the GUIs update function (ms).
5+
update_interval = 10 # Interval between calls to the GUIs update function (ms).
66

77
event_history_len = 200 # Length of event history to plot (# events).
88
state_history_len = 100 # Length of state history to plot (# states).

gui/plotting.py

+13-26
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import numpy as np
33
from datetime import timedelta
44
import pyqtgraph as pg
5-
from pyqtgraph.Qt import QtGui, QtWidgets
5+
from pyqtgraph.Qt import QtGui
66
from PyQt5.QtCore import Qt
77

88
from config.gui_settings import event_history_len, state_history_len, analog_history_dur
@@ -114,34 +114,28 @@ def run_start(self):
114114
self.data = np.zeros([self.data_len*2, 2], int)
115115
for plot in self.plots.values():
116116
plot.clear()
117-
self.cs = self.state_IDs[0]
118-
self.updated_states = []
119117

120118
def process_data(self, new_data):
121119
'''Store new data from board'''
122120
new_states = [nd for nd in new_data if nd[0] == 'D' and nd[2] in self.state_IDs]
123-
self.updated_states = [self.cs]
124121
if new_states:
125122
n_new =len(new_states)
126123
self.data = np.roll(self.data, -2*n_new, axis=0)
127124
for i, ns in enumerate(new_states): # Update data array.
128125
timestamp, ID = ns[1:]
129-
self.updated_states.append(ID)
130126
j = 2*(-n_new+i) # Index of state entry in self.data
131127
self.data[j-1:,0] = timestamp
132128
self.data[j: ,1] = ID
133-
self.cs = ID
134129

135130
def update(self, run_time):
136131
'''Update plots.'''
137-
self.data[-1,0] = 1000*run_time # Update exit time of current state to current time.
138-
for us in self.updated_states: # Set data for updated state plots.
139-
state_data = self.data[self.data[:,1]==us,:]
140-
timestamps, ID = (state_data[:,0]/1000, state_data[:,1])
141-
self.plots[us].setData(x=timestamps, y=ID, connect='pairs')
142-
# Shift all state plots.
143-
for plot in self.plots.values():
144-
plot.setPos(-run_time, 0)
132+
self.data[-1,0] = run_time*1000 # Update exit time of current state to current time.
133+
for ID in self.state_IDs:
134+
state_data = self.data[self.data[:,1]==ID,:]
135+
timestamps, IDs = (state_data[:,0]/1000-run_time, state_data[:,1])
136+
if timestamps.size > 0:
137+
self.plots[ID].setData(x=timestamps, y=IDs, connect='pairs')
138+
145139

146140
# Events_plot--------------------------------------------------------
147141

@@ -187,10 +181,8 @@ def process_data(self, new_data):
187181

188182
def update(self, run_time):
189183
'''Update plots'''
190-
# Should not need to setData but setPos does not cause redraw otherwise.
191184
if not self.event_IDs: return
192-
self.plot.setData(self.data, symbolBrush=[pg.intColor(ID) for ID in self.data[:,1]])
193-
self.plot.setPos(-run_time, 0)
185+
self.plot.setData(x=self.data[:,0]-run_time, y=self.data[:,1], symbolBrush=[pg.intColor(ID) for ID in self.data[:,1]])
194186

195187
# ------------------------------------------------------------------------------------------
196188

@@ -205,15 +197,12 @@ def __init__(self, parent=None, data_dur=10):
205197
self.axis.setMouseEnabled(x=True,y=False)
206198
self.axis.showGrid(x=True,alpha=0.75)
207199
self.axis.setLimits(xMax=0)
208-
self.legend = None
209200

210201
def set_state_machine(self, sm_info):
211202
self.inputs = sm_info['analog_inputs']
212203
if not self.inputs: return # State machine may not have analog inputs.
213-
if self.legend:
214-
self.legend.close()
215-
self.legend = self.axis.addLegend(offset=(10, 10))
216204
self.axis.clear()
205+
self.legend = self.axis.addLegend(offset=(10, 10))
217206
self.plots = {ai['ID']: self.axis.plot(name=name,
218207
pen=pg.mkPen(pg.intColor(ai['ID'],len(self.inputs)))) for name, ai in sorted(self.inputs.items())}
219208
self.axis.getAxis('bottom').setLabel('Time (seconds)')
@@ -232,7 +221,6 @@ def process_data(self, new_data):
232221
'''Store new data from board.'''
233222
if not self.inputs: return # State machine may not have analog inputs.
234223
new_analog = [nd for nd in new_data if nd[0] == 'A']
235-
self.updated_inputs = [na[1] for na in new_analog]
236224
for na in new_analog:
237225
ID, sampling_rate, timestamp, data_array = na[1:]
238226
new_len = len(data_array)
@@ -243,10 +231,9 @@ def process_data(self, new_data):
243231
def update(self, run_time):
244232
'''Update plots.'''
245233
if not self.inputs: return # State machine may not have analog inputs.
246-
for ID in self.updated_inputs:
247-
self.plots[ID].setData(self.data[ID])
248-
for plot in self.plots.values():
249-
plot.setPos(-run_time, 0)
234+
for ai in self.inputs.values():
235+
ID = ai['ID']
236+
self.plots[ID].setData(x=self.data[ID][:,0]-run_time, y=self.data[ID][:,1])
250237

251238
# -----------------------------------------------------
252239

0 commit comments

Comments
 (0)