class MyFrame(wx.Frame): def __init__(self, parent, id, trial_values, outsider_points, channel_number, trial_number, channel_mean, channel_std_der, y_min, y_max, stdX): wx.Frame.__init__(self, parent, id, 'scrollable plot', style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER, size=(800, 400)) self.panel = wx.Panel(self, -1) self.fig = Figure((5, 4), 75) self.canvas = FigureCanvasWxAgg(self.panel, -1, self.fig) self.scroll_range = len(trial_values) self.canvas.SetScrollbar(wx.HORIZONTAL, 0, 5, self.scroll_range) sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(self.canvas, -1, wx.EXPAND) self.panel.SetSizer(sizer) self.panel.Fit() self.outsider_points = outsider_points self.bursts_x = list(map(lambda x: x[0], self.outsider_points)) self.bursts_y = list(map(lambda x: x[1], self.outsider_points)) self.stdX = stdX self.y_min = y_min self.y_max = y_max self.channel_mean = channel_mean self.channel_std_der = channel_std_der self.trial_values = trial_values self.init_data() self.init_plot(channel_number, trial_number) self.canvas.Bind(wx.EVT_SCROLLWIN, self.OnScrollEvt) def init_data(self): self.x = [] for i in range(len(self.trial_values)): self.x.append(i) # Extents of data sequence: self.i_min = 0 # self.i_max = len(self.t) self.i_max = len(self.trial_values) # Size of plot window: self.i_window = len(self.trial_values) # Indices of data interval to be plotted: self.i_start = 0 self.i_end = self.i_start + self.i_window def init_plot(self, channel_number, trial_number): self.axes = self.fig.add_subplot(111) self.plot_data = \ self.axes.plot(self.x[self.i_start:self.i_end], self.trial_values[self.i_start:self.i_end])[0] self.axes.set_ylim(min(self.y_min, -self.stdX * self.channel_std_der), self.y_max) self.axes.axhline(y=self.channel_mean, linewidth=0.3, color='r') self.axes.axhline(y=self.stdX * self.channel_std_der, linewidth=0.3, color='g', linestyle='--') self.axes.axhline(y=-self.stdX * self.channel_std_der, linewidth=0.3, color='g', linestyle='--') self.axes.set_ylabel('Amplitudes') self.axes.set_xlabel('Relative Timestamp') self.axes.set_title('Channel ' + str(channel_number) + ' Trial ' + str(trial_number) + ' Snapshot') def draw_plot(self): # Update data in plot: self.plot_data.set_xdata(self.x[self.i_start:self.i_end]) self.plot_data.set_ydata(self.trial_values[self.i_start:self.i_end]) # Adjust plot limits: self.axes.set_xlim((min(self.x[self.i_start:self.i_end]), max(self.x[self.i_start:self.i_end]))) self.axes.set_ylim(min(self.y_min, -self.stdX * self.channel_std_der), self.y_max) self.axes.axhline(y=self.channel_mean, linewidth=0.3, color='r') self.axes.axhline(y=self.stdX * self.channel_std_der, linewidth=0.3, color='g', linestyle='--') self.axes.axhline(y=-self.stdX * self.channel_std_der, linewidth=0.3, color='g', linestyle='--') # self.axes.scatter(self.bursts_x, self.bursts_y, c='black') for i in range(0, len(self.bursts_x), 2): point1 = [self.bursts_x[i], self.bursts_y[i]] point2 = [self.bursts_x[i + 1], self.bursts_y[i + 1]] x_values = [point1[0], point2[0]] y_values = [point1[1], point2[1]] if (all(i > self.channel_mean for i in y_values)): y_values = [ self.stdX * self.channel_std_der, self.stdX * self.channel_std_der ] else: y_values = [ -self.stdX * self.channel_std_der, -self.stdX * self.channel_std_der ] self.axes.plot(x_values, y_values, color='black') self.axes.scatter(x_values, y_values, c='black') # Redraw: self.canvas.draw() def update_scrollpos(self, new_pos): self.i_start = self.i_min + new_pos self.i_end = self.i_min + self.i_window + new_pos self.canvas.SetScrollPos(wx.HORIZONTAL, new_pos) self.draw_plot() def OnScrollEvt(self, event): evtype = event.GetEventType() if evtype == wx.EVT_SCROLLWIN_THUMBTRACK.typeId: pos = event.GetPosition() self.update_scrollpos(pos) elif evtype == wx.EVT_SCROLLWIN_LINEDOWN.typeId: pos = self.canvas.GetScrollPos(wx.HORIZONTAL) self.update_scrollpos(pos + 1) elif evtype == wx.EVT_SCROLLWIN_LINEUP.typeId: pos = self.canvas.GetScrollPos(wx.HORIZONTAL) self.update_scrollpos(pos - 1) elif evtype == wx.EVT_SCROLLWIN_PAGEUP.typeId: pos = self.canvas.GetScrollPos(wx.HORIZONTAL) self.update_scrollpos(pos - 10) elif evtype == wx.EVT_SCROLLWIN_PAGEDOWN.typeId: pos = self.canvas.GetScrollPos(wx.HORIZONTAL) self.update_scrollpos(pos + 10) else: print("unhandled scroll event, type id:", evtype)
class MyFrame(wx.Frame): """ Creates a GUI class that displays data for an 8x8 set of electrodes with the corners missing. Main View: Scrollable data for each electrode is displayed according to the placement of electrodes in the 8x8 arrangement Zoom in View: Scrollable data for a single electrode is displayed with MatPlotLib options such as saving data """ def __init__(self, parent, id, data, time, samprate): #Specify electrode numbers and electrodes that are missed #In this specific implementation we have #8x8 set of electrodes, with corners missing (0,7,56,63) self.empty = [0, 7, 56, 63] self.electrodeX = 8 self.electrodeY = 8 """ if len(data)!=(self.electrodeX*self.electrodeY-len(self.empty)): print "You do not have enough data for electrodes." print "There should be data for 64 electrodes" raise ValueError """ #Data Variables self.data = data self.time = time self.samprate = samprate #Adjust Display Size tmp = wx.DisplaySize() tmp2 = (tmp[0], tmp[1] - 100) wx.Frame.__init__(self, parent, id, 'LSCE - Overall Plot', (0, 0), tmp2) self.panel = wx.Panel(self, -1) self.dimensions = self.GetSize() self.xoffset = 50 self.yoffset = 100 self.labelwidth = 140 #canvas, graphs, scrollbar self.fig = Figure((5, 4), 75) self.canvas = FigureCanvasWxAgg(self.panel, -1, self.fig) self.scroll_range = len(data[0]) - time * samprate + 1 print self.scroll_range self.canvas.SetScrollbar(wx.HORIZONTAL, 0, max(1, self.scroll_range / 20), self.scroll_range) self.graphs = [] sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(self.canvas, -1, wx.EXPAND) self.panel.SetSizer(sizer) self.panel.Fit() self.lastupdate = datetime.datetime.utcnow() self.init_data() self.init_plot() self.Layout() #Bind Events, Scrollbar & Button Press self.canvas.Bind(wx.EVT_SCROLLWIN_THUMBTRACK, self.OnScrollEvt) self.canvas.Bind(wx.EVT_SCROLLWIN_THUMBRELEASE, self.OnScrollStop) self.canvas.mpl_connect('button_press_event', self.onclick) """ Parses data to be fed into visualization. """ def init_data(self): # Generate x axis limits and data intervals: self.dt = 1.0 / self.samprate self.t = arange(0, float(len(self.data[0])) / self.samprate, self.dt) print "There are " + self.t.__repr__( ) + " time series, and " + self.data[0].__repr__() + " data entries." # Extents of data sequence: self.i_min = 0 self.i_max = len(self.t) # Size of plot window: self.i_window = self.time * self.samprate print "Window size is " + self.i_window.__repr__() + " entries." # Indices of data interval to be plotted: self.i_start = 0 self.i_end = self.i_start + self.i_window """ Creates 8x8 Data Plots """ def init_plot(self): #Start Time End Time Label Positioning self.label1x = self.xoffset self.labely = self.dimensions[1] - self.yoffset self.label2x = self.dimensions[0] - self.xoffset - self.labelwidth #Start Time End Time Labels self.startTime = wx.TextCtrl( self.panel, value="Start Time: " + (float(self.i_start) / self.samprate).__repr__(), pos=(self.label1x, self.labely), size=(self.labelwidth, -1)) self.endTime = wx.TextCtrl( self.panel, value="End Time: " + (float(self.i_end) / self.samprate).__repr__(), pos=(self.label2x, self.labely), size=(self.labelwidth, -1)) #creating each sub plot self.axes = [] self.graphs = [] arrayoffset = 0 for j in range(self.electrodeX * self.electrodeY): if j not in self.empty: self.axes.append( self.fig.add_subplot(self.electrodeX, self.electrodeY, j + 1)) self.axes[j].yaxis.set_major_locator( matplotlib.ticker.NullLocator()) self.axes[j].xaxis.set_major_locator( matplotlib.ticker.NullLocator()) self.dataCurrent = self.data[0] self.graphs.append(self.axes[j].plot( self.t[self.i_start:self.i_end], self.data[0][self.i_start:self.i_end])[0]) else: self.axes.append(0) self.graphs.append(0) arrayoffset = arrayoffset + 1 self.canvas.draw() """ Updates the section of data displayed according to scrolling event """ def draw_plot(self): # Adjust plot limits: for i in range(self.electrodeX * self.electrodeY): if i not in self.empty: # Update data in plot: self.graphs[i].set_xdata(self.t[self.i_start:self.i_end]) self.graphs[i].set_ydata(self.data[0][self.i_start:self.i_end]) self.axes[i].set_xlim((min(self.t[self.i_start:self.i_end]), max(self.t[self.i_start:self.i_end]))) self.axes[i].set_ylim( (min(self.data[0][self.i_start:self.i_end]), max(self.data[0][self.i_start:self.i_end]))) # Redraw: self.canvas.draw() self.startTime.Refresh() self.endTime.Refresh() """ Handles Graph Scrolling """ def OnScrollEvt(self, event): if ((datetime.datetime.utcnow() - self.lastupdate).microseconds > 250000): self.draw_plot() self.lastupdate = datetime.datetime.utcnow() # Update the indices of the plot: self.i_start = self.i_min + event.GetPosition() self.i_end = self.i_min + self.i_window + event.GetPosition() #Update Scrollbar & labels self.canvas.SetScrollPos(wx.HORIZONTAL, event.GetPosition(), True) self.startTime.ChangeValue("Start Time: " + (float(self.i_start) / self.samprate).__repr__()) self.endTime.ChangeValue("End Time: " + (float(self.i_end) / self.samprate).__repr__()) """ Handles Graph Scrolling """ def OnScrollStop(self, event): self.draw_plot() """ When a graph is clicked on, handles the creation of a zoomed in view of that graph (Zoom in View) """ def onclick(self, event): #loop through all plots to check which one was clicked i = 0 while i < self.electrodeX * self.electrodeY: if i not in self.empty: if event.inaxes == self.axes[i]: fig2 = plt.figure() ax_single = fig2.add_subplot(111) #input in data and graph section/ limits ax_single.plot(self.t, self.data[0], 'yo-') ax_single.set_xlim([0, self.time]) ax_single.set_autoscale_on(False) #Plot Naming According to Electrode Position if (i + 1) % self.electrodeX != 0: rowno = ((i + 1) / self.electrodeX) + 1 else: rowno = (i + 1) / self.electrodeX if (i + 1) % self.electrodeX == 0: colno = self.electrodeX else: colno = (i + 1) % self.electrodeX fig2.canvas.set_window_title('Plot ' + rowno.__repr__() + " x " + colno.__repr__()) fig2.show() break i += 1