Пример #1
0
class matplotsink(wx.Panel):
    def __init__(self, parent, title, queue, gsz, zoom):
        wx.Panel.__init__(self, parent, wx.SIMPLE_BORDER)

        self.gsz = gsz
        self.parent = parent
        self.title = title
        self.q = queue
        self.zoom = zoom
        self.paused = False

        #        self.create_menu()
        #        self.create_status_bar()
        self.create_main_panel()

    def create_menu(self):
        self.menubar = wx.MenuBar()

        menu_file = wx.Menu()
        m_expt = menu_file.Append(-1, "&Save plot\tCtrl-S",
                                  "Save plot to file")
        self.Bind(wx.EVT_MENU, self.on_save_plot, m_expt)
        menu_file.AppendSeparator()
        m_exit = menu_file.Append(-1, "E&xit\tCtrl-X", "Exit")
        self.Bind(wx.EVT_MENU, self.on_exit, m_exit)
        self.menubar.Append(menu_file, "&File")
        self.SetMenuBar(self.menubar)

    def create_main_panel(self):
        self.panel = self

        self.init_plot()
        self.canvas = FigCanvas(self.panel, -1, self.fig)
        self.scroll_range = 400
        self.canvas.SetScrollbar(wx.HORIZONTAL, 0, 5, self.scroll_range)
        self.canvas.Bind(wx.EVT_SCROLLWIN, self.OnScrollEvt)

        self.pause_button = wx.Button(self.panel, -1, "Pause")
        self.Bind(wx.EVT_BUTTON, self.on_pause_button, self.pause_button)
        self.Bind(wx.EVT_UPDATE_UI, self.on_update_pause_button,
                  self.pause_button)

        self.cb_grid = wx.CheckBox(self.panel,
                                   -1,
                                   "Show Grid",
                                   style=wx.ALIGN_RIGHT)
        self.Bind(wx.EVT_CHECKBOX, self.on_cb_grid, self.cb_grid)
        self.cb_grid.SetValue(True)

        self.cb_xlab = wx.CheckBox(self.panel,
                                   -1,
                                   "Show X labels",
                                   style=wx.ALIGN_RIGHT)
        self.Bind(wx.EVT_CHECKBOX, self.on_cb_xlab, self.cb_xlab)
        self.cb_xlab.SetValue(True)

        self.hbox1 = wx.BoxSizer(wx.HORIZONTAL)
        self.hbox1.Add(self.pause_button,
                       border=5,
                       flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL)
        self.hbox1.AddSpacer(20)
        self.hbox1.Add(self.cb_grid,
                       border=5,
                       flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL)
        self.hbox1.AddSpacer(10)
        self.hbox1.Add(self.cb_xlab,
                       border=5,
                       flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL)

        self.vbox = wx.BoxSizer(wx.VERTICAL)
        self.vbox.Add(self.canvas, 1, flag=wx.LEFT | wx.TOP | wx.GROW)
        self.vbox.Add(self.hbox1, 0, flag=wx.ALIGN_LEFT | wx.TOP)

        self.panel.SetSizer(self.vbox)
        self.vbox.Fit(self)
        self.ani = animation.FuncAnimation(self.fig,
                                           self.draw_plot,
                                           interval=100)

    def OnScrollEvt(self, event):
        self.i_start = event.GetPosition()
        self.i_end = self.i_window + event.GetPosition()
        self.draw_plot(0)

    def create_status_bar(self):
        self.statusbar = self.CreateStatusBar()

    def draw_test(self, event):
        self.xar = np.arange(len(self.q.queue))
        self.yar = np.array(self.q.queue)
        self.axes.plot(self.xar, self.yar)

    def init_plot(self):
        self.dpi = 100
        self.fig = Figure((3.0, 3.0), dpi=self.dpi)
        self.fig.set_size_inches(7.0, 4.0)
        self.fig.set_dpi(self.dpi)

        self.axes = self.fig.add_subplot(111)
        self.axes.set_axis_bgcolor('black')
        self.axes.set_title(self.title, size=12)

        pylab.setp(self.axes.get_xticklabels(), fontsize=8)
        pylab.setp(self.axes.get_yticklabels(), fontsize=8)
        self.i_window = self.gsz
        self.i_start = 0
        self.i_end = self.i_start + self.i_window
        # plot the data as a line series, and save the reference
        # to the plotted line series
        #
        self.plot_data = self.axes.plot(
            [],
            linewidth=1,
            color=(1, 1, 0),
        )[0]

    def draw_plot(self, event):
        """ Redraws the plot
         """
        if len(list(self.q.queue)) > 1 and not self.paused:

            if self.zoom:
                xmax = len(list(
                    self.q.queue)) if len(list(self.q.queue)) > 50 else 50

                xmin = xmax - 50
                # for ymin and ymax, find the minimal and maximal values
                # in the data set and add a mininal margin.
                #
                # note that it's easy to change this scheme to the
                # minimal/maximal value in the current display, and not
                # the whole data set.
                #
                ymin = round(min(list(self.q.queue)), 0) - 1

                ymax = round(max(list(self.q.queue)), 0) + 1

                self.axes.set_xbound(lower=xmin, upper=xmax)
                self.axes.set_ybound(lower=ymin, upper=ymax)

                # anecdote: axes.grid assumes b=True if any other flag is
                # given even if b is set to False.
                # so just passing the flag into the first statement won't
                # work.
                #
                if self.cb_grid.IsChecked():
                    self.axes.grid(True, color='gray')
                else:
                    self.axes.grid(False)

                # Using setp here is convenient, because get_xticklabels
                # returns a list over which one needs to explicitly
                # iterate, and setp already handles this.
                #
                pylab.setp(self.axes.get_xticklabels(),
                           visible=self.cb_xlab.IsChecked())

                self.plot_data.set_xdata(np.arange(len(list(self.q.queue))))
                self.plot_data.set_ydata(np.array(list(self.q.queue)))
                self.canvas.draw()

            else:
                if self.cb_grid.IsChecked():
                    self.axes.grid(True, color='gray')
                else:
                    self.axes.grid(False)

        # Using setp here is convenient, because get_xticklabels
        # returns a list over which one needs to explicitly
        # iterate, and setp already handles this.

                pylab.setp(self.axes.get_xticklabels(),
                           visible=self.cb_xlab.IsChecked())

                self.plot_data.set_xdata(
                    np.arange(len(list(
                        self.q.queue)))[self.i_start:self.i_end])
                self.plot_data.set_ydata(
                    np.array(list(self.q.queue))[self.i_start:self.i_end])
                self.axes.set_xlim(
                    min(
                        np.arange(len(list(
                            self.q.queue)))[self.i_start:self.i_end]),
                    max(
                        np.arange(len(list(
                            self.q.queue)))[self.i_start:self.i_end]))
                #		 if self.zoom:
                self.axes.set_ylim(min(np.array(list(self.q.queue))),
                                   max(np.array(list(self.q.queue))))

                self.canvas.draw()

    def on_pause_button(self, event):
        self.paused = not self.paused

    def on_update_pause_button(self, event):
        label = "Resume" if self.paused else "Pause"
        self.pause_button.SetLabel(label)

    def on_cb_grid(self, event):
        self.draw_plot(0)

    def on_cb_xlab(self, event):
        self.draw_plot(0)

    def on_save_plot(self, event):
        file_choices = "PNG (*.png)|*.png"

        dlg = wx.FileDialog(self,
                            message="Save plot as...",
                            defaultDir=os.getcwd(),
                            defaultFile="plot.png",
                            wildcard=file_choices,
                            style=wx.SAVE)

        if dlg.ShowModal() == wx.ID_OK:
            path = dlg.GetPath()
            self.canvas.print_figure(path, dpi=self.dpi)
            self.flash_status_message("Saved to %s" % path)

    def on_redraw_timer(self, event):
        # if paused do not add data, but still redraw the plot
        # (to respond to scale modifications, grid change, etc.)
        #
        if not self.paused:
            self.data += self.datagen.next()
        self.draw_plot(0)

    def on_exit(self, event):
        self.Destroy()

    def flash_status_message(self, msg, flash_len_ms=1500):
        self.statusbar.SetStatusText(msg)
        self.timeroff = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.on_flash_status_off, self.timeroff)
        self.timeroff.Start(flash_len_ms, oneShot=True)

    def on_flash_status_off(self, event):
        self.statusbar.SetStatusText('')
Пример #2
0
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):
    def __init__(self, parent, id):
        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 = 400
        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.init_data()
        self.init_plot()

        self.canvas.Bind(wx.EVT_SCROLLWIN, self.OnScrollEvt)

    def init_data(self):
        
        # Generate some data to plot:
        self.dt = 0.01
        self.t = arange(0,5,self.dt)
        self.x = sin(2*pi*self.t)

        # Extents of data sequence: 
        self.i_min = 0
        self.i_max = len(self.t)

        # Size of plot window:       
        self.i_window = 100

        # Indices of data interval to be plotted:
        self.i_start = 0
        self.i_end = self.i_start + self.i_window

    def init_plot(self):
        self.axes = self.fig.add_subplot(111)
        self.plot_data = \
                  self.axes.plot(self.t[self.i_start:self.i_end],
                                 self.x[self.i_start:self.i_end])[0]

    def draw_plot(self):

        # Update data in plot:
        self.plot_data.set_xdata(self.t[self.i_start:self.i_end])
        self.plot_data.set_ydata(self.x[self.i_start:self.i_end])

        # Adjust plot limits:
        self.axes.set_xlim((min(self.t[self.i_start:self.i_end]),
                           max(self.t[self.i_start:self.i_end])))
        self.axes.set_ylim((min(self.x[self.i_start:self.i_end]),
                            max(self.x[self.i_start:self.i_end])))

        # Redraw:                  
        self.canvas.draw()

    def OnScrollEvt(self, event):

	# 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()
        self.draw_plot()
Пример #4
0
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