示例#1
0
class PlotFigure(wx.Frame):
    global plt_data_a_x, plt_data_a_y, plt_data_b_x, plt_data_b_y, plt_data_c_x, plt_data_c_y

    def __init__(self):

        wx.Frame.__init__(self, None, wx.ID_ANY, title="!!!", size=(1000, 1000))
        self.fig = Figure((10, 10), 100)
        self.canvas = FigureCanvas(self, wx.ID_ANY, self.fig)
        self.ax = self.fig.add_subplot(111)
        self.ax.set_ylim([-10, 10])
        self.ax.set_xlim([-5, 15])
        self.ax.set_autoscale_on(False)
        self.ax.grid(True)
        self.user, = self.ax.plot(plt_data_a_x, plt_data_a_y, 'o', label='map')
        self.ax.legend(loc='upper center')
        self.canvas.draw()
        self.bg = self.canvas.copy_from_bbox(self.ax.bbox)
        wx.EVT_TIMER(self, TIMER_ID, self.onTimer)

    def onTimer(self, evt):
        """callback function for timer events"""

        self.canvas.restore_region(self.bg)
        a, = self.ax.plot(plt_data_b_x, plt_data_b_y, 'or')
        self.ax.draw_artist(a)
        b, = self.ax.plot(plt_data_c_x, plt_data_c_y, 'og')
        self.ax.draw_artist(b)
        c, = self.ax.plot(plt_data_d_x, plt_data_d_y, 'ok')
        self.ax.draw_artist(c)
        self.canvas.blit(self.ax.bbox)
示例#2
0
class MyFigure():
    def __init__(self, panel, ipos, isize=(400, 230)):
        self.fig_container = wx.TextCtrl(panel,
                                         -1,
                                         "",
                                         pos=ipos,
                                         size=isize,
                                         style=wx.TE_MULTILINE | wx.TE_RICH2)
        self.fig = Figure((4, 2), 100)
        self.canvas = FigureCanvas(self.fig_container, wx.ID_ANY, self.fig)
        self.ax = self.fig.add_subplot(111)
        self.ax.set_autoscale_on(False)
        self.ax.set(xlim=[0, TOTAL_SEND], ylim=[0, MAX_DELTA])
        self.ax.grid(True)
        self.data = [0] * TOTAL_SEND
        self.plt_data, = self.ax.plot(range(TOTAL_SEND), self.data)
        self.canvas.draw()
        self.bg = self.canvas.copy_from_bbox(self.ax.bbox)
        self.index = 0

    def update(self, idata):
        self.data[self.index] = float(idata.microseconds) / 1000000
        self.canvas.restore_region(self.bg)
        self.plt_data.set_ydata(self.data)
        self.ax.draw_artist(self.plt_data)
        self.canvas.blit(self.ax.bbox)
        self.index += 1
示例#3
0
class AngleCircle(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, style = wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX, title='Neo LiDAR demo(python)', size=(800, 800))
        self.fig = Figure((8, 8), 100)
        self.canvas = FigureCanvas(self, wx.ID_ANY, self.fig)
        self.ax = self.fig.add_subplot(111)
        self.ax.set_ylim([-10, 10])
        self.ax.set_xlim([-10, 10])
        self.ax.set_autoscale_on(False)
        self.ax.set_xticks(range(-10, 11, 2))
        self.ax.set_yticks(range(-10, 11, 2))
        self.ax.grid(True)
#        self.datax = [None] * 360
#        self.datay = [None] * 360
        #for i in range(360):
            #x[i] = np.random.randint(-40, 40)
            #y[i] = np.random.randint(-40, 40)
        #self.datax = np.random.randn(100)
        #self.datay = np.random.randn(100)
        self.draw_data, = self.ax.plot(x, y, '.', ms = 3.0, mec = 'RED')
        self.canvas.draw()
        self.bg = self.canvas.copy_from_bbox(self.ax.bbox)
        wx.EVT_TIMER(self, TIMER_ID, self.onTimer)
        th.start()


    def onTimer(self, evt):
        global x, y
        global flag
        self.canvas.restore_region(self.bg)
        #self.draw_data.set_data(x, y)
        #self.draw_data.set_ydata(y)
        self.ax.draw_artist(self.draw_data)
        self.canvas.blit(self.ax.bbox)
示例#4
0
文件: show.py 项目: xeecos/LightMusic
class PlotFigure(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, title="Sensor Monitor", size=(800, 600))
        #set window size
        self.fig = Figure((8, 6), 100)
        self.canvas = FigureCanvas(self, wx.ID_ANY, self.fig)
        self.ax = self.fig.add_subplot(111)
        self.ax.set_ylim([0, 100])
        self.ax.set_xlim([0, POINTS])
        self.ax.set_autoscale_on(False)
        self.ax.set_xticks([])
        self.ax.set_yticks(range(0, 101, 10))
        self.ax.grid(True)
        self.user = [None] * POINTS
        self.l_user,=self.ax.plot(range(POINTS),self.user,label='Light Sensors')
        self.ax.legend(loc='upper center',
                           ncol=4,
                           prop=font_manager.FontProperties(size=10))
        self.canvas.draw()
        self.bg = self.canvas.copy_from_bbox(self.ax.bbox)
        wx.EVT_TIMER(self, TIMER_ID, self.onTimer)

    def onTimer(self, evt):
        self.canvas.restore_region(self.bg)
        for i in range(0,240):
          index = int(i/40)*40
          per = (index-i)+20.0
          per =((math.sin((per/20.0)*math.pi/2))+1.0)/2.0
          self.user[i+30] = 100-(float(arr[i/40])*per+float(arr[(i+40)/40])*(1-per))*1
        self.l_user.set_ydata(self.user)
        self.ax.draw_artist(self.l_user)
        self.canvas.blit(self.ax.bbox)
示例#5
0
class PlotFigure(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, title="CPU Usage Monitor", size=(600, 400))
        # Matplotlib Figur
        self.fig = Figure((6, 4), 100)
        # bind the Figure to the backend specific canvas
        self.canvas = FigureCanvas(self, wx.ID_ANY, self.fig)
        # add a subplot  
        self.ax = self.fig.add_subplot(111)
         # limit the X and Y axes dimensions 
        self.ax.set_ylim([0, 100])
        self.ax.set_xlim([0, POINTS])
         
        self.ax.set_autoscale_on(False)
        self.ax.set_xticks([])
        # we want a tick every 10 point on Y (101 is to have 10  
        self.ax.set_yticks(range(0, 101, 10))


        # disable autoscale, since we don't want the Axes to ad  
        # draw a grid (it will be only for Y)  
        self.ax.grid(True)  
        # generates first "empty" plots  
        self.user = [None] * POINTS  
        self.l_user,=self.ax.plot(range(POINTS),self.user,label='User %')  
    
        # add the legend  
        self.ax.legend(loc='upper center',  
                           ncol=4,  
                           prop=font_manager.FontProperties(size=10))  
        # force a draw on the canvas()  
         # trick to show the grid and the legend  
        self.canvas.draw()  
        # save the clean background - everything but the line  
        # is drawn and saved in the pixel buffer background  
        self.bg = self.canvas.copy_from_bbox(self.ax.bbox)  
        # bind events coming from timer with id = TIMER_ID  
        # to the onTimer callback function  
        wx.EVT_TIMER(self, TIMER_ID, self.onTimer)  
        self.Bind(wx.EVT_CLOSE,self.frame_close,self)
      
    def onTimer(self, evt):  
        self.canvas.restore_region(self.bg)  
                    # update the data  
        temp =np.random.randint(60,80)  
        self.user = self.user[1:] + [temp]  
            # update the plot  
        self.l_user.set_ydata(self.user)  
            # just draw the "animated" objects  
        self.ax.draw_artist(self.l_user)# It is used to efficiently update Axes data (axis ticks, labels, etc are not updated)  
        self.canvas.blit(self.ax.bbox) 
        print num
    
    def frame_close(self,event):
        self.Show(False)

    def __del__(self):
        exit()
示例#6
0
class PlotFigure(wx.Frame):
    """Matplotlib wxFrame with animation effect"""
    def __init__(self):
        wx.Frame.__init__(self,
                          None,
                          wx.ID_ANY,
                          title="CPU Usage Monitor",
                          size=(600, 400))
        # Matplotlib Figure
        self.fig = Figure((6, 4), 100)
        # bind the Figure to the backend specific canvas
        self.canvas = FigureCanvas(self, wx.ID_ANY, self.fig)
        # add a subplot
        self.ax = self.fig.add_subplot(111)
        # limit the X and Y axes dimensions
        self.ax.set_ylim([0, 100])
        self.ax.set_xlim([0, POINTS])

        self.ax.set_autoscale_on(False)
        self.ax.set_xticks([])
        # we want a tick every 10 point on Y (101 is to have 10
        self.ax.set_yticks(range(0, 101, 10))
        # disable autoscale, since we don't want the Axes to ad
        # draw a grid (it will be only for Y)
        self.ax.grid(True)
        # generates first "empty" plots
        self.user = [None] * POINTS
        self.l_user, = self.ax.plot(range(POINTS), self.user, label='User %')

        # add the legend
        self.ax.legend(loc='upper center',
                       ncol=4,
                       prop=font_manager.FontProperties(size=10))
        # force a draw on the canvas()
        # trick to show the grid and the legend
        self.canvas.draw()
        # save the clean background - everything but the line
        # is drawn and saved in the pixel buffer background
        self.bg = self.canvas.copy_from_bbox(self.ax.bbox)
        # bind events coming from timer with id = TIMER_ID
        # to the onTimer callback function
        wx.EVT_TIMER(self, TIMER_ID, self.onTimer)

    def onTimer(self, evt):
        """callback function for timer events"""
        # restore the clean background, saved at the beginning
        self.canvas.restore_region(self.bg)
        # update the data
        temp = np.random.randint(10, 80)
        self.user = self.user[1:] + [temp]
        # update the plot
        self.l_user.set_ydata(self.user)
        # just draw the "animated" objects
        self.ax.draw_artist(
            self.l_user
        )  # It is used to efficiently update Axes data (axis ticks, labels, etc are not updated)
        self.canvas.blit(self.ax.bbox)
class PlotFigure(wx.Frame):
    def __init__(self, groundTruth=None):
        wx.Frame.__init__(self, None, wx.ID_ANY, title="Trajectory")

        self.fig = Figure()
        self.canvas = FigureCanvas(self, wx.ID_ANY, self.fig)
        self.ax = self.fig.add_subplot(111)
        self.ax.set_xlim([-600, 1000])
        self.ax.set_ylim([-1500, 1500])
        self.ax.set_autoscale_on(False)
        self.orbPos1 = None
        self.orbPos2 = None
        self.ax.grid(True)

        if groundTruth != None:
            grnd = groundTruth.toArray(False)
            self.groundPlot, = self.ax.plot(grnd[:, 0], grnd[:, 1])

        # This must be done after all initial drawing
        self.canvas.draw()
        self.bg = self.canvas.copy_from_bbox(self.ax.bbox)

        # Bind events to timer function
        wx.EVT_TIMER(self, TIMER_ID, self.onTimer)

    def onTimer(self, event):
        self.canvas.restore_region(self.bg)

        orbPosition1 = orbProc1.getPose()
        if orbPosition1 is not None:
            if self.orbPos1 is None:
                self.orbPos1 = self.ax.scatter(orbPosition1.x,
                                               orbPosition1.y,
                                               color=[[1, 0, 0, 0.5]],
                                               s=100,
                                               linewidths=0)
            else:
                self.orbPos1.set_offsets([orbPosition1.x, orbPosition1.y])

        orbPosition2 = orbProc2.getPose()
        if orbPosition2 is not None:
            if self.orbPos2 is None:
                self.orbPos2 = self.ax.scatter(orbPosition2.x,
                                               orbPosition2.y,
                                               color=[[0, 1, 0, 0.5]],
                                               s=100,
                                               linewidths=0)
            else:
                self.orbPos2.set_offsets([orbPosition2.x, orbPosition2.y])

        self.canvas.draw()
        self.canvas.blit(self.ax.bbox)
示例#8
0
class PlotFigure(wx.Frame):
    def __init__(self,data):
        wx.Frame.__init__(self, None, wx.ID_ANY, title="CPU Usage Monitor", size=(600, 400))
        # Matplotlib Figur
        self.fig = Figure((6, 4), 100)
        self.canvas = FigureCanvas(self, wx.ID_ANY, self.fig)
        # add a subplot  
        self.ax = self.fig.add_subplot(111)
        self.data=data;
        self.ax.set_ylim([0,100])
        self.ax.set_xlim([0, POINTS])
        
        self.ax.set_autoscale_on(False)
        self.ax.set_xticks([])
        self.ax.set_yticks(range(0,100, 5))


        # disable autoscale, since we don't want the Axes to ad  
        # draw a grid (it will be only for Y)  
        self.ax.grid(True)  
        # generates first "empty" plots  
        self.user = [None] * POINTS  
        self.l_user,=self.ax.plot(range(POINTS),self.user,label=u'CPU percentage')  
    
        # add the legend  
        self.ax.legend(loc='upper center',  
                           ncol=4,  
                           prop=font_manager.FontProperties(size=10))  
        self.canvas.draw()  
        self.bg = self.canvas.copy_from_bbox(self.ax.bbox)  
        wx.EVT_TIMER(self, TIMER_ID, self.onTimer)  
        self.Bind(wx.EVT_CLOSE,self.frame_close,self)
      
    def onTimer(self, evt):  
        self.canvas.restore_region(self.bg)
        temp = (math.log(self.data.recvive())/LOG_FREQUENCE)*100
        #temp =np.random.randint(60,80)  

        self.user = self.user[1:] + [temp]  
            # update the plot  
        self.l_user.set_ydata(self.user)  
            # just draw the "animated" objects  
        self.ax.draw_artist(self.l_user)# It is used to efficiently update Axes data (axis ticks, labels, etc are not updated)  
        self.canvas.blit(self.ax.bbox) 
        #print self.data.recvive()
    
    def frame_close(self,event):
        self.Show(False)

    def __del__(self):
        exit()
示例#9
0
class PlotFigure(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, -1, "Test wxFigure")
        self.fig = p.figure(1)
        self.ax = p.subplot(111)
        self.canvas = FigureCanvasWxAgg(self, -1, self.fig)
        #        self.canvas = self.ax.figure.canvas
        self.background = None
        self.cnt = 0
        self.tstart = time.time()
        wx.EVT_TIMER(self, TIMER_ID, self.update_line)

    def init_plot(self):
        # create the initial line
        x = nx.arange(0, 2 * nx.pi, 0.01)
        self.l_pos_a = [((0, 0), (1, 1)), ((0, 1), (1, 0))]
        self.l_pos_b = [((0, 0), (0, 1)), ((1, 1), (1, 0))]
        self.line_c = LineCollection(self.l_pos_a, animated=True)
        line, = p.plot(x, nx.sin(x), animated=False)
        self.ax.add_collection(self.line_c)

    def update_line(self, evt):
        # save the clean slate background -- everything but the animated line
        # is drawn and saved in the pixel buffer background
        if self.background is None:
            self.background = self.canvas.copy_from_bbox(self.ax.bbox)

        # restore the clean slate background
        self.canvas.restore_region(self.background)
        # update the data
        #    line.set_ydata(nx.sin(x+update_line.cnt/10.0))
        if (self.cnt / 10) % 2 == 0:
            self.line_c.set_verts(self.l_pos_b)
        else:
            self.line_c.set_verts(self.l_pos_a)
        # just draw the animated artist
        self.ax.draw_artist(self.line_c)
        # just redraw the axes rectangle
        self.canvas.blit(self.ax.bbox)

        if self.cnt == 50:
            # print the timing info and quit
            print 'FPS:', self.cnt / (time.time() - self.tstart)
            sys.exit()

        self.cnt += 1

        #        wx.WakeUpIdle()
        return True
示例#10
0
class PlotFigure(wx.Frame):
    """Matplotlib wxFrame with animation effect"""
    def __init__(self):
        wx.Frame.__init__(self,
                          None,
                          wx.ID_ANY,
                          title="CPU Usage Monitor",
                          size=(600, 400))
        self.fig = Figure((6, 4), 100)
        self.canvas = FigureCanvas(self, wx.ID_ANY, self.fig)
        self.ax = self.fig.add_subplot(111)
        # limit the X and Y axes dimensions
        self.ax.set_ylim(2140, 2150)
        self.ax.set_xlim([0, POINTS])
        self.ax.set_autoscale_on(False)
        self.ax.set_xticks([])
        # we want a tick every 10 point on Y (101 is to have 10
        #self.ax.set_yticks(range(0, 101, 10))
        self.ax.grid(True)
        self.user = [None] * POINTS
        self.l_user, = self.ax.plot(range(POINTS), self.user, label=u'IF1406')

        self.md = MdThread("127.0.0.1", 12345)
        self.md.start()
        self.md.RegTick(self.OnTick)
        # add the legend
        self.ax.legend(loc='upper center',
                       ncol=4,
                       prop=font_manager.FontProperties(size=10))
        self.canvas.draw()
        self.bg = self.canvas.copy_from_bbox(self.ax.bbox)
        #wx.EVT_TIMER(self, TIMER_ID, self.onTimer)

    def OnTick(self, tick):
        self.canvas.restore_region(self.bg)
        # update the data
        if tick.InstrumentID != 'IF1404':
            return
        print tick.LastPrice
        temp = np.random.randint(10, 80)
        self.user = self.user[1:] + [tick.LastPrice]
        # update the plot
        self.l_user.set_ydata(self.user)
        # just draw the "animated" objects
        self.ax.draw_artist(
            self.l_user
        )  # It is used to efficiently update Axes data (axis ticks, labels, etc are not updated)
        self.canvas.blit(self.ax.bbox)
示例#11
0
class PlotFigure (wx.Frame):
    
    def __init__ (self, groundTruth=None):
        wx.Frame.__init__ (self, None, wx.ID_ANY, title="Trajectory")
        
        self.fig = Figure ()
        self.canvas = FigureCanvas(self, wx.ID_ANY, self.fig)
        self.ax = self.fig.add_subplot (111)
        self.ax.set_xlim ([-600, 1000])
        self.ax.set_ylim ([-1500, 1500])
        self.ax.set_autoscale_on (False)
        self.orbPos1 = None
        self.orbPos2 = None
        self.ax.grid(True)
        
        if groundTruth != None:
            grnd = groundTruth.toArray(False)
            self.groundPlot, = self.ax.plot (grnd[:,0], grnd[:,1])

        # This must be done after all initial drawing
        self.canvas.draw()
        self.bg = self.canvas.copy_from_bbox (self.ax.bbox)
        
        # Bind events to timer function
        wx.EVT_TIMER (self, TIMER_ID, self.onTimer)

    def onTimer (self, event):
        self.canvas.restore_region(self.bg)
        
        orbPosition1 = orbProc1.getPose()
        if orbPosition1 is not None:
            if self.orbPos1 is None:
                self.orbPos1 = self.ax.scatter (orbPosition1.x, orbPosition1.y, color=[[1,0,0,0.5]], s=100, linewidths=0)
            else :
                self.orbPos1.set_offsets([orbPosition1.x, orbPosition1.y])

        orbPosition2 = orbProc2.getPose()
        if orbPosition2 is not None:
            if self.orbPos2 is None:
                self.orbPos2 = self.ax.scatter (orbPosition2.x, orbPosition2.y, color=[[0,1,0,0.5]], s=100, linewidths=0)
            else :
                self.orbPos2.set_offsets([orbPosition2.x, orbPosition2.y])


        self.canvas.draw()
        self.canvas.blit(self.ax.bbox)
示例#12
0
class PlotFigure(wx.Frame):
    """Matplotlib wxFrame with animation effect"""
    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, title="CPU Usage Monitor", size=(600, 400))
        self.fig = Figure((6, 4), 100)
        self.canvas = FigureCanvas(self, wx.ID_ANY, self.fig)
        self.ax = self.fig.add_subplot(111)
        # limit the X and Y axes dimensions
        self.ax.set_ylim(2140, 2150)
        self.ax.set_xlim([0, POINTS])
        self.ax.set_autoscale_on(False)
        self.ax.set_xticks([])
        # we want a tick every 10 point on Y (101 is to have 10
        #self.ax.set_yticks(range(0, 101, 10))
        self.ax.grid(True)
        self.user = [None] * POINTS
        self.l_user,=self.ax.plot(range(POINTS),self.user,label=u'IF1406')

        self.md = MdThread("127.0.0.1",12345)
        self.md.start()
        self.md.RegTick(self.OnTick)
        # add the legend
        self.ax.legend(loc='upper center',
                           ncol=4,
                           prop=font_manager.FontProperties(size=10))
        self.canvas.draw()
        self.bg = self.canvas.copy_from_bbox(self.ax.bbox)
        #wx.EVT_TIMER(self, TIMER_ID, self.onTimer)

    def OnTick(self,tick):
        self.canvas.restore_region(self.bg)
                # update the data
        if tick.InstrumentID != 'IF1404':
            return
        print tick.LastPrice
        temp =np.random.randint(10,80)
        self.user = self.user[1:] + [tick.LastPrice]
        # update the plot
        self.l_user.set_ydata(self.user)
        # just draw the "animated" objects
        self.ax.draw_artist(self.l_user)# It is used to efficiently update Axes data (axis ticks, labels, etc are not updated)
        self.canvas.blit(self.ax.bbox)
示例#13
0
class PlotPanel(wx.Panel):
    
    def __init__(self,parent,data_window,yrange=(-3,3),**kwargs):
        from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
        from matplotlib.figure import Figure
                
        self.dw = data_window        
        
        # initialize Panel
        if 'style' not in kwargs.keys():
            kwargs['style'] = wx.NO_FULL_REPAINT_ON_RESIZE
        wx.Panel.__init__( self, parent, **kwargs )

        # initialize matplotlib stuff
        self.figure = Figure()
        self.canvas = FigureCanvasWxAgg(self, -1, self.figure )
        
        self.subplot_x = self.figure.add_subplot(311)
        self.subplot_x.set_ylim(yrange)   
        self.subplot_x.set_xticks([])     
        self.subplot_y = self.figure.add_subplot(312)
        self.subplot_y.set_ylim(yrange) 
        self.subplot_y.set_xticks([])
        self.subplot_z = self.figure.add_subplot(313)
        self.subplot_z.set_ylim(yrange)
        self.subplot_z.set_xticks([])
        
        self.dw.winlock.acquire()
        self.line_x, = self.subplot_x.plot(self.dw.win[:,0],color='r',lw=2,animated=True)
        self.line_y, = self.subplot_y.plot(self.dw.win[:,1],color='g',lw=2,animated=True)
        self.line_z, = self.subplot_z.plot(self.dw.win[:,2],color='b',lw=2,animated=True)
        self.dw.winlock.release()
        self.canvas.draw()
        self.draw()
        
        self.dw.start()
                
        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER,self.OnTimer,self.timer)
        self.timer.Start(1)

    def OnTimer(self,event):
        self.draw()

    def draw( self ):
        """Draw data."""
        if not hasattr(self, 'background' ):
            self.background = self.canvas.copy_from_bbox(self.figure.bbox)
            
        self.canvas.restore_region(self.background)
        self.dw.winlock.acquire()
        self.line_x.set_ydata(self.dw.win[:,0])
        self.line_y.set_ydata(self.dw.win[:,1])
        self.line_z.set_ydata(self.dw.win[:,2])
        self.dw.winlock.release()
        
        self.subplot_x.draw_artist(self.line_x)
        self.subplot_y.draw_artist(self.line_y)
        self.subplot_z.draw_artist(self.line_z)
        
        self.canvas.blit(self.subplot_x.bbox)
        self.canvas.blit(self.subplot_y.bbox)
        self.canvas.blit(self.subplot_z.bbox)
class Window(wx.Frame):
    global Monitor_Interval, y_Range

    def __init__(self, parent):
        super(Window, self).__init__(parent)
        self.InitUI()
        self.Centre()
        self.Show()
        self.SetIcon(wx.Icon('bitcoin_48px.ico', wx.BITMAP_TYPE_ICO))
        self.taskBarIcon = TaskBarIcon(self)
        # create some sizers
        mainSizer = wx.BoxSizer(wx.VERTICAL)
        checkSizer = wx.BoxSizer(wx.HORIZONTAL)

        #事件绑定
        self.Bind(wx.EVT_CLOSE, self.OnClose)
        self.Bind(wx.EVT_ICONIZE, self.OnIconfiy)  # 最小化事件绑定
        self.Bind(wx.EVT_PAINT, self.OnPaint)

    def InitUI(self):
        global initial_time, elapsed_time
        global Monitor_Interval, y_Range
        global Cur_Price, Max_Price, Min_Price, Price_Log, Counter
        #静态文本条
        wx.StaticText(self, label='Top price:', pos=(30, 310 + 50))
        wx.StaticText(self, label='Current price:', pos=(30, 330 + 50))
        wx.StaticText(self, label='Floor price:', pos=(30, 350 + 50))
        wx.StaticText(self, label='Current time:', pos=(210, 310 + 50))
        wx.StaticText(self, label='Monitor interval:', pos=(210, 330 + 50))
        wx.StaticText(self, label='Monitor time:', pos=(210, 350 + 50))
        wx.StaticText(self, label='Network state:', pos=(30, 310))
        wx.StaticText(self, label='Price trend:', pos=(210, 310))
        #动态文本条
        self.string_top_price = wx.StaticText(self,
                                              label='',
                                              pos=(130, 310 + 50))
        self.string_price = wx.StaticText(self, label='', pos=(130, 330 + 50))
        self.string_flr_price = wx.StaticText(self,
                                              label='',
                                              pos=(130, 350 + 50))
        self.string_cur_time = wx.StaticText(self,
                                             label='',
                                             pos=(320, 310 + 50))
        self.string_mon_gap = wx.StaticText(self,
                                            label='',
                                            pos=(320, 330 + 50))
        self.string_elp_time = wx.StaticText(self,
                                             label='',
                                             pos=(320, 350 + 50))
        self.string_network = wx.StaticText(self, label='', pos=(130, 310))
        self.string_price_trend = wx.StaticText(self, label='', pos=(320, 310))
        # 创建定时器
        self.timer = wx.Timer(self)  #创建定时器
        self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)  #绑定一个定时器事件
        self.SetSize((500, 480))
        #窗口的颜色
        self.SetBackgroundColour('#DCDCDC')
        #窗口的标题
        self.SetTitle('Huobi Bitcoin price monitor Version 0.1')
        self.Centre()
        self.Show(True)
        #检查网络连接
        if Check_Network() == 1:
            #查询价格,更新文本条
            self.string_price.SetLabel(str(Get_Huobi_Price()))
            self.string_top_price.SetLabel(str(Max_Price))
            self.string_flr_price.SetLabel(str(Min_Price))
            #设置网络状态指示灯为绿色
            self.string_network.SetLabel('ok')
            self.string_price_trend.SetLabel('unknow')
        else:
            self.string_price.SetLabel('0')
            self.string_top_price.SetLabel('0')
            self.string_flr_price.SetLabel('0')
            #设置网络状态指示灯为红色
            self.string_network.SetLabel('error')
            self.string_price_trend.SetLabel('unknow')
        self.string_cur_time.SetLabel(
            time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())))
        self.string_mon_gap.SetLabel(
            str(int(Monitor_Interval / 1000.0)) + ' s')
        initial_time = time.time()
        self.string_elp_time.SetLabel('0.00 mins')
        #绘制曲线相关,先生成画板
        self.fig = Figure(facecolor='#DCDCDC')  #设置背景色
        self.fig.set_figheight(3)  #设置Figure高度
        self.fig.set_figwidth(5)  #设置Figure宽度
        # bind the Figure to the backend specific canvas
        self.canvas = FigureCanvas(self, wx.ID_ANY, self.fig)
        # add a subplot
        self.ax = self.fig.add_subplot(111)
        # limit the X and Y axes dimensions,以当前价格为中心,y_Range之内
        self.ax.set_xlim([0, Curce_Points])
        if y_Range == 1000:
            self.ax.set_ylim([Cur_Price - 500, Cur_Price + 500])
        elif y_Range == 500:
            self.ax.set_ylim([Cur_Price - 250, Cur_Price + 250])
        elif y_Range == 100:
            self.ax.set_ylim([Cur_Price - 50, Cur_Price + 50])
        self.ax.set_autoscale_on(False)
        if Monitor_Interval == 1000 * 30:
            self.ax.set_xticks(np.linspace(0, 600, 7))
            self.ax.set_xticklabels(
                ('300', '250', '200', '150', '100', '50', '0'), fontdict=font1)
        elif Monitor_Interval == 1000 * 10:
            self.ax.set_xticks(np.linspace(0, 600, 5))
            self.ax.set_xticklabels(('100', '75', '50', '25', '0'),
                                    fontdict=font1)
        elif Monitor_Interval == 1000 * 60:
            self.ax.set_xticks(np.linspace(0, 600, 7))
            self.ax.set_xticklabels(
                ('600', '500', '400', '300', '200', '100', '0'),
                fontdict=font1)
        elif Monitor_Interval == 1000 * 60 * 5:
            self.ax.set_xticks(np.linspace(0, 600, 7))
            self.ax.set_xticklabels(
                ('3000', '2500', '2000', '1500', '1000', '500', '0'),
                fontdict=font1)
        if y_Range == 1000:
            self.ax.set_yticks(
                range(Cur_Price - 500 - 1, Cur_Price + 500 + 1, 100))
            tem_array = tuple(
                range(Cur_Price - 500 - 1, Cur_Price + 500 + 1, 100))
        elif y_Range == 500:
            self.ax.set_yticks(
                range(Cur_Price - 250 - 1, Cur_Price + 250 + 1, 50))
            tem_array = tuple(
                range(Cur_Price - 250 - 1, Cur_Price + 250 + 1, 50))
        elif y_Range == 100:
            self.ax.set_yticks(
                range(Cur_Price - 50 - 1, Cur_Price + 50 + 1, 10))
            tem_array = tuple(range(Cur_Price - 50 - 1, Cur_Price + 50 + 1,
                                    10))
        self.ax.set_yticklabels(tem_array, fontdict=font1)
        #曲线图边框的颜色,本程序选择橘黄色
        self.ax.spines['left'].set_color('#FF9000')
        self.ax.spines['right'].set_color('#FF9000')
        self.ax.spines['top'].set_color('#FF9000')
        self.ax.spines['bottom'].set_color('#FF9000')
        #坐标轴刻度朝向,颜色,长度,以及宽度
        self.ax.tick_params(axis='x',
                            direction='in',
                            colors='black',
                            length=4,
                            width=1)
        self.ax.tick_params(axis='y',
                            direction='in',
                            colors='black',
                            length=5,
                            width=1)
        #网格线
        self.ax.grid(True)
        # generates first "empty" plots
        self.user = [None] * Curce_Points
        self.l_user, = self.ax.plot(range(Curce_Points))
        #图例(此处已关闭)
        ###self.l_user,=self.ax.plot(range(Curce_Points),self.user,label='Price curve of Bitcoin')
        ##self.ax.legend(loc='upper center',ncol=4,prop=font_manager.FontProperties(size=9))

        # force a draw on the canvas() trick to show the grid and the legend
        self.canvas.draw()
        # save the clean background - everything but the line is drawn and saved in the pixel buffer background
        self.bg = self.canvas.copy_from_bbox(self.ax.bbox)
        # bind events coming from timer with id = TIMER_ID to the onTimer callback function
        wx.EVT_TIMER(self, TIMER_ID, self.OnTimer)

    def __del__(self):
        pass

    def OnTimer(self, evt):  #显示时间事件处理函数
        global Cur_Price, Max_Price, Min_Price, Price_Log, Counter
        global initial_time, elapsed_time
        global Network_State
        #检查网络状态,只有网络连通了,才调用价格查询子程序
        if Check_Network() == 1:
            Cur_Price = Get_Huobi_Price()
            #网络状态指示灯绿色
            self.string_network.SetLabel('ok')
        else:
            print('no network')
            #网络状态指示灯红色
            self.string_network.SetLabel('error')
        self.string_price.SetLabel(str(Cur_Price))
        self.string_top_price.SetLabel(str(Max_Price))
        self.string_flr_price.SetLabel(str(Min_Price))
        self.string_cur_time.SetLabel(
            time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())))
        self.string_mon_gap.SetLabel(
            str(int(Monitor_Interval / 1000.0)) + ' s')
        elapsed_time = time.time() - initial_time
        self.string_elp_time.SetLabel(
            str(round(elapsed_time / 60, 2)) + ' mins')  # 转换成分钟,保留2位有效数字
        #价格趋势rise或者fall或者unchanged
        if Cur_Price > Price_Log[Counter - 1]:
            self.string_price_trend.SetLabel('rise')
        elif Cur_Price == Price_Log[Counter - 1]:
            self.string_price_trend.SetLabel('unchanged')
        else:
            self.string_price_trend.SetLabel('fall')
        #绘制曲线
        self.canvas.restore_region(self.bg)
        #更新曲线数据
        temp = Cur_Price
        self.user = self.user[1:] + [temp]
        # update the plot
        self.l_user.set_ydata(self.user)
        # just draw the "animated" objects
        self.ax.draw_artist(
            self.l_user
        )  # It is used to efficiently update Axes data (axis ticks, labels, etc are not updated)
        self.canvas.blit(self.ax.bbox)

    def OnPaint(self, event=None):
        dc = wx.PaintDC(self)
        dc.Clear()
        pen = wx.Pen('#808A87', 1, wx.SOLID)  #1表示线宽
        dc.SetPen(pen)
        dc.DrawLine(0, 300, 500, 300)
        dc.SetPen(pen)
        dc.DrawLine(0, 340, 500, 340)

    def OnHide(self, event):
        self.Hide()

    def OnIconfiy(self, event):
        event.Skip()
        self.Hide()

    def OnClose(self, event):
        self.taskBarIcon.Destroy()
        self.Destroy()
示例#15
0
class Graph(wx.BoxSizer):
    """
    This holds a curve plot with associated toolbar
    keyword arguments:
    parent -- reference to the panel or context the plot should be created in.
    orientation -- (optional) wx.BoxSizer style. This also sets the deafult
        direction to expand when adding sub-plots (default: wx.VERTICAL)
    title -- (optional) sets the title of the plot window (default: '').
    dpi -- (optional) sets dots per inch of plot window.
    params -- (optional) set matplotlib rcParams, should be a dictionary.
    (default: sets font size of: ticks, legend, axes label, font)
    **kwargs -- any keyword argument to matplotlib.Figure
    """
    def __init__(self,
                 parent,
                 orientation=wx.VERTICAL,
                 title='',
                 dpi=None,
                 params=None,
                 **kwargs):

        super(Graph, self).__init__(orientation)
        #initialize some font settings for matplotlib
        if params == None:
            params = {
                'axes.labelsize': 16,
                'font.size': 14,
                'legend.fontsize': 14,
                'xtick.labelsize': 12,
                'ytick.labelsize': 12
            }
        matplotlib.rcParams.update(params)

        self.figure = Figure(dpi=dpi, figsize=(2, 2), **kwargs)
        self.canvas = FigureCanvas(parent, wx.NewId(), self.figure)
        self.sub_plots = _plot_list(self.figure)
        self.sub_plots.append(self.figure.add_subplot(111), title)
        self.toolbar = NavigationToolbar2Wx(self.canvas)

        ###Create some extra controls for the toolbar###
        self.cb_grid = wx.CheckBox(self.toolbar, wx.NewId(), 'Show Grid')
        btn_mark = wx.Button(self.toolbar, wx.NewId(), 'Mark selection')
        #btn_rem = wx.Button(parent, wx.NewId(), 'Remove_graph')
        self.cursor_pos = wx.StaticText(
            self.toolbar,
            wx.NewId(),
            'x=0.0000, y=0.0000            ',
            style=wx.ALIGN_RIGHT | wx.ST_ELLIPSIZE_END | wx.ST_NO_AUTORESIZE)

        ####add extra controls to toolbar####
        self.toolbar.AddControl(self.cb_grid)
        self.toolbar.AddControl(btn_mark)
        self.toolbar.AddStretchableSpace()
        self.toolbar.AddControl(self.cursor_pos)
        #self.toolbar.AddStretchableSpace()

        #needed to update the layout
        self.toolbar.Realize()

        #######Main layout#######
        v_sizer = wx.BoxSizer(wx.VERTICAL)
        v_sizer.Add(self.canvas, 1, wx.EXPAND)
        v_sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
        #Add to self
        self.Add(v_sizer, 1, wx.EXPAND)

        ###Set title and other things###
        self.orientation = orientation
        #layout of plots (height, width, count)
        self.layout = (1, 1, 1)
        self.cb_grid.SetValue(True)
        self.sub_plots.show_grid(True)

        #connect the buttons to event handlers
        self.cb_grid.Connect(-1, -1, wx.wxEVT_COMMAND_CHECKBOX_CLICKED,
                             self._on_cb_grid)
        btn_mark.Connect(-1, -1, wx.wxEVT_COMMAND_BUTTON_CLICKED,
                         self._on_mark)
        #btn_rem.Connect(-1, -1, wx.wxEVT_COMMAND_BUTTON_CLICKED, self.on_rem)

        self.canvas.mpl_connect('motion_notify_event',
                                self._UpdateCursorInformation)

    ############Event handlers############
    def _on_cb_grid(self, evt):
        """
        Toggles if grid should be shown on sub-plots
        """
        self.sub_plots.show_grid(self.cb_grid.IsChecked())
        #redraw plots
        self.canvas.draw()

    def _on_mark(self, evt):
        """
        Draws or removes a selection outline on current sub-plot selection
        """
        mark_color = 'k'
        if self.sub_plots.color.lower() == 'black':
            mark_color = 'white'
        if self.sub_plots.has_selection:
            #delete markers
            for sub_plot in self.sub_plots.sub_plots:
                for line in sub_plot.selection:
                    sub_plot.axes.lines.remove(line)
            self.canvas.draw()
        else:
            for i, sub_plot in enumerate(self.sub_plots.sub_plots):
                x1, x2, y1, y2 = sub_plot.axes.axis()
                x = [x1, x2, x2, x1, x1]
                y = [y1, y1, y2, y2, y1]
                sub_plot.selection = self.redraw(x,
                                                 y,
                                                 hold=True,
                                                 limits=(x1, x2, y1, y2),
                                                 index=i,
                                                 color=mark_color,
                                                 linewidth=2.0)
        self.sub_plots.has_selection = not self.sub_plots.has_selection

    def _UpdateCursorInformation(self, evt):
        if evt.inaxes:
            x, y = evt.xdata, evt.ydata
            txt = 'x={0:.4g}, y={1:.4g}'.format(x, y)
            self.cursor_pos.SetLabel(txt)

    ############Worker functions############
    def add_secondary_y_axis(self, label='', index=None):
        """
        Creates a secondary y_axis on the specified sub-plots
        
        keyword arguments:
        label -- (optional) axis label of the second y-axis (default: '')
        index -- (optional) a integer or list of integers with the index of 
            sub-plots for which a secondary y-axis should be created. When 
            'None' the formatter is set for all sub-plots (default: None)
        """

        if type(index) == list:
            for i in index:
                self.sub_plots(i).create_y2_axis(label)
        elif type(index) == int:
            self.sub_plots(index).create_y2_axis(label)
        else:
            #do all
            count = self.layout[-1]
            for sub_plot in self.sub_plots.sub_plots:
                sub_plot.create_y2_axis(label)

    def add_subplot(self, title='', orientation=None):
        """
        Adds an additional subplot. If more than one row exists and it will
        not be filled, than the plots on the last row will be expanded to
        fill all horizontal space. All plots will be recreated
        
        keyword arguments:
        title -- (optional) title text of new subplot (default: '')
        orientation -- (optional) direction to add subplot, valid data is:
            wx.VERTICAL or wx.HORIZONTAL (default: Graph.orientation)
        
        return -- index of created plot
        """

        orientation = self.orientation if orientation == None else orientation
        count = self.layout[-1] + 1
        size = self.layout[0] * self.layout[1]
        #check if there is room for another subplot
        if size >= count:
            self.layout = self.layout[:2] + (count, )
        else:
            #expand layout
            if orientation == wx.VERTICAL:
                self.layout = (self.layout[0] + 1, self.layout[1], count)
            else:
                self.layout = (self.layout[0], self.layout[1] + 1, count)

        #Clear away old axes
        self.sub_plots.clear_axes()
        #recreate axes and add new one
        size = self.layout[0] * self.layout[1]
        for i in range(1, count + 1):
            if count < size and i > self.layout[1] * (self.layout[0] - 1):
                #expand graphs on last row
                exp_layout = (self.layout[0], self.layout[1] - (size - count))
                exp_i = exp_layout[0] * exp_layout[1] - (count - i)

                axes = self.figure.add_subplot(*exp_layout + (exp_i, ))
                #check if to rebind axes or append new object
                if i == count:
                    self.sub_plots.append(axes, title)
                else:
                    self.sub_plots.set_axes(axes, i - 1)
            else:
                axes = self.figure.add_subplot(*self.layout[:2] + (i, ))
                #check if to rebind axes or append new object
                if i == count:
                    self.sub_plots.append(axes, title)
                else:
                    self.sub_plots.set_axes(axes, i - 1)

        self.canvas.draw()
        #return sub-plot index
        return count - 1

    def cleanse_fontcache(self):
        """
        Shouldn't be used. Can fix bug when using frozen programs under windows.
        Better to modify the setup script so that font files are left out of the
        matplotlib data files.
        """
        file_path = path.join(path.expanduser('~'), \
                    '.matplotlib', \
                    'fontList.cache')
        if path.exists(file_path):
            remove(file_path)

    def clear_lines(self, index=0):
        """
        Removes all lines from the selected sub-plot
        
        keyword arguments:
        index -- (optional) index of subplot, which should be cleared from all
            lines (default: 0)
        """
        self.sub_plots(index).axes.cla()
        self.sub_plots(index).lines = []

    def get_lines(self, index=0):
        """
        Retrieves all the lines of the specified sub-plot
        
        keyword arguments:
        index -- (optional) index of subplot from, which the lines should be
            retrieved from (default: 0)
        """
        return self.sub_plots(index).axes.get_lines()

    def redraw(self,
               x,
               y,
               index=0,
               hold=False,
               xmin=None,
               ymin=None,
               limits=None,
               limit_selector=None,
               alpha=1.0,
               draw=True,
               **kwarg):
        """
        Updates plot with new vectors
        keyword arguments:
        x -- the x-axis values
        y -- the y-axis values
        index -- (optional) index of subplot to plot the vector in (default: 0)
        hold -- (optional) should old vectors be kept (default: False)
        xmin -- (optional) set minimum value of x-axis (default: None)
        ymin -- (optional) set minimum value of y-axis (default: None)
        limits -- (optional) list to set the limits of x and y-axis. overrides
            the xmin and ymin arguments (default: None)
        limit_selector -- (optional) a fucntion which given the arguments:
            *(x1, x2, y1, y2) will return a list with the axis limits
            overrides the xmin, ymin and the limits argument (default: None)
            e.g. sel = lambda x1, x2, y1, y2: [x1, x2, min(y1, 0), y2]
        alpha -- (optional) sets the alpha of the line (default: 1.0)
        draw -- (optional) should the canvas be updated to show the new lines
        
        **kwarg -- all extra keyword arguments are sent to the plot function
        """
        #set plot to update
        try:
            plot = self.sub_plots(index)
        except IndexError:
            raise (IndexError,
                   "The sub-plot of index:{0:d} doesn't exist".format(index))

        plot.axes.hold(hold)
        lines = plot.axes.plot(x, y, alpha=alpha, **kwarg)

        #Create a legend if label was given
        if not lines[0].get_label()[0] == "_":
            plot.axes.legend()  #label must be sent through kwarg

        #if not ymin == None:
        x1, x2, y1, y2 = plot.axes.axis()
        ymin = y1 if ymin == None else ymin
        xmin = x1 if xmin == None else xmin
        plot.axes.axis([xmin, x2, ymin, y2])
        if not limits == None:
            plot.axes.axis(limits)
        if not limit_selector == None:
            plot.axes.axis(limit_selector(x1, x2, y1, y2))

        #plot it
        #plot.axes.grid(self.sub_plots.grid)
        plot.reload()
        if draw:
            self.canvas.draw()
        #store lines in a list
        #return line object
        #plot.lines.extend(lines)
        return lines

    def redraw_secondary_y(self, x, y, index=0, **kwarg):
        """
        Update secondary y-axis with a new vector
        keyword arguments:
        x -- the x-axis values
        y -- the y-axis values
        index -- (optional) index of subplot to plot the vector in (default: 0)
        style -- (optional) line style (default: 'r.')
        **kwarg -- all extra keyword arguments are sent to the plot function
        """
        sub_plot = self.sub_plots(index)
        lines = sub_plot.y2_axis.plot(x, y, style, **kwarg)
        #show it
        self.canvas.draw()
        return lines

    def remove_lines(self, lines, index=0):
        """
        Re
        
        keyword arguments:
        lines -- A list of matplotlib lines as given by the redraw function
        index -- (optional) index of subplot from, which the lines should be
            retrieved from (default: 0)
        """
        for line in lines:
            self.sub_plots(index).remove_line(line)
        self.canvas.draw()

    def remove_subplot(self):
        """
        Removes the last sub-plot.
        Note that plots in the last row aren't expanded to fill the entire row.
        """
        count = self.layout[-1] - 1
        if count < 0:
            raise ValueError, "There is no sub-plot to remove"

        self.layout = (self.layout[0], self.layout[1], count)

        if count > 0:
            layout_change = True
            #check if layout of plots can be decreased
            if self.layout[0] > 1 and self.layout[1] > 1:
                if self.layout[0] < self.layout[1]:
                    lrg = 1
                    sml = 0
                else:
                    lrg = 0
                    sml = 1
                #check if a decrease is possible on the major axis
                size = (self.layout[lrg] - 1) * (self.layout[sml])
                if size >= count:
                    if lrg == 0:
                        self.layout = (self.layout[0] - 1, self.layout[1],
                                       count)
                    else:
                        self.layout = (self.layout[0], self.layout[1] - 1,
                                       count)
                else:
                    #check the minor axis
                    size = (self.layout[lrg]) * (self.layout[sml] - 1)
                    if size >= count:
                        if sml == 0:
                            self.layout = (self.layout[0] - 1, self.layout[1],
                                           count)
                        else:
                            self.layout = (self.layout[0], self.layout[1] - 1,
                                           count)
                    else:
                        layout_change = False
            else:
                if self.layout[0] > self.layout[1]:
                    self.layout = (self.layout[0] - 1, self.layout[1], count)
                else:
                    self.layout = (self.layout[0], self.layout[1] - 1, count)
        else:
            layout_change = False

        #remove the last sub-plot
        self.sub_plots.remove()
        if layout_change:
            #clear figure and recreate plots
            self.sub_plots.clear_axes()

            for i in range(1, count + 1):
                plot_index = i - 1
                self.sub_plots.set_axes(
                    self.figure.add_subplot(*self.layout[:2] + (i, )),
                    plot_index)

        #redraw screen
        self.canvas.draw()

    def set_formatter(self,
                      frmt='sci',
                      axes='all',
                      useOffset=True,
                      limits=(-3, 3),
                      index=None):
        """
        Sets the formatter of the axes. Default is to set scientific notation
        for all axes of all subplots.
        
        keyword arguments:
        frmt -- Sets the type of formatter used, valid values are:
            'sci', 'log', 'plain' (default: 'sci')
        axes -- which axes should the formatter be used for, valid values are:
            'all', 'x', 'y' (default: 'all')
        useOffset -- Should offset be used to make the tickers more meaningful 
            (default: True)
        limits -- Limits for scientific notation as a tuple (default: (-3, 3))
        index -- a integer or list of integers with the index of sub-plots for
            which the formatter should set. When 'None' the formatter is set
            for all sub-plots (default: None)
        """

        frmt = frmt.lower()
        axes = axes.lower()

        if frmt == 'log':
            formatter = LogFormatter()
        else:
            sci = frmt == 'sci'
            formatter = ScalarFormatter(useOffset=useOffset)
            formatter.set_powerlimits(limits)
            formatter.set_scientific(sci)

        # format axes
        if type(index) == list:
            for i in index:
                self.sub_plots(i).set_formatter(formatter, axes)
        elif type(index) == int:
            self.sub_plots(index).set_formatter(formatter, axes)
        else:
            # do all
            for sub_plot in self.sub_plots.sub_plots:
                sub_plot.set_formatter(formatter, axes)
            #set default formatter
            self.sub_plots.set_default_formatter(formatter, axes)

        # redraw screen
        self.canvas.draw()

    def set_label(self, xlabel='', ylabel='', index=None):
        """
        Set labels of the specified plot axes
        
        keyword arguments:
        xlabel -- (optional) sets the label of the x-axis (default: '')
        ylabel -- (optional) sets the label of the y-axis (default: '')
        index -- (optional) a integer or list of integers with the index of 
            sub-plots for which a the labels should be set. When 'None' the
            labels is set for all sub-plots (default: None)
        """

        if type(index) == list:
            for i in index:
                self.sub_plots.set_label(xlabel, ylabel, i)
        elif type(index) == int:
            self.sub_plots.set_label(xlabel, ylabel, index)
        else:
            # do all
            count = self.layout[-1]
            for i in range(count):
                self.sub_plots.set_label(xlabel, ylabel, i)
        # Redraw screen
        self.canvas.draw()

    def set_limits(self, limits, index=0):
        """
        Sets the axis limits of the specified sub-plot
        
        keyword arguments:
        limits -- A list to set the limits of x and y-axis: [x1, x2, y1, y2]
        index -- (optional) index of subplot to set axis limits (default: 0)
        """
        self.sub_plots(index).axes.axis(limits)
        self.canvas.draw()

    def set_title(self, titles='', index=0):
        """
        Set titles of the sub-plots
        
        keyword arguments:
        titles -- should be a list of title strings or a single
            string, in which case an index should be supplied (default: '')
        index -- (optional) Is only needed when titles is a single string
            specifies for which sub-plot to set the title
        """
        if type(titles) == list:
            for i, title in enumerate(titles):
                self.sub_plots(i).set_title(title)
        else:
            self.sub_plots(index).set_title(titles)

        self.canvas.draw()

    def update(self):
        """
        Will send a draw command to the canvas uppdating the graphs
        """
        self.canvas.draw()
        self.canvas.flush_events()

    def update_plot_only(self, lines, index=0):
        """
        Will redraw the background and plot lines only
        
        keyword arguments:
        lines -- a list of line objects for the plot
        index -- (optional) index of subplot to set axis limits (default: 0)
        """
        try:
            plot = self.sub_plots(index)
        except IndexError:
            raise (IndexError,
                   "The sub-plot of index:{0:d} doesn't exist".format(index))
        ax = plot.axes
        #draw the background
        ax.draw_artist(ax.patch)
        #draw the lines
        for line in lines:
            ax.draw_artist(line)
        #draw the x grid
        for line in ax.get_xgridlines():
            ax.draw_artist(line)
        #draw the y grid
        for line in ax.get_ygridlines():
            ax.draw_artist(line)
        #redraw display selectively
        self.canvas.blit(ax.bbox)
示例#16
0
class PlotPanel(wx.Panel):
    def __init__(self, parent, statusbar):
        wx.Panel.__init__(self, parent, -1, size=(50, 50))
        self.statusbar = statusbar

        self.plot_handl = None
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self.sizer)

        self.figure = Figure(None, dpi=300)
        self.ax = self.figure.add_axes([0, 0, 1, 1],
                                       frameon=False,
                                       projection=ccrs.PlateCarree())
        self.canvas = PlotFigureCanvas(self, -1, self.figure)
        self.toolbar = PlotToolbar(self.canvas, self)

        self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
        self.sizer.Add(self.toolbar, 0, wx.EXPAND)

        # Clear artifacts
        self.clear_artifacts()

        # Bind events
        self.figure.canvas.mpl_connect('button_release_event', self.onclick)
        self.ax.callbacks.connect('xlim_changed', self.on_xlims_change)
        self.ax.callbacks.connect('ylim_changed', self.on_ylims_change)

        # setup empty list of meridians and parallels
        self.meridians_w = {}
        self.meridians_b = {}
        self.parallels_w = {}
        self.parallels_b = {}

        self.labels = []

        self.nlons = NUM_GRID_LINES
        self.nlats = NUM_GRID_LINES
        self.lons = []
        self.lats = []
        self.latll = -90
        self.latur = 90
        self.lonll = -180
        self.lonur = 180

        self.motion_display_font = FontProperties()
        self.motion_display_font.set_size(MOTION_DISPLAY_FONT_SIZE)
        self.motion_display_font.set_family('monospace')

        self.grid_label_font = FontProperties()
        self.grid_label_font.set_size(GRID_LABEL_FONT_SIZE)
        self.grid_label_font.set_family('monospace')

        self.map = None
        self.motion_display = None

        self._rc_zoomed = False

        self.cursor_coordinates_enabled = True
        self.coordinate_grid_enabled = True
        self.grid_labels_enabled = True

    def set_cursor_coordinates_enabled(self, enabled):
        self.cursor_coordinates_enabled = enabled

        # apply immediately
        if not enabled:
            if self.motion_display:
                self.motion_display.remove()
                self.figure.canvas.draw()
            self.motion_display = None

    def set_coordinate_grid_enabled(self, enabled):
        self.coordinate_grid_enabled = enabled

    def set_grid_labels_enabled(self, enabled):
        self.grid_labels_enabled = enabled

    def on_xlims_change(axes):
        pass

    def on_ylims_change(axes):
        pass

    def on_mouse_move(self, event):
        if not self.map:
            return
        lon, lat = self.map(event.xdata, event.ydata, inverse=True)
        lonll = max(self.lonll, self.map.llcrnrlon)
        lonur = min(self.lonur, self.map.urcrnrlon)
        latll = max(self.latll, self.map.llcrnrlat)
        latur = min(self.latur, self.map.urcrnrlat)
        if lat >= latll and lat <= latur and \
                lon >= lonll and lon <= lonur and \
                self.map.projection == 'cyl' and \
                self.cursor_coordinates_enabled:
            if self.motion_display is None:
                # setup coordinate display for mouse motion
                self.motion_display = self.ax.annotate(
                    s="(NaN, NaN)",
                    xy=(0.995, 0.995),
                    xycoords='axes fraction',
                    fontproperties=self.motion_display_font,
                    verticalalignment='top',
                    horizontalalignment='right',
                    bbox=dict(facecolor='white', alpha=1.0, pad=0.2, lw=0.2))

            display_lon = self.wrap_lon_at_day_boundary(lon)
            self.motion_display.set_text('(%+10.5f,%+10.5f)' %
                                         (display_lon, lat))
            self.ax.draw_artist(self.motion_display)
            self.canvas.blit(self.motion_display.get_window_extent())
        else:
            if self.motion_display:
                self.motion_display.remove()
                self.figure.canvas.draw()
            self.motion_display = None

    def wrap_lon_at_day_boundary(self, lon):
        wrapped_lon = lon
        while wrapped_lon < -180:
            wrapped_lon += 360.0
        while wrapped_lon > 180:
            wrapped_lon -= 360.0
        return wrapped_lon

    def do_dynamic_update(self):
        if not self.map:
            return

        # update meridians
        self._plot_meridians_and_parallels()
        self.figure.canvas.draw()

    def set_right_click_zoomed(self):
        self._rc_zoomed = True

    def onclick(self, event):
        if event is None or event.button != 3 or not event.inaxes:
            return
        if self._rc_zoomed:
            self._rc_zoomed = False
            return
        self.click_event = event
        menu = wx.Menu()
        menu.Append(wx.ID_ANY, "Add Point Here",
                    "Adds a point where the mouse was clicked on the map",
                    wx.ITEM_NORMAL)
        self.Bind(wx.EVT_MENU, self.callback, id=wx.ID_ANY)
        if self.canvas.HasCapture():
            self.canvas.ReleaseMouse()
        wx.CallAfter(self.PopupMenu, menu)

    def callback(self, event):
        self.map.plot(self.click_event.xdata,
                      self.click_event.ydata,
                      'r.',
                      markersize=1.)
        self.figure.canvas.draw()

    def clear_artifacts(self):
        for artifact in ['artists', 'lines', 'patches']:
            while getattr(self.ax, 'artists') != []:
                getattr(self.ax, 'artists')[0].remove()
        self.artifacts = {'artists': [], 'lines': [], 'patches': []}

    def updatePlot(self, attrs):

        self.statusbar.SetStatusText('Plotting... (Please Be Patient)')
        self.ax.clear()
        self.plot(attrs)
        self.statusbar.SetStatusText('Ready')

    def plot(self, param):
        # Create Map
        if not param:
            self.ax.stock_img()
            self.figure.canvas.draw()

            # # Create a really simple plot to fill the void on app startup.
            # self.map = Basemap(ax=self.ax, resolution=RESOLUTION_MAP['Crude'],
            #                    ellps='WGS84', suppress_ticks=True)
            # self.map.bluemarble()
            # self._plot_meridians_and_parallels()

            # # add the motion display to the list of texts for the new axes
            # if self.motion_display:
            #     self.ax.texts.append(self.motion_display)
            # self.figure.canvas.draw()
            return

        # projection_name = param['Projection']
        # projection_key = revlookup(PROJECTIONS, 'name', projection_name)
        # resolution = RESOLUTION_MAP[param['Resolution']]
        # kwargs = {'projection': projection_key,
        #           'ellps': 'WGS84',
        #           'suppress_ticks': True,
        #           'ax': self.ax,
        #           'resolution': resolution}
        # for p in PROJECTION_PARAMS[projection_key].keys():
        #     if 'rspherex' == p:
        #         kwargs['rsphere'] = (param[OPTIONS['rspherex']['name']],
        #                              param[OPTIONS['rspherey']['name']])
        #     elif 'rspherey' == p:
        #         pass
        #     else:
        #         kwargs[p] = param[OPTIONS[p]['name']]
        # self.map = Basemap(**kwargs)

        # # Draw Circle
        # self.draw_range_circle(param["longitude"],
        #                        param["geodetic_latitude"],
        #                        param["range"],
        #                        color='r',
        #                        alpha=0.5)

        # # Draw Blue Marble Texture
        # if param.get('Blue Marble', False):
        #     self.map.bluemarble()
        # else:
        #     self.map.fillcontinents(color='coral', lake_color='aqua')

        # # Draw Coastlines, borders, lines
        # if param.get('Coastlines', False):
        #     self.map.drawcoastlines()
        # if param.get('State Borders', False):
        #     self.map.drawstates()
        # if param.get('Country Borders', False):
        #     self.map.drawcountries()
        # self._plot_meridians_and_parallels()

        # # add the motion display to the list of texts for the new axes
        # if self.motion_display:
        #     self.ax.texts.append(self.motion_display)

        # self.figure.canvas.draw()

    def draw_great_circle(self, x1, y1, x2, y2, linewidth=.5, color='r'):
        self.map.drawgreatcircle(x1, y1, x2, y2, linewidth, color)

    def draw_text(self,
                  text,
                  x,
                  y,
                  xycoords='data',
                  color='white',
                  size='xx-small'):
        self.ax.add_artist(
            AnnotationBbox(TextArea(text,
                                    minimumdescent=False,
                                    textprops={
                                        'color': color,
                                        'size': size
                                    })(x, y),
                           xycoords='data',
                           frameon=False))

    def draw_image(self, image, x, y, zoom=.1, alpha=.7, xycoords='data'):
        if isinstance(image, PyEmbeddedImage):
            png = pyembeddedimage_to_png(image)
        elif isinstance(image, basestring):
            png = read_png(image)
        else:
            png = image
        self.ax.add_artist(
            AnnotationBbox(OffsetImage(png, zoom=zoom, alpha=alpha), (x, y),
                           xycoords=xycoords,
                           frameon=False))

    def draw_range_circle(self, lat, lon, radius, color='r', alpha=.5):
        # FIXME Use the real radius of the earth at this lat/lon
        self.map.tissot(lon,
                        lat,
                        180. / pi * radius / 6370.,
                        256,
                        facecolor=color,
                        alpha=alpha)

    def _plot_meridians_and_parallels(self):
        """
        Plots meridians and parallels appropriate for the current zoom level
        """

        # if grid is off and labels are off wipe lines
        if not self.coordinate_grid_enabled and not self.grid_labels_enabled:
            self._label_grid([], [])
            self._clear_meridians_and_parallels()
            return

        # FIXME: Get this working for other projections
        if self.map.projection != 'cyl':
            self._clear_meridians_and_parallels()

            # FIXME: Make it an option to turn on/off white or black lines
            if self.coordinate_grid_enabled:
                lats = np.linspace(-90, 90, 10)
                self.parallels_b = self.map.drawparallels(
                    lats,
                    labels=[True, False, False, False],
                    fontsize=GRID_LABEL_FONT_SIZE,
                    linewidth=0.2,
                    dashes=[],
                    color='black')
                self.parallels_w = self.map.drawparallels(
                    lats,
                    labels=[False, False, False, False],
                    linewidth=0.2,
                    dashes=[1, 1],
                    color='white')
                lons = np.linspace(-180, 180, 10)
                self.meridians_b = self.map.drawmeridians(
                    lons,
                    labels=[False, False, False, True],
                    fontsize=GRID_LABEL_FONT_SIZE,
                    linewidth=0.2,
                    dashes=[],
                    color='black')
                self.meridians_w = self.map.drawmeridians(
                    lons,
                    labels=[False, False, False, False],
                    linewidth=0.2,
                    dashes=[1, 1],
                    color='white')

            self._label_grid(lons, lats)
            return

        # get the corners of the viewport
        self.lonll, self.latll, delta_lon, delta_lat = self.ax.viewLim.bounds
        self.latur = self.latll + delta_lat
        self.lonur = self.lonll + delta_lon

        # translate to lat/lon (if needed)
        self.lonll, self.latll = self.map(self.lonll, self.latll, inverse=True)
        self.lonur, self.latur = self.map(self.lonur, self.latur, inverse=True)

        if not self._zoom_is_valid():
            return

        # get the range of lat/lon of the current viewport
        lat_range = self.latur - self.latll
        lon_range = self.lonur - self.lonll

        # get the estimated number of parallels and meridians to plot
        nlons = round(NUM_GRID_LINES * 360.0 / lon_range)
        nlats = round(NUM_GRID_LINES * 180.0 / lat_range)

        found = False
        for kv in LAT_GRID_LOOKUP:
            if nlats <= kv[0]:
                self.nlats = kv[1]
                found = True
                break
        if not found:
            self.nlats = self._scale_grid_by_twos(nlats, self.nlats)

        found = False
        for kv in LON_GRID_LOOKUP:
            if nlons <= kv[0]:
                self.nlons = kv[1]
                found = True
                break
        if not found:
            self.nlons = self._scale_grid_by_twos(nlons, self.nlons)

        # return if we've got too few to plot
        if self.nlons <= 1 or self.nlats <= 1:
            return

        # calculate the actual meridian coordinates
        lons = np.linspace(-180, 180.0, self.nlons)
        lons = np.concatenate((lons - 360.0, lons, lons + 360.0))
        lats = np.linspace(-90.0, 90.0, self.nlats)

        # filter them to speed plotting
        lon_condition = lons >= self.lonll
        lons = np.extract(lon_condition, lons)
        lon_condition = lons <= self.lonur
        lons = np.extract(lon_condition, lons)

        lat_condition = lats >= self.latll
        lats = np.extract(lat_condition, lats)
        lat_condition = lats <= self.latur
        lats = np.extract(lat_condition, lats)

        # plot labels for each one
        self._label_grid(lons, lats)

        self.lats = lats
        self.lons = lons

        # plot new parallels/meridians
        # these are made up of a solid black line, and a dashed white line
        self._clear_meridians_and_parallels()

        # FIXME: Make it an option to turn on/off white or black lines
        if self.coordinate_grid_enabled:
            self.parallels_b = self.map.drawparallels(
                lats,
                labels=[False, False, False, False],
                linewidth=0.2,
                dashes=[],
                color='black')
            self.parallels_w = self.map.drawparallels(
                lats,
                labels=[False, False, False, False],
                linewidth=0.2,
                dashes=[1, 1],
                color='white')
            self.meridians_b = self.map.drawmeridians(
                lons,
                labels=[False, False, False, False],
                linewidth=0.2,
                dashes=[],
                color='black')
            self.meridians_w = self.map.drawmeridians(
                lons,
                labels=[False, False, False, False],
                linewidth=0.2,
                dashes=[1, 1],
                color='white')

    def _label_grid(self, lons, lats):
        """
        Plots labels on grid lines.
        """
        degree_sign = u'\N{DEGREE SIGN}'
        for label in self.labels:
            if label in self.ax.texts:
                label.remove()
        self.labels = []

        if self.grid_labels_enabled:

            # peg the corners on the projection boundaries
            lonll = max(self.lonll, self.map.llcrnrlon)
            lonur = min(self.lonur, self.map.urcrnrlon)
            latll = max(self.latll, self.map.llcrnrlat)
            latur = min(self.latur, self.map.urcrnrlat)

            for lat in lats:
                if lat > latur or lat < latll:
                    continue
                if lat >= 0:
                    NS = 'N'
                else:
                    NS = 'S'
                (d, m, sd) = self._to_dms(lat)
                self.labels.append(
                    self.ax.text(lonll,
                                 lat,
                                 "%02d%s%02d'%05.2f\"%s" %
                                 (abs(d), degree_sign, m, sd, NS),
                                 fontproperties=self.grid_label_font,
                                 verticalalignment='center',
                                 horizontalalignment='left',
                                 bbox=dict(facecolor='white',
                                           alpha=0.5,
                                           pad=0.2,
                                           lw=0.2)))

            for lon in lons:
                if lon > lonur or lon < lonll:
                    continue

                # normalize
                display_lon = self.wrap_lon_at_day_boundary(lon)
                if display_lon >= 0:
                    NS = 'E'
                else:
                    NS = 'W'
                (d, m, sd) = self._to_dms(display_lon)
                self.labels.append(
                    self.ax.text(lon,
                                 latll,
                                 "%03d%s%02d'%05.2f\"%s" %
                                 (abs(d), degree_sign, m, sd, NS),
                                 fontproperties=self.grid_label_font,
                                 rotation='vertical',
                                 verticalalignment='bottom',
                                 horizontalalignment='center',
                                 bbox=dict(facecolor='white',
                                           alpha=0.5,
                                           pad=0.2,
                                           lw=0.2)))

    def _to_dms(self, deg):
        """
        Converts degrees to degrees minutes seconds
        """
        d = int(deg)
        md = abs(deg - d) * 60.0
        m = int(md)
        sd = (md - m) * 60.0
        return [d, m, sd]

    def _scale_grid_by_twos(self, n_target, n_current):
        """
        Determines number of grid lines to plot via hopping by powers of 2
        """
        half_n_current = int(n_current / 2.0) + 1
        twice_n_current = round(n_current * 2) - 1
        if n_target < n_current and n_target > 1:
            while n_target < n_current:
                n_current = half_n_current
                half_n_current = int(n_current / 2.0) + 1
                if n_current < 3:
                    break
        else:
            while n_target >= twice_n_current:
                n_current = twice_n_current
                twice_n_current = round(n_current * 2) - 1

        # should be an odd number at this point, but make sure
        if n_current % 2 == 0:
            n_current += 1

        return n_current

    def _zoom_is_valid(self):
        """
        Checks if zoom level is valid
        """
        # check if corners are valid
        try:
            delta_lon = self.lonur - self.lonll
            delta_lat = self.latur - self.latll
        except:
            return False
        return True

    def _clear_meridians_and_parallels(self):
        """
        Clears currently plotted meridians and parallels
        """
        # clear old meridians and parallels
        # these are made up of a solid black line, and a dashed white line
        for par in self.parallels_w:
            for item in self.parallels_w[par]:
                if len(item) > 0:
                    if item[0] in self.ax.lines:
                        item[0].remove()
        self.parallels_w.clear()

        for par in self.parallels_b:
            for item in self.parallels_b[par]:
                if len(item) > 0:
                    if item[0] in self.ax.lines:
                        item[0].remove()
        self.parallels_b.clear()

        for mer in self.meridians_w:
            for item in self.meridians_w[mer]:
                if len(item) > 0:
                    if item[0] in self.ax.lines:
                        item[0].remove()
        self.meridians_w.clear()

        for mer in self.meridians_b:
            for item in self.meridians_b[mer]:
                if len(item) > 0:
                    if item[0] in self.ax.lines:
                        item[0].remove()
        self.meridians_b.clear()
示例#17
0
class MyPlot(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self,parent, -1)
    
        self.fig = None
        self.canvas = None
        self.ax = None
        self.background = None
        self.lines = []
        self._doRePlot = True
                
        
        self.foo = 1
        self.t = time.time()
        self.blit_time=0
        self.y = numpy.cos(numpy.arange(0.0,1.0,0.1))
                
        self.ylim = None
        self.autolim = None
        self.span = 500
        self.begin = 0
        self.channels = []
        
        self._SetSize()
        
        self.Bind(wx.EVT_IDLE, self._onIdle)
        self.Bind(wx.EVT_SIZE, self._onSize)
        self._resizeFlag = True
        
        sizer=wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.canvas,1,wx.GROW)
        self.SetSizer(sizer)
        self.canvas.Show() 
    
    def addChannel(self, channel):
        self.channels.append(channel)
        
    def setTimespan(self, span):
        self.span = span
        
    def setYlim(self, ymin, ymax):
        self.ylim = [ymin, ymax]
        
    def _resizeCreateContent(self):
        '''Resize graph according to user input and initialize plots'''
        
        self.lines=[]        
        for c in self.channels:
            data=c.getNext()
            line, = self.ax.plot(data[0],data[1], animated = True)
            self.lines.append(line)
        gca = self.fig.gca()
        #TODO: add an auto mode here
        if self.ylim:
            gca.set_ylim(self.ylim)
        else:
            if self.autolim:
                diff = self.autolim[1] - self.autolim[0]
                gca.set_ylim([self.autolim[0] - 0.1*diff, self.autolim[1] + 0.1*diff])
            else:
                gca.set_ylim([-1,1])
        gca.set_xlim([self.begin, (self.begin+self.span)])
        self.ax.grid()
        #self.fig.clear()
        
        self.canvas.draw()        
        self.background = None
        print 'content'
        self._doRePlot = False
        
        
    def _createGraphics(self):
        """Reallocate new figure and take care of panel resizing issues"""
        self.fig=Figure()
        self.canvas=FigureCanvas(self,-1,self.fig)
        self.ax = self.fig.add_subplot(111)
        
        self.ax._cachedRenderer=self.canvas.get_renderer()
        
    def _onSize(self, evt):
        self._resizeFlag = True
        
    def _onIdle(self, event):
        event.RequestMore(True)
        if self._resizeFlag:
            self._resizeFlag = False
            self._SetSize()
        self.draw_plot()
        #if self.foo > 2000:
            #u=time.time()
            #print self.foo/(u-self.t), self.blit_time/(u-self.t)
            #exit(0)

    def _SetSize(self, pixels=None):
        if not pixels:
            pixels = self.GetClientSize()
        self._createGraphics()
        self.canvas.SetSize(pixels)
        
        self.fig.set_size_inches(pixels[0]/self.fig.get_dpi(),
        pixels[1]/self.fig.get_dpi(), forward=True)
        self._doRePlot = True
       
    def draw_plot(self):
                if self._doRePlot:
                    self._resizeCreateContent()
                if self.background is None:
                    self.background = self.canvas.copy_from_bbox(self.ax.bbox)
                self.foo += 1
                #self.y = numpy.cos(numpy.arange(0.0,1.0,0.1)+self.foo*0.1)
                # Optimization on the blitting: we compute the box where the changes happen
                changes_box = None

                for i in range(len(self.lines)):
                    data=self.channels[i].getNext()
                    
                    if len(data[1])>0:
                        if self.autolim:
                            print self.autolim[0], data[1], self.autolim[1]
                            self.autolim = [ min(self.autolim[0], min(data[1])), \
                                max(self.autolim[1], max(data[1])) ]
                        else:
                            self.autolim = [ min(data[1]), min(data[1]) ]
                        
                        if changes_box is None:
                            changes_box = Bbox.unit()
                        print '>>>>>>>>'
                        print data[0], data[1]
                        changes_box.update_from_data(numpy.array(data[0]), \
                                numpy.array(data[1]), ignore=changes_box.is_unit())
                        
                        if not self._doRePlot and len(data[0]) > 0 :
                            end = data[0][-1]
                            
                            if end > self.begin+self.span:
                                self.begin += self.span
                                self._doRePlot = True
                                print 'do replot'
                        self.lines[i].set_data(data[0], data[1])
                    else:
                        self.lines[i].set_data([], [])
                
                if not changes_box:
                    return
                #self.canvas.restore_region(self.background)
                for line in self.lines:
                    self.ax.draw_artist(line)
                    #print line.get_transform()
                    tr = line.get_transform()
                    
                changes_box_inframe = changes_box.transformed(tr)
                
                box_padding = 5
                (x,y,l,w) = changes_box_inframe.bounds
                changes_box_inframe = Bbox.from_bounds(x-box_padding, \
                    y-box_padding, l+2*box_padding, w+2*box_padding)
                
                #print 
                t0 = time.time()
                self.canvas.blit(None)
                #self.canvas.blit(changes_box_inframe)
                self.blit_time += time.time() - t0
示例#18
0
class wxpygui_frame(wx.Frame):
    """The main gui frame."""
    def __init__(self, tb):
        wx.Frame.__init__(self, parent=None, id=-1, title="gr-analyzer")
        self.tb = tb

        self.min_power = -120  # dBm
        self.max_power = 0  # dBm

        self.init_mpl_canvas()
        self.x = None  # set by configure_mpl_plot

        # Setup a threshold level at None
        self.threshold = threshold.threshold(self, None)

        # Init markers (visible=False)
        self.mkr1 = marker.marker(self, 1, '#00FF00',
                                  'd')  # thin green diamond
        self.mkr2 = marker.marker(self, 2, '#00FF00',
                                  'd')  # thin green diamond

        # init control boxes
        self.gain_ctrls = gain.ctrls(self)
        self.threshold_ctrls = threshold.ctrls(self)
        self.mkr1_ctrls = marker.mkr1_ctrls(self)
        self.mkr2_ctrls = marker.mkr2_ctrls(self)
        self.res_ctrls = resolution.ctrls(self)
        self.windowfn_ctrls = window.ctrls(self)
        self.lo_offset_ctrls = lotuning.ctrls(self)
        self.nframes_ctrls = nframes.ctrls(self)
        self.tune_delay_ctrls = tune_delay.ctrls(self)
        self.frequency_ctrls = frequency.ctrls(self)
        self.span_ctrls = span.ctrls(self)
        self.trigger_ctrls = trigger.ctrls(self)
        self.power_ctrls = power.ctrls(self)
        self.export_ctrls = export.ctrls(self)
        self.detector_ctrls = detector.ctrls(self)
        self.scale_ctrls = scale.ctrls(self)

        self.set_layout()

        self.logger = logging.getLogger('gr-analyzer.wxpygui_frame')

        # gui event handlers
        self.Bind(wx.EVT_CLOSE, self.close)
        self.Bind(wx.EVT_IDLE, self.idle_notifier)

        self.canvas.mpl_connect('button_press_event', self.on_mousedown)
        self.canvas.mpl_connect('button_release_event', self.on_mouseup)

        self.plot_background = None

        # Used to peak search within range
        self.span = None  # the actual matplotlib patch
        self.span_left = None  # left bound x coordinate
        self.span_right = None  # right bound x coordinate

        self.last_click_evt = None

        self.closed = False

        # Used to increment file numbers
        self.fft_data_export_counter = 0
        self.time_data_export_counter = 0

        ####################
        # GUI Sizers/Layout
        ####################

    def set_layout(self):
        """Setup frame layout and sizers"""
        # front panel to hold plot and control stack side-by-side
        frontpanel = wx.BoxSizer(wx.HORIZONTAL)

        # control stack to hold control clusters vertically
        controlstack = wx.BoxSizer(wx.VERTICAL)

        # first cluster - usrp state

        usrpstate_outline = wx.StaticBox(self, wx.ID_ANY, "USRP State")
        usrpstate_cluster = wx.StaticBoxSizer(usrpstate_outline, wx.HORIZONTAL)

        usrpstate_row1 = wx.BoxSizer(wx.HORIZONTAL)
        usrpstate_row1.Add(self.trigger_ctrls.layout, flag=wx.ALL, border=5)
        usrpstate_row1.Add(self.detector_ctrls.layout, flag=wx.ALL, border=5)
        usrpstate_row1.Add(self.gain_ctrls.layout, flag=wx.ALL, border=5)
        usrpstate_row1.Add(self.lo_offset_ctrls.layout, flag=wx.ALL, border=5)

        usrpstate_row2 = wx.BoxSizer(wx.HORIZONTAL)
        usrpstate_row2.Add(
            self.frequency_ctrls.layout,
            proportion=1,
            flag=wx.ALL,  #|wx.EXPAND,
            border=5)
        usrpstate_row2.Add(
            self.span_ctrls.layout,
            proportion=1,
            flag=wx.ALL,  #|wx.EXPAND,
            border=5)
        usrpstate_row2.Add(
            self.scale_ctrls.layout,
            proportion=1,
            flag=wx.ALL,  #|wx.EXPAND,
            border=5)

        usrpstate_col1 = wx.BoxSizer(wx.VERTICAL)
        usrpstate_col1.Add(usrpstate_row1)
        usrpstate_col1.Add(usrpstate_row2, flag=wx.EXPAND)

        usrpstate_col2 = wx.BoxSizer(wx.VERTICAL)

        # col 1
        usrpstate_cluster.Add(usrpstate_col1)
        # col 2
        usrpstate_cluster.Add(usrpstate_col2)

        # second cluster - display controls

        display_outline = wx.StaticBox(self, wx.ID_ANY, "Display")
        display_cluster = wx.StaticBoxSizer(display_outline, wx.HORIZONTAL)

        nframesbox = wx.BoxSizer(wx.HORIZONTAL)
        nframesbox.Add(self.nframes_ctrls.layout,
                       proportion=1,
                       flag=wx.ALL,
                       border=5)
        nframesbox.Add(self.tune_delay_ctrls.layout,
                       proportion=1,
                       flag=wx.ALL,
                       border=5)

        display_col1 = wx.BoxSizer(wx.VERTICAL)
        display_col1.Add(self.res_ctrls.layout, flag=wx.ALL, border=5)
        display_col1.Add(nframesbox, flag=wx.EXPAND)

        display_col2 = wx.BoxSizer(wx.VERTICAL)
        display_col2.Add(self.windowfn_ctrls.layout, flag=wx.ALL, border=5)
        display_col2.Add(self.power_ctrls.layout,
                         flag=wx.ALL | wx.EXPAND,
                         border=5)

        # col 1
        display_cluster.Add(display_col1)
        # col 2
        display_cluster.Add(display_col2)

        # third cluster - data controls

        data_outline = wx.StaticBox(self, wx.ID_ANY, "Data")
        data_cluster = wx.StaticBoxSizer(data_outline, wx.HORIZONTAL)

        data_col3 = wx.BoxSizer(wx.VERTICAL)
        data_col3.Add(self.threshold_ctrls.layout)
        data_col3.Add(self.export_ctrls.layout)

        # col 1
        data_cluster.Add(self.mkr1_ctrls.layout, flag=wx.ALL, border=5)
        # col 2
        data_cluster.Add(self.mkr2_ctrls.layout, flag=wx.ALL, border=5)
        # col 3
        data_cluster.Add(data_col3, flag=wx.ALL, border=5)

        # put everything together

        # Add control clusters vertically to control stack
        controlstack.Add(usrpstate_cluster,
                         flag=wx.EXPAND | wx.LEFT | wx.RIGHT,
                         border=5)
        controlstack.Add(display_cluster,
                         flag=wx.EXPAND | wx.LEFT | wx.RIGHT,
                         border=5)
        controlstack.Add(data_cluster,
                         flag=wx.EXPAND | wx.LEFT | wx.RIGHT,
                         border=5)

        # Add plot and control stack side-by-side on the front panel
        frontpanel.Add(self.plot, flag=wx.ALIGN_CENTER_VERTICAL)
        frontpanel.Add(controlstack, flag=wx.ALIGN_CENTER_VERTICAL)

        self.SetSizer(frontpanel)
        self.Fit()

    ####################
    # GUI Initialization
    ####################

    def init_mpl_canvas(self):
        """Initialize a matplotlib plot."""
        self.plot = wx.Panel(self, wx.ID_ANY, size=(700, 600))
        self.figure = Figure(figsize=(7, 6), dpi=100)
        self.figure.subplots_adjust(right=.95)
        self.canvas = FigureCanvas(self.plot, -1, self.figure)

    def configure_mpl_plot(self, y, adjust_freq_range=True):
        """Configure or reconfigure the matplotlib plot"""
        maxbin = self.tb.cfg.max_plotted_bin
        self.x = self.tb.cfg.bin_freqs[:maxbin]
        # self.line in a numpy array in the form [[x-vals], [y-vals]], where
        # x-vals are bin center frequencies and y-vals are powers. So once we
        # initialize a power at each freq, just find the index of the
        # frequency that a measurement was taken at, and insert it into the
        # corresponding index in y-vals.
        if adjust_freq_range:
            len_x = len(self.x)
            len_y = len(y)
            if len_x != len_y:
                # There's a race condition when in continuous mode and
                # a frequency range-adjusting parameter (like span) is
                # changed, so we sometimes get updated x-values before
                # updated y-values. Since a) it only affects
                # continuous mode and b) the user has requested a
                # different view, there's no harm in simply dropping
                # the old data and re-calling configure_mpl_plot next frame.
                # Still - this is a workaround.
                # The most "correct" solution would be to have
                # controller_c tag the first sample propagated after
                # flowgraph starts, which plotter_f would look for and
                # use to trigger plot reconfig.
                self.logger.debug("data mismatch - frame dropped")
                return False

            if hasattr(self, 'mkr1'):
                self.mkr1.unplot()
            if hasattr(self, 'mkr2'):
                self.mkr2.unplot()
            if hasattr(self, 'line'):
                self.line.remove()

            # initialize a line
            self.line, = self.subplot.plot(self.x,
                                           y,
                                           animated=True,
                                           antialiased=True,
                                           linestyle='-',
                                           color='b')

        self.canvas.draw()
        self._update_background()

        return True

    def format_axis(self):
        """Set the formatting of the plot axes."""
        if hasattr(self, "subplot"):
            ax = self.subplot
        else:
            ax = self.figure.add_subplot(111)

        xaxis_formatter = FuncFormatter(self.format_mhz)
        ax.xaxis.set_major_formatter(xaxis_formatter)
        ax.set_xlabel("Frequency (MHz)")
        ax.set_ylabel("Power (dBm)")
        cf = self.tb.cfg.center_freq
        lowest_xtick = cf - (self.tb.cfg.span / 2)
        highest_xtick = cf + (self.tb.cfg.span / 2)
        ax.set_xlim(lowest_xtick - 1e6, highest_xtick + 1e6)
        ax.set_ylim(self.min_power + 1, self.max_power - 1)
        xticks = np.linspace(lowest_xtick, highest_xtick, 5, endpoint=True)
        ax.set_xticks(xticks)
        ax.set_yticks(np.arange(self.min_power, self.max_power, 10))
        ax.grid(color='.90', linestyle='-', linewidth=1)
        ax.set_title("Power Spectrum")

        self.subplot = ax
        self.canvas.draw()
        self._update_background()

    @staticmethod
    def format_mhz(x, pos):
        """Format x ticks (in Hz) to MHz with 0 decimal places."""
        return "{:.1f}".format(x / float(1e6))

    ####################
    # Plotting functions
    ####################

    def update_plot(self, y, redraw_plot, keep_alive):
        """Update the plot."""

        if redraw_plot:
            #assert not keep_alive
            self.logger.debug("Reconfiguring matplotlib plot")
            self.format_axis()
            if not self.configure_mpl_plot(y):
                # Got bad data, try again next frame
                self.tb.plot_iface.redraw_plot.set()
                return

        # Required for plot blitting
        self.canvas.restore_region(self.plot_background)

        if keep_alive:
            # Just keep markers and span alive after single run
            y = self.line.get_ydata()
            self.subplot.draw_artist(self.line)
        else:
            self._draw_line(y)
            self._check_threshold(y)

        self._draw_span()
        self._draw_threshold()
        self._draw_markers(y)

        # blit canvas
        self.canvas.blit(self.subplot.bbox)

    def _update_background(self):
        """Force update of the plot background."""
        self.plot_background = self.canvas.copy_from_bbox(self.subplot.bbox)

    def _draw_span(self):
        """Draw a span to bound the peak search functionality."""
        if self.span is not None:
            self.subplot.draw_artist(self.span)

    def _draw_threshold(self):
        """Draw a span to bound the peak search functionality."""
        if self.threshold.line is not None:
            self.subplot.draw_artist(self.threshold.line)

    def _draw_line(self, y):
        """Draw the latest chunk of line data."""
        self.line.set_ydata(y)
        self.subplot.draw_artist(self.line)

    def _draw_markers(self, y):
        """Draw power markers at a specific frequency."""
        # Update mkr1 if it's set
        if self.mkr1.freq is not None:
            m1bin = self.mkr1.bin_idx
            mkr1_power = y[m1bin]
            self.mkr1.point.set_ydata(mkr1_power)
            self.mkr1.point.set_visible(True)  # make visible
            self.mkr1.text_label.set_visible(True)
            self.mkr1.text_power.set_text("{:.1f} dBm".format(mkr1_power))
            self.mkr1.text_power.set_visible(True)

            # redraw
            self.subplot.draw_artist(self.mkr1.point)
            self.figure.draw_artist(self.mkr1.text_label)
            self.figure.draw_artist(self.mkr1.text_power)

        # Update mkr2 if it's set
        if self.mkr2.freq is not None:
            m2bin = self.mkr2.bin_idx
            mkr2_power = y[m2bin]
            self.mkr2.point.set_ydata(mkr2_power)
            self.mkr2.point.set_visible(True)  # make visible
            self.mkr2.text_label.set_visible(True)
            self.mkr2.text_power.set_text("{:.2f} dBm".format(mkr2_power))
            self.mkr2.text_power.set_visible(True)

            # Redraw
            self.subplot.draw_artist(self.mkr2.point)
            self.figure.draw_artist(self.mkr2.text_label)
            self.figure.draw_artist(self.mkr2.text_power)

    def _check_threshold(self, y):
        """Warn to stdout if the threshold level has been crossed."""
        # Update threshold
        # indices of where the y-value is greater than self.threshold.level
        if self.threshold.level is not None:
            overloads, = np.where(y > self.threshold.level)
            if overloads.size:  # is > 0
                self.log_threshold_overloads(overloads, y)

    def log_threshold_overloads(self, overloads, y):
        """Outout threshold violations to the logging system."""
        logheader = "============= Overload at {} ============="
        self.logger.warning(logheader.format(int(time.time())))
        logmsg = "Exceeded threshold {0:.0f}dBm ({1:.2f}dBm) at {2:.2f}MHz"
        for i in overloads:
            self.logger.warning(
                logmsg.format(self.threshold.level, y[i], self.x[i] / 1e6))

    ################
    # Event handlers
    ################

    def on_mousedown(self, event):
        """store event info for single click."""
        self.last_click_evt = event

    def on_mouseup(self, event):
        """Determine if mouse event was single click or click-and-drag."""
        if abs(self.last_click_evt.x - event.x) >= 5:
            # mouse was clicked and dragged more than 5 pxls, set a span
            self.span = self.subplot.axvspan(
                self.last_click_evt.xdata,
                event.xdata,
                color='red',
                alpha=0.2,
                # play nice with blitting:
                animated=True)

            xdata_points = [self.last_click_evt.xdata, event.xdata]
            # always set left bound as lower value
            self.span_left, self.span_right = sorted(xdata_points)
        else:
            # caught single click, clear span
            if self.subplot.patches:
                self.span.remove()
                self.subplot.patches = []
                self.span = self.span_left = self.span_right = None

    def idle_notifier(self, event):
        self.tb.plot_iface.set_gui_idle()

    def set_continuous_run(self, event):
        self.tb.pending_cfg.export_raw_time_data = False
        self.tb.pending_cfg.export_raw_fft_data = False
        self.tb.pending_cfg.continuous_run = True
        self.tb.set_continuous_run()

    def set_single_run(self, event):
        self.tb.pending_cfg.continuous_run = False
        self.tb.set_single_run()

    @staticmethod
    def _verify_data_dir(dir):
        if not os.path.exists(dir):
            os.makedirs(dir)

    def export_time_data(self, event):
        if (self.tb.single_run.is_set() or self.tb.continuous_run.is_set()):
            msg = "Can't export data while the flowgraph is running."
            msg += " Use \"single\" run mode."
            self.logger.error(msg)
            return
        else:
            if not self.tb.timedata_sink.data():
                self.logger.warn("No more time data to export")
                return

            # creates path string 'data/time_data_01_TIMESTAMP.dat'
            dirname = "data"
            self._verify_data_dir(dirname)
            fname = str.join(
                '', ('time_data_', str(self.time_data_export_counter).zfill(2),
                     '_', str(int(time.time())), '.dat'))

            wildcard = "Data and Settings files (*.dat; *.mat)|*.dat;*.mat"
            style = wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT
            filepath_dialog = wx.FileDialog(self,
                                            message="Save As",
                                            defaultDir=dirname,
                                            defaultFile=fname,
                                            wildcard=wildcard,
                                            style=style)

            if filepath_dialog.ShowModal() == wx.ID_CANCEL:
                return

            self.time_data_export_counter += 1
            filepath_dialog.Destroy()

            self.tb.save_time_data_to_file(filepath_dialog.GetPath())

    def export_fft_data(self, event):
        if self.tb.single_run.is_set() or self.tb.continuous_run.is_set():
            msg = "Can't export data while the flowgraph is running."
            msg += " Use \"single\" run mode."
            self.logger.error(msg)
            return
        else:
            if not self.tb.freqdata_sink.data():
                self.logger.warn("No more FFT data to export")
                return False

            # creates path string 'data/fft_data_01_TIMESTAMP.dat'
            dirname = "data"
            self._verify_data_dir(dirname)
            fname = str.join(
                '', ('fft_data_', str(self.fft_data_export_counter).zfill(2),
                     '_', str(int(time.time())), '.dat'))

            wildcard = "Data and Settings files (*.dat; *.mat)|*.dat;*.mat"
            style = wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT
            filepath_dialog = wx.FileDialog(self,
                                            message="Save As",
                                            defaultDir=dirname,
                                            defaultFile=fname,
                                            wildcard=wildcard,
                                            style=style)

            if filepath_dialog.ShowModal() == wx.ID_CANCEL:
                return

            self.fft_data_export_counter += 1
            filepath_dialog.Destroy()

            self.tb.save_freq_data_to_file(filepath_dialog.GetPath())

    def close(self, event):
        """Handle a closed gui window."""
        self.closed = True
        self.tb.stop()
        self.tb.wait()
        self.Destroy()
        self.logger.debug("GUI closing.")
示例#19
0
class Frame(wx.Frame):
	def __init__(self):
		wx.Frame.__init__(self, None, -1)

		self.SetTitle('Blitting Example')

		# Figure layout.
		self.fig = Figure((5,4), 100)
		self.canvas = FigureCanvas(self, -1, self.fig)

		# BEGIN: Widget layout.
		self.wx_widgets = []
		sizer = wx.BoxSizer()
		sizer.Add(self.canvas, proportion=1, flag=wx.EXPAND)
		self.SetSizer(sizer)
		self.Fit()
		# END: Widget layout.

		# BEGIN: Plot initialization.
		self.axes = self.fig.add_subplot(111) 
		self.line1_ydata = [numpy.random.normal()]
		self.line2_ydata = [numpy.random.normal()]
		self.line1, = self.axes.plot(self.line1_ydata, color='b', animated=BLIT)
		self.line2, = self.axes.plot(self.line2_ydata, color='r', animated=BLIT)
		self.fps_label = self.axes.annotate("FPS: 0", (0.01, 0.95), xycoords="axes fraction", animated=BLIT)
		self.xaxis = self.axes.get_xaxis()
		self.yaxis = self.axes.get_yaxis()
		# END: Plot initialization.

		# BEGIN: Timers
		# IMPORTANT: Use wx.EVT_TIMER for redraw to avoid resource conflicts/crashes.
		self.redraw_timer = wx.Timer(self, wx.NewId())   # Plot refresh timer.
		self.redraw_timer.Start(50)
		wx.EVT_TIMER(self, self.redraw_timer.GetId(), self.redraw) 
		self.frames = 0
		self.start = time.time()
		# END: Timers

	###############################
	# BEGIN: Plot related methods #
	###############################
	def redraw(self, evt):
	
		# update the ydata, normally this would be done by SyncDB
		y1 = self.line1_ydata[-1] + numpy.random.normal()
		y2 = self.line2_ydata[-1] + numpy.random.normal()
		self.line1_ydata.append(y1)
		self.line2_ydata.append(y2)
		
		self.line1.set_data(range(len(self.line1_ydata)), self.line1_ydata)
		self.line2.set_data(range(len(self.line2_ydata)), self.line2_ydata)
		self.axes.set_ylim(min(self.line1_ydata + self.line2_ydata), max(self.line1_ydata + self.line2_ydata))
		self.axes.set_xlim(max(0, len(self.line1_ydata)-100), max(100, len(self.line1_ydata)))
		self.fps_label.set_text("FPS: %.2f" % (self.frames / float(time.time() - self.start)))
		
		if BLIT:
			self.fig.draw_artist(self.fig)
			self.axes.draw_artist(self.line1)
			self.axes.draw_artist(self.line2)
			self.axes.draw_artist(self.fps_label)
			self.fig.draw_artist(self.xaxis)
			self.fig.draw_artist(self.yaxis)
			self.canvas.blit(self.fig.bbox)
		else:
			self.canvas.draw()
		
		self.frames += 1
示例#20
0
class PlotFigure(wx.Frame):
    """Matplotlib wxFrame with animation effect"""
    def __init__(self):
        # initialize the super class
        wx.Frame.__init__(self,
                          None,
                          wx.ID_ANY,
                          title="CPU Usage Monitor",
                          size=(600, 400))
        # Matplotlib Figure
        self.fig = Figure((6, 4), 100)
        # bind the Figure to the backend specific canvas
        self.canvas = FigureCanvas(self, wx.ID_ANY, self.fig)
        # add a subplot
        self.ax = self.fig.add_subplot(111)

        # limit the X and Y axes dimensions
        # we prefer 2 separate functions for clarity
        self.ax.set_ylim([0, 100])
        self.ax.set_xlim([0, POINTS])
        # but we want a "frozen" window (defined by y/xlim functions)
        self.ax.set_autoscale_on(False)
        # we do not want ticks on X axis
        self.ax.set_xticks([])
        # we want a tick every 10 point on Y (101 is to have 100 too)
        self.ax.set_yticks(range(0, 101, 10))
        # disable autoscale, since we don't want the Axes to adapt
        # draw a grid (it will be only for Y)
        self.ax.grid(True)
        # generates first "empty" plots
        self.user = [None] * POINTS
        self.nice = [None] * POINTS
        self.sys = [None] * POINTS
        self.idle = [None] * POINTS
        self.l_user, = self.ax.plot(range(POINTS), self.user, label='User%')
        self.l_nice, = self.ax.plot(range(POINTS), self.nice, label='Nice%')
        self.l_sys, = self.ax.plot(range(POINTS), self.sys, label='Sys%')
        self.l_idle, = self.ax.plot(range(POINTS), self.idle, label='Idle%')
        # add the legend
        self.ax.legend(loc='upper center',
                       ncol=4,
                       prop=font_manager.FontProperties(size=10))
        # force a draw on the canvas()
        # trick to show the grid and the legend
        self.canvas.draw()
        # save the clean background - everything but the line
        # is drawn and saved in the pixel buffer background
        self.bg = self.canvas.copy_from_bbox(self.ax.bbox)
        # take a snapshot of CPU usage, needed for the update algorithm

        self.before = self.prepare_cpu_usage()
        # bind events coming from timer with id = TIMER_ID
        # to the onTimer callback function
        wx.EVT_TIMER(self, TIMER_ID, self.onTimer)

    def prepare_cpu_usage(self):
        """helper function to return CPU usage info"""
        # get the CPU times using psutil module
        t = p.cpu_times()
        # return only the values we're interested in
        if hasattr(t, 'nice'):
            return [t.user, t.nice, t.system, t.idle]
        else:
            # special case for Windows, without 'nice' value
            return [t.user, 0, t.system, t.idle]

    def get_cpu_usage(self):
        """Compute CPU usage comparing previous and currentmeasurements"""
        # take the current CPU usage information
        now = self.prepare_cpu_usage()
        # compute deltas between current and previous measurements
        delta = [now[i] - self.before[i] for i in range(len(now))]
        # compute the total (needed for percentages calculation)
        total = sum(delta)
        # save the current measurement to before object
        self.before = now
        # return the percentage of CPU usage for our 4 categories
        return [(100.0 * dt) / total for dt in delta]

    def onTimer(self, evt):
        """callback function for timer events"""
        # get the CPU usage information
        tmp = self.get_cpu_usage()
        # restore the clean background, saved at the beginning
        self.canvas.restore_region(self.bg)
        # update the data
        self.user = self.user[1:] + [tmp[0]]
        self.nice = self.nice[1:] + [tmp[1]]
        self.sys = self.sys[1:] + [tmp[2]]
        self.idle = self.idle[1:] + [tmp[3]]
        # update the plot
        self.l_user.set_ydata(self.user)
        self.l_nice.set_ydata(self.nice)
        self.l_sys.set_ydata(self.sys)
        self.l_idle.set_ydata(self.idle)
        # just draw the "animated" objects
        self.ax.draw_artist(self.l_user)
        self.ax.draw_artist(self.l_nice)
        self.ax.draw_artist(self.l_sys)
        self.ax.draw_artist(self.l_idle)
        # "blit" the background with the animated lines
        self.canvas.blit(self.ax.bbox)
示例#21
0
class WxLineScatterWidget(wx.Panel):
    axis_width = 20
    axis_offset = 1.05

    def __init__(self, *args, **kwargs):
        kwargs['style'] = kwargs.setdefault(
            'style',
            wx.NO_FULL_REPAINT_ON_RESIZE) | wx.NO_FULL_REPAINT_ON_RESIZE
        wx.Panel.__init__(self, *args, **kwargs)
        self.id = wx.NewId()
        self.plot1 = 'none'
        self.plot2 = 'none'
        self.plot3 = 'none'
        self.lineprops1 = wxLineProps({'color': '#990000', 'fill': True})
        self.lineprops2 = wxLineProps({'color': '#009900', 'fill': True})
        self.lineprops3 = wxLineProps({'color': '#000099', 'fill': True})
        self.autoy1 = True
        self.autoy2 = True
        self.autoy3 = True
        self.smooth1 = 1
        self.smooth2 = 1
        self.smooth3 = 1
        self.xaxis = ''
        self.press = False
        self.cursor = None
        self.span = None
        self.selstart = 0
        self.selstop = 0
        self.enablecursor = True
        self.enablespan = True
        self.cursorcolor = '#FF0000'
        self.cursorwidth = 1

        self.gpxfig = Figure()
        self.ax1 = self.gpxfig.add_subplot(
            1, 1, 1
        )  # create a grid of 1 row, 1 col and put a subplot in the first cell of this grid
        self.gpxfig.subplots_adjust(right=0.9, left=0.06)

        self.ax2 = self.ax1.twinx()
        #self.ax2.spines["left"].set_visible(False)

        self.ax3 = self.ax1.twinx()
        self.ax3.spines["right"].set_position(("axes", self.axis_offset))
        #self.ax3.spines["left"].set_visible(False)
        # canvas and events
        self.gpxcanvas = FigureCanvas(self, -1, self.gpxfig)
        self.gpxcanvas.mpl_connect('scroll_event', self.OnMouseWheel)
        self.gpxcanvas.mpl_connect('button_press_event', self.OnLeftMouseDown)
        self.gpxcanvas.mpl_connect('button_release_event', self.OnLeftMouseUp)
        self.gpxcanvas.mpl_connect('motion_notify_event', self.OnMouseMotion)
        self.gpxcanvas.mpl_connect('resize_event', self.OnSize)
        self.gpxcanvas.mpl_connect('figure_enter_event', self.OnMouseEnter)
        self.gpxcanvas.mpl_connect('figure_leave_event', self.OnMouseLeave)
        self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightMouseDown)
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.gpxcanvas, 1,
                       wx.LEFT | wx.TOP | wx.GROW | wx.EXPAND)
        self.SetSizer(self.sizer)
        #self.OnSize(None)

        msgwrap.register(self.OnSigCurChanged, signal="CurChanged")
        msgwrap.register(self.OnSigSelChanged, signal="SelChanged")
        msgwrap.register(self.OnSigValChanged, signal="ValChanged")

        #set background color to pure white
        #that code does not work on linux...
        #color = wx.SystemSettings.GetColour(wx.wx.SYS_COLOUR_BTNFACE)
        color = wx.Colour(255, 255, 255)
        self.gpxfig.set_facecolor(
            (color.red / 255.0, color.green / 255.0, color.blue / 255.0))
        self.gpxfig.set_edgecolor(
            (color.red / 255.0, color.green / 255.0, color.blue / 255.0))
        self.gpxfig.set_edgecolor((0.0, 0.0, 0.0))
        self.gpxcanvas.SetBackgroundColour(color)

        # create right now the popup menu
        self.select_menu = wx.Menu()
        for text in ["Disable selected",\
                            "Enable selected",\
                            "Delete selected",\
                            "Disable non selected",\
                            "Enable non selected",\
                            "Delete non selected",\
                            "Toggle points"]:
            item = self.select_menu.Append(wx.NewId(), text)
            self.Bind(wx.EVT_MENU, self.OnPopup, item)

    def x_to_num(self, value, scaled=True):
        if self.xaxis == 'time':
            return dates.date2num(dateutil.parser.parse(value))
        else:
            if scaled:
                #return float(value)/self.gpx.get_scale(self.xaxis)
                return float(value) * self.gpx.get_scale(self.xaxis)
            else:
                return float(value)

    def num_to_x(self, value, scaled=True):
        if self.xaxis == 'time':
            return dates.num2date(value)
        else:
            if scaled:
                #return value*self.gpx.get_scale(self.xaxis)
                return value / self.gpx.get_scale(self.xaxis)
            else:
                return value

    def x_max(self):
        if self.xaxis == 'time':
            return self.x_to_num(
                self.gpx[self.xaxis][self.gpx.get_row_count() - 1])
        else:
            return self.x_to_num(np.nanmax(self.gpx[self.xaxis]))

    def x_min(self):
        if self.xaxis == 'time':
            return self.x_to_num(self.gpx[self.xaxis][0])
        else:
            return self.x_to_num(np.nanmin(self.gpx[self.xaxis]))

    def format_x_axis(self):
        if self.xaxis == 'time':
            xlo = self.ax1.get_xlim()[0]
            xhi = self.ax1.get_xlim()[1]
            if (xhi - xlo) > 0.003:
                self.ax1.xaxis.set_major_formatter(
                    dates.DateFormatter("%H:%M"))
            else:
                self.ax1.xaxis.set_major_formatter(
                    dates.DateFormatter("%H:%M:%S"))
            self.ax1.set_xlabel('Time (HH:MM:SS)')
        else:
            #self.ax1.set_xlabel('Distance (m)')
            self.ax1.set_xlabel(self.xaxis + " (" +
                                self.gpx.get_unit(self.xaxis)[0] + ")")
            #self.ax1.xaxis.set_major_formatter(mpl.ticker.FormatStrFormatter('%.0f') )
            self.ax1.xaxis.set_major_formatter(mpl.ticker.ScalarFormatter())
            pass

    def get_axis(self, event, tolerance):
        bbox = self.ax1.get_window_extent().transformed(
            self.gpxfig.dpi_scale_trans.inverted())
        l = bbox.bounds[0] * self.gpxfig.dpi
        b = bbox.bounds[1] * self.gpxfig.dpi
        r = l + bbox.bounds[2] * self.gpxfig.dpi
        t = b + bbox.bounds[3] * self.gpxfig.dpi
        #convert screen coordinates to graph coordinates
        xlo = self.ax1.get_xlim()[0]
        xhi = self.ax1.get_xlim()[1]
        event.xdata = (event.x - l) / (r - l) * (xhi - xlo) + xlo
        if ptinrect(l - tolerance, t, l, b, event.x, event.y):
            ylo, yhi = self.ax1.get_ylim()
            event.ydata = (event.y - b) / (t - b) * (yhi - ylo) + ylo
            return 'left'
        if ptinrect(r, t, r + tolerance, b, event.x, event.y):
            ylo, yhi = self.ax2.get_ylim()
            event.ydata = (event.y - b) / (t - b) * (yhi - ylo) + ylo
            return 'right'
        if ptinrect(l, t, r, t + tolerance, event.x, event.y):
            ylo, yhi = self.ax1.get_ylim()
            event.ydata = (event.y - b) / (t - b) * (yhi - ylo) + ylo
            return 'top'
        if ptinrect(l, b - tolerance, r, b, event.x, event.y):
            ylo, yhi = self.ax1.get_ylim()
            event.ydata = (event.y - b) / (t - b) * (yhi - ylo) + ylo
            return 'bottom'
        #we need a small adjustment here, but this hack gives good results
        if ptinrect(r * self.axis_offset * 0.985, t,
                    r * self.axis_offset * 0.985 + tolerance, b, event.x,
                    event.y):
            ylo, yhi = self.ax3.get_ylim()
            event.ydata = (event.y - b) / (t - b) * (yhi - ylo) + ylo
            return "3rd"
        if ptinrect(l, t, r, b, event.x, event.y):
            ylo, yhi = self.ax1.get_ylim()
            event.ydata = (event.y - b) / (t - b) * (yhi - ylo) + ylo
            return 'main'

    def update_axis(self, ax, plot, ylo, yhi, yauto, lineprops, smooth):
        if plot != 'none':
            ## process data!!
            N = smooth
            #data=(1.0)*np.convolve(self.gpx[plot]*self.gpx.scale[plot], np.ones((N,))/N)[(N-1):]
            data = (1.0) * np.convolve(self.gpx[(plot, True)],
                                       np.ones((N, )) / N)[(N - 1):]
            data[self.gpx['ok'] == False] = np.NAN
            ##end of data processing
            #remove fill_between collection
            for coll in ax.collections:
                ax.collections.remove(coll)
            #need to rebuild dates array in case something was deleted
            self.xvalues = []
            for x in self.gpx[self.xaxis]:
                self.xvalues.append(self.x_to_num(x))
            ax.get_lines()[0].set_data(self.xvalues, data)
            self.format_x_axis()
            if lineprops['fill']:
                ax.fill_between(self.xvalues,
                                0,
                                data,
                                facecolor=lineprops['color'],
                                alpha=0.2)
            ax.get_lines()[0].set_color(lineprops['color'])
            ax.get_lines()[0].set_linewidth(lineprops['linewidth'])
            ax.get_lines()[0].set_marker(lineprops['marker'])
            ax.get_lines()[0].set_markersize(lineprops['markersize'])
            ax.set_autoscaley_on(yauto)
            ##now using legends instead of labels
            #ax.set_ylabel(plot+" ("+str(self.gpx.get_unit(plot)[0])+")")
            #ax.yaxis.label.set_color(lineprops['color'])
            lines = self.line1 + self.line2 + self.line3
            labs = [
                p for p in [self.plot1, self.plot2, self.plot3] if p != 'none'
            ]
            self.ax1.legend(
                lines, labs, loc='best'
            )  #,bbox_to_anchor=(0.5, 1.3), ncol=3, fancybox=False, shadow=False)

            if not yauto:
                ax.set_ylim(ylo, yhi)
            else:
                ax.set_ylim(np.min(self.gpx[plot] * self.gpx.scale[plot]),
                            np.max(self.gpx[plot] * self.gpx.scale[plot]))
            ax.set_visible(True)
            for tick in ax.get_yticklabels():
                tick.set_color(lineprops['color'])
            ax.spines["right"].set_edgecolor(lineprops['color'])
            ax.tick_params(axis='y', colors=lineprops['color'])
        else:
            ax.get_lines()[0].set_data(self.xvalues,
                                       np.zeros(self.gpx.get_row_count()))
            ax.set_visible(False)
        self.cursor.set_color(self.cursorcolor)
        self.cursor.set_linewidth(self.cursorwidth)
        self.format_x_axis()
        self.Draw(False)
        self.OnSize(None)

    def AttachGpx(self, data):
        self.gpx = data
        self.xvalues = []
        self.xaxis = self.gpx.get_header_names()[0]
        for x in self.gpx[self.xaxis]:
            self.xvalues.append(self.x_to_num(x))
        self.ax1.set_xlabel('')
        self.line1 = self.ax1.plot(self.xvalues,
                                   np.zeros(self.gpx.get_row_count()),
                                   picker=5,
                                   label='ax1')
        self.line2 = self.ax2.plot(self.xvalues,
                                   np.zeros(self.gpx.get_row_count()),
                                   picker=5,
                                   label='ax2')
        self.line3 = self.ax3.plot(self.xvalues,
                                   np.zeros(self.gpx.get_row_count()),
                                   picker=5,
                                   label='ax3')
        xlo = self.x_to_num(self.gpx[self.xaxis][0])
        xhi = self.x_to_num(self.gpx[self.xaxis][self.gpx.get_row_count() - 1])
        if xlo != xhi:
            self.ax1.set_xlim([xlo, xhi])
        if self.enablecursor == True:
            self.cursor = self.ax1.axvline(color='r', animated=True)
            mid = (self.ax1.get_xlim()[0] + self.ax1.get_xlim()[1]) / 2
            self.cursor.set_xdata(mid)
            #self.cursor.set_color('k')
            #self.cursor.set_linewidth(4)
        if self.enablespan == True:
            self.span = patches.Rectangle(
                (self.ax1.get_xlim()[0], 0),
                (self.ax1.get_xlim()[1] - self.ax1.get_xlim()[0]) / 3,
                200,
                color='k',
                alpha=0.3,
                animated=True)
            self.ax1.add_patch(self.span)
            self.span.set_visible(False)
        self.SetDefaultPlots()
        self.OnSize(None)

    def DetachGpx(self):
        self.gpx = None
        self.plot1 = 'none'
        self.plot2 = 'none'
        self.plot3 = 'none'
        self.autoy1 = True
        self.autoy2 = True
        self.autoy3 = True
        self.fill1 = True
        self.fill2 = True
        self.fill3 = True
        self.xaxis = ''
        self.press = False
        if self.cursor != None:
            self.cursor.remove()
            self.cursor = None
        if self.span != None:
            self.span.remove()
            self.span = None

    def OnSigSelChanged(self, arg1, arg2, arg3):
        if arg1 == self.id:
            return
        if self.span != None:
            xlo = self.x_to_num(self.gpx[self.xaxis][arg2])
            xhi = self.x_to_num(self.gpx[self.xaxis][arg3])
            self.span.set_bounds(
                xlo,
                self.ax1.get_ylim()[0], xhi - xlo,
                self.ax1.get_ylim()[1] - self.ax1.get_ylim()[0])
            self.span.set_visible(True)

    def OnSigValChanged(self, arg1):
        if arg1 == self.id:
            return
        self.update_axis(self.ax1, self.plot1,
                         self.ax1.get_xlim()[0],
                         self.ax1.get_xlim()[1], self.autoy1, self.lineprops1,
                         self.smooth1)
        self.update_axis(self.ax2, self.plot2,
                         self.ax2.get_xlim()[0],
                         self.ax2.get_xlim()[1], self.autoy2, self.lineprops2,
                         self.smooth2)
        self.update_axis(self.ax3, self.plot3,
                         self.ax2.get_xlim()[0],
                         self.ax2.get_xlim()[1], self.autoy3, self.lineprops3,
                         self.smooth3)

    def OnSigCurChanged(self, arg1, arg2):
        if arg1 == self.id:
            return
        if self.gpx != None:
            xval = self.gpx[self.xaxis][arg2]
            self.gpxcanvas.restore_region(self.background)
            if self.cursor != None:
                self.cursor.set_xdata(self.x_to_num(xval))
                self.ax1.draw_artist(self.cursor)
            if self.span != None and self.span.get_visible():
                self.ax1.draw_artist(self.span)
            self.gpxcanvas.blit()
        self.UpdateStatusBar(arg2)

    def SetDefaultPlots(self):
        self.xaxis = self.gpx.get_header_names()[0]
        self.plot1 = self.gpx.get_header_names()[1]
        self.plot2 = 'none'
        self.plot3 = 'none'
        self.update_axis(self.ax1, self.plot1, 0, 1, True, self.lineprops1,
                         self.smooth1)
        self.update_axis(self.ax2, self.plot2, 0, 1, True, self.lineprops2,
                         self.smooth2)
        self.update_axis(self.ax3, self.plot3, 0, 1, True, self.lineprops3,
                         self.smooth3)

    def XAxisAllowed(self):
        l = ''
        for name in self.gpx.get_header_names():
            l += '|' + name
        return l[1:]

    def YAxisAllowed(self):
        l = ''
        for name in self.gpx.get_header_names():
            l += '|' + name
        return l[1:]

    def Draw(self, blit):
        if blit:
            self.gpxcanvas.restore_region(self.background)
        else:
            self.gpxcanvas.draw()
            self.background = self.gpxcanvas.copy_from_bbox(self.ax1.bbox)
        if self.span != None and self.span.get_visible():
            self.ax1.draw_artist(self.span)
        if self.cursor != None:
            self.ax1.draw_artist(self.cursor)
        self.gpxcanvas.blit()

    def OnSize(self, event):
        pixels = self.GetClientSize()
        if pixels[0] < 20 or pixels[1] < 20:
            return
        self.SetSize(pixels)
        self.gpxcanvas.SetSize(pixels)
        self.gpxfig.set_size_inches(
            float(pixels[0]) / self.gpxfig.get_dpi(),
            float(pixels[1]) / self.gpxfig.get_dpi())
        leg = self.ax1.xaxis.get_tightbbox(self.gpxcanvas.get_renderer())
        leg1 = self.ax1.yaxis.get_tightbbox(self.gpxcanvas.get_renderer())
        leg2 = self.ax2.yaxis.get_tightbbox(self.gpxcanvas.get_renderer())
        leg3 = self.ax3.yaxis.get_tightbbox(self.gpxcanvas.get_renderer(
        ))  #leg2 and leg3 are exactly the same!!
        bottomalign = (leg.height + 5) / pixels[1]
        leftalign = (leg1.width + 5) / pixels[0]
        if self.plot2 == 'none' and self.plot3 == 'none':
            rightalign = (1 - (5.0) / pixels[0]) / self.axis_offset
        else:
            rightalign = (1 - (leg2.width + 5) / pixels[0]) / self.axis_offset
        if pixels[1] > 32:
            self.gpxfig.subplots_adjust(bottom=bottomalign)
        if pixels[0] > 32:
            self.gpxfig.subplots_adjust(left=leftalign, right=rightalign)
        ##PYTHON3
        self.gpxfig.subplots_adjust(right=0.9, left=0.06, bottom=0.2)
        self.Draw(False)

    def OnLeftMouseDblClick(self, event):
        #dble click. Let's get prepared
        xlo = self.num_to_x(self.ax1.get_xlim()[0], False)
        xhi = self.num_to_x(self.ax1.get_xlim()[1], False)
        y1lo = self.ax1.get_ylim()[0]
        y1hi = self.ax1.get_ylim()[1]
        y2lo = self.ax2.get_ylim()[0]
        y2hi = self.ax2.get_ylim()[1]
        y3lo = self.ax3.get_ylim()[0]
        y3hi = self.ax3.get_ylim()[1]

        (dummy,xaxis,xlo,xhi,self.cursorcolor,self.cursorwidth,
        dummy,self.plot1,y1lo,y1hi,self.autoy1,self.smooth1,
        self.lineprops1['color'],self.lineprops1['linewidth'],self.lineprops1['marker'],self.lineprops1['markersize'],self.lineprops1['fill'],\
        dummy,self.plot2,y2lo,y2hi,self.autoy2,self.smooth2,
        self.lineprops2['color'],self.lineprops2['linewidth'],self.lineprops2['marker'],self.lineprops2['markersize'],self.lineprops2['fill'],\
        dummy,self.plot3,y3lo,y3hi,self.autoy3,self.smooth3,
        self.lineprops3['color'],self.lineprops3['linewidth'],self.lineprops3['marker'],self.lineprops3['markersize'],self.lineprops3['fill'])=\
            WxQuery("Graph Settings",\
                [('wxnotebook','X Axis',None,None,None),
                 ('wxcombo','X axis',self.XAxisAllowed(),self.xaxis,'str'),
                 ("wxentry","Start",None,str(xlo),'str'),
                 ("wxentry","End",None,str(xhi),'str'),
                 ('wxcolor','Cursor color',None,self.cursorcolor,'str'),
                 ('wxspin','Cursor width','0|6|1',self.cursorwidth,'int'),

                 ('wxnotebook','Y1Axis',None,None,None),
                 ('wxcombo','Channel 1',self.YAxisAllowed(),self.plot1,'str'),
                 ('wxentry','Bottom',None,y1lo,'float'),
                 ('wxentry','Top',None,y1hi,'float'),
                 ('wxcheck','Auto Scale','-9|-8', self.autoy1,'bool'), #8
                 ('wxhscale','Smooth','1|12|1|1',self.smooth1,'int'),
                 ('wxcolor','Color',None,self.lineprops1['color'],'str'),
                 ('wxspin','Line width','0|12|1',self.lineprops1['linewidth'],'int'),
                 ('wxcombo','Marker','.|o|+|x|^|4|s|*|D',self.lineprops1['marker'],'str'),
                 ('wxspin','Marker size','0|12|1',self.lineprops1['markersize'],'int'),
                 ('wxcheck','Fill area',None,self.lineprops1['fill'],'bool'),

                 ('wxnotebook','Y2 Axis',None,None,None),
                 ('wxcombo','Channel 2',self.YAxisAllowed(),self.plot2,'str'),
                 ('wxentry','Bottom',None,y2lo,'float'),
                 ('wxentry','Top',None,y2hi,'float'),
                 ('wxcheck','Auto Scale','-20|-19', self.autoy2,'bool'),
                 ('wxhscale','Smooth','1|12|1|1',self.smooth2,'int'),
                 ('wxcolor','Color',None,self.lineprops2['color'],'str'),
                 ('wxspin','Line width','0|12|1',self.lineprops2['linewidth'],'int'),
                 ('wxcombo','Marker','.|o|+|x|^|4|s|*|D',self.lineprops2['marker'],'str'),
                 ('wxspin','Marker size','0|12|1',self.lineprops2['markersize'],'int'),
                 ('wxcheck','Fill area',None,self.lineprops2['fill'],'bool'),

                 ('wxnotebook','Y3 Axis',None,None,None),
                 ('wxcombo','Channel 3',self.YAxisAllowed(),self.plot3,'str'),
                 ('wxentry','Bottom',None,y3lo,'float'),
                 ('wxentry','Top',None,y3hi,'float'),
                 ('wxcheck','Auto Scale','-31|-30', self.autoy3,'bool'),
                 ('wxhscale','Smooth','1|12|1|1',self.smooth3,'int'),
                 ('wxcolor','Color',None,self.lineprops3['color'],'str'),
                 ('wxspin','Line width','0|12|1',self.lineprops3['linewidth'],'int'),
                 ('wxcombo','Marker','.|o|+|x|^|4|s|*|D',self.lineprops3['marker'],'str'),
                 ('wxspin','Marker size','0|12|1',self.lineprops3['markersize'],'int'),
                 ('wxcheck','Fill area',None,self.lineprops3['fill'],'bool')
                ])
        if self.xaxis == xaxis:
            xlo = max(self.x_to_num(xlo, False), self.x_min())
            xhi = min(self.x_to_num(xhi, False), self.x_max())
            self.ax1.set_xlim([xlo, xhi])
        else:  #time units have changed... don't bother and set to full x range
            self.xaxis = xaxis
            self.ax1.set_xlim([self.x_min(), self.x_max()])
        self.update_axis(self.ax1, self.plot1, y1lo, y1hi, self.autoy1,
                         self.lineprops1, self.smooth1)
        self.update_axis(self.ax2, self.plot2, y2lo, y2hi, self.autoy2,
                         self.lineprops2, self.smooth2)
        self.update_axis(self.ax3, self.plot3, y3lo, y3hi, self.autoy3,
                         self.lineprops3, self.smooth3)

    def OnLeftMouseDown(self, event):
        where = self.get_axis(event, self.axis_width)
        #if hasattr(event, 'guiEvent') and int(event.guiEvent.type)==5:
        #calling direcly the dialog may freeze on unix (linux-osX systems) under wx backend
        #workaround   is to release mouse
        #see http://stackoverflow.com/questions/16815695/modal-dialog-freezes-the-whole-application
        #event.guiEvent.GetEventObject().ReleaseMouse() for pick_event
        if event.button == 1:
            if event.dblclick:
                try:
                    event.guiEvent.GetEventObject().ReleaseMouse()
                except:
                    pass
                self.OnLeftMouseDblClick(event)
                return
            if where == 'bottom':
                (self.x0, self.y0) = (event.xdata, event.ydata)
                self.press = True
            if where == 'main' and self.span != None:
                self.span.set_visible(True)
                (self.x0, self.y0) = (event.xdata, event.ydata)
                self.selstart = self.x0
                self.selstop = self.x0
                self.span.set_bounds(
                    event.xdata,
                    self.ax1.get_ylim()[0], 0,
                    self.ax1.get_ylim()[1] - self.ax1.get_ylim()[0])
                self.press = True
        elif event.button == 3:
            if where == 'main':
                self.OnRightMouseDown(event)

    def OnLeftMouseUp(self, event):
        where = self.get_axis(event, self.axis_width)
        self.press = False
        if event.button == 1 and self.span != None:
            if where == 'main':
                idx1 = np.searchsorted(self.ax1.get_lines()[0].get_data()[0],
                                       self.x0)
                idx2 = np.searchsorted(self.ax1.get_lines()[0].get_data()[0],
                                       event.xdata)
                self.selstart = min(idx1, idx2)
                self.selstop = max(idx1, idx2)
                if self.selstart == self.selstop:
                    self.span.set_visible(False)
                msgwrap.message("SelChanged",
                                arg1=self.id,
                                arg2=self.selstart,
                                arg3=self.selstop)
                self.press = False

    def OnRightMouseDown(self, event):
        #may be necessary in some OSes
        event.guiEvent.GetEventObject().ReleaseMouse()
        if self.selstart == self.selstop:
            self.select_menu.Enable(
                self.select_menu.FindItem("Disable selected"), False)
            self.select_menu.Enable(
                self.select_menu.FindItem("Enable selected"), False)
            self.select_menu.Enable(
                self.select_menu.FindItem("Delete selected"), False)
        else:
            self.select_menu.Enable(
                self.select_menu.FindItem("Disable selected"), True)
            self.select_menu.Enable(
                self.select_menu.FindItem("Enable selected"), True)
            self.select_menu.Enable(
                self.select_menu.FindItem("Delete selected"), True)
        self.select_menu.Enable(self.select_menu.FindItem("Toggle points"),
                                True)
        # on some OS (and depending on wxPython/wxWidgets version, calling
        # wx.PopupMenu will fail unless it is called after matplotlib handler has returned
        # for some magic reason, we do not need to specify wx.Point(event.x, event.y) in parameterss
        #self.PopupMenu(self.select_menus)
        wx.CallAfter(self.PopupMenu, self.select_menu)

    def OnMouseMotion(self, event):
        where = self.get_axis(event, self.axis_width)
        if where == 'bottom' or where == 'right' or where == 'left' or where == '3rd':
            wx.SetCursor(wx.Cursor(wx.CURSOR_MAGNIFIER))
        else:
            wx.SetCursor(wx.Cursor(wx.CURSOR_ARROW))
        if where == 'bottom' and self.press:
            dx = event.xdata - self.x0
            dy = event.ydata - self.y0
            self.ax1.set_xlim(self.ax1.get_xlim()[0] - dx,
                              self.ax1.get_xlim()[1] - dx)
            self.Draw(False)
        if where == 'main' and self.press:
            self.span.set_bounds(self.x0,\
                                self.ax1.get_ylim()[0],\
                                event.xdata-self.x0,\
                                self.ax1.get_ylim()[1]-self.ax1.get_ylim()[0])
            self.Draw(True)
        if where == 'main' and self.cursor != None:
            self.cursor.set_xdata(event.xdata)
            xval = event.xdata
            idx = np.searchsorted(self.ax1.get_lines()[0].get_data()[0], xval)
            while self.gpx['ok'][
                    idx] == False and idx >= 0:  #look for nearest enabled point
                idx -= 1
            idx = clamp(idx, 0, self.gpx.get_row_count() - 1)
            self.cursor.set_xdata(self.x_to_num(self.gpx[self.xaxis][idx]))
            msgwrap.message("CurChanged", arg1=self.id, arg2=idx)
            ##send a message for the status bar
            self.UpdateStatusBar(idx)
            self.Draw(True)

    def OnMouseWheel(self, event):
        where = self.get_axis(event, self.axis_width)
        if where == 'bottom':
            xmax = self.x_max()
            xmin = self.x_min()
            xlo, xhi = self.ax1.get_xlim()
            if event.button == 'down':
                scale_factor = 1.2
            else:
                scale_factor = 1 / 1.2
            nxhi = event.xdata + (scale_factor * (xhi - event.xdata))
            nxlo = event.xdata - (scale_factor * (event.xdata - xlo))
            nxhi = min(nxhi, xmax)
            nxlo = max(nxlo, xmin)
            self.ax1.set_xlim([nxlo, nxhi])
            self.format_x_axis()
        elif where == 'left' or where == 'right' or where == '3rd':
            if where == 'left':
                ax = self.ax1
                plot = self.plot1
            elif where == 'right':
                ax = self.ax2
                plot = self.plot2
            elif where == '3rd':
                ax = self.ax3
                plot = self.plot3
            ymax = np.max(self.gpx[plot] * self.gpx.scale[plot])
            ymin = np.min(self.gpx[plot] * self.gpx.scale[plot])
            ylo, yhi = ax.get_ylim()
            if event.button == 'down':
                scale_factor = 1.2
            else:
                scale_factor = 1 / 1.2
            nyhi = event.ydata + (scale_factor * (yhi - event.ydata))
            nylo = event.ydata - (scale_factor * (event.ydata - ylo))
            nyhi = min(nyhi, ymax)
            nylo = max(nylo, ymin)
            ax.set_ylim([nylo, nyhi])
        self.Draw(False)

    def OnMouseEnter(self, event):
        self.SetFocus(
        )  # stupid bug in wxSplitterWindow, mouse wheel is always send to the same panel in wxSplittedWIndow

    def OnMouseLeave(self, event):
        wx.SetCursor(wx.Cursor(wx.CURSOR_ARROW))
        pass

    def OnPopup(self, event):
        item = self.select_menu.FindItemById(event.GetId())
        text = item.GetText()
        if text == "Disable selected":
            self.gpx['ok'][self.selstart:self.selstop] = False
        if text == "Enable selected":
            self.gpx['ok'][self.selstart:self.selstop] = True
        if text == "Disable non selected":
            self.gpx['ok'][:self.selstart] = False
            self.gpx['ok'][self.selstop:] = False
        if text == "Enable non selected":
            self.gpx['ok'][:self.selstart] = True
            self.gpx['ok'][self.selstop:] = True
        if text == "Delete selected":
            if wx.MessageDialog(None, "Delete Points...?",\
                                'Are you sure you want to delete these points',\
                                wx.YES_NO | wx.ICON_QUESTION).ShowModal()==wx.ID_YES:
                for _ in range(self.selstart, self.selstop):
                    self.gpx.drop_row(
                        self.selstart
                    )  #each time we delete, the rest of the array is shifted. so we have to delete always the same index
        if text == "Delete non selected":
            if wx.MessageDialog(None, "Delete Points...?",\
                                'Are you sure you want to delete these points',\
                                wx.YES_NO | wx.ICON_QUESTION).ShowModal()==wx.ID_YES:
                for _ in range(self.selstop, self.gpx.get_row_count()):
                    self.gpx.drop_row(
                        self.selstop
                    )  #delete first end of range, to avoid shifting selstop
                for _ in range(0, self.selstart):
                    self.gpx.drop_row(0)
        if text == "Toggle points":
            self.gpx['ok'] = np.invert(self.gpx['ok'])
        msgwrap.message("ValChanged", arg1=self.id)
        self.update_axis(self.ax1, self.plot1,
                         self.ax1.get_ylim()[0],
                         self.ax1.get_ylim()[1], self.autoy1, self.lineprops1,
                         self.smooth1)
        self.update_axis(self.ax2, self.plot2,
                         self.ax2.get_ylim()[0],
                         self.ax2.get_ylim()[1], self.autoy2, self.lineprops2,
                         self.smooth2)
        self.update_axis(self.ax3, self.plot3,
                         self.ax3.get_ylim()[0],
                         self.ax3.get_ylim()[1], self.autoy3, self.lineprops3,
                         self.smooth3)

    def UpdateStatusBar(self, idx):
        if self.plot1 != "none":
            msg1=self.plot1+\
                " ("+str(self.gpx.get_unit(self.plot1)[0])+"): "\
                +str(self.gpx[self.plot1][idx]*self.gpx.scale[self.plot1])
        else:
            msg1 = ""
        if self.plot2 != "none":
            msg2=self.plot2+\
                " ("+str(self.gpx.get_unit(self.plot2)[0])+"): "\
                +str(self.gpx[self.plot2][idx]*self.gpx.scale[self.plot2])
        else:
            msg2 = ""
        if self.plot3 != "none":
            msg3=self.plot3+\
                " ("+str(self.gpx.get_unit(self.plot3)[0])+"): "\
                +str(self.gpx[self.plot3][idx]*self.gpx.scale[self.plot3])
        else:
            msg3 = ""
        msgwrap.message("StatusChanged",arg1=self.id,\
                            arg2=self.gpx['time'][idx],\
                            arg3=msg1,\
                            arg4=msg2,\
                            arg5=msg3
                            )
示例#22
0
class Graph(wx.BoxSizer):
    """
    This holds a curve plot with associated toolbar
    keyword arguments:
    parent -- reference to the panel or context the plot should be created in.
    orientation -- (optional) wx.BoxSizer style. This also sets the deafult
        direction to expand when adding sub-plots (default: wx.VERTICAL)
    title -- (optional) sets the title of the plot window (default: '').
    dpi -- (optional) sets dots per inch of plot window.
    params -- (optional) set matplotlib rcParams, should be a dictionary.
    (default: sets font size of: ticks, legend, axes label, font)
    **kwargs -- any keyword argument to matplotlib.Figure
    """
    def __init__(self, parent,
                orientation= wx.VERTICAL,
                title='',
                dpi=None,
                params = None,
                **kwargs):
        
        super(Graph, self).__init__(orientation)
        #initialize some font settings for matplotlib
        if params == None:
            params = {'axes.labelsize': 16,
              'font.size': 14,
              'legend.fontsize': 14,
              'xtick.labelsize': 12,
              'ytick.labelsize': 12}
        matplotlib.rcParams.update(params)
        
        self.figure = Figure(dpi=dpi, figsize=(2,2), **kwargs)
        self.canvas = FigureCanvas(parent, wx.NewId(), self.figure)
        self.sub_plots = _plot_list(self.figure)
        self.sub_plots.append(self.figure.add_subplot(111), title)
        self.toolbar = NavigationToolbar2Wx(self.canvas)
        
        ###Create some extra controls for the toolbar###
        self.cb_grid = wx.CheckBox(self.toolbar, wx.NewId(), 'Show Grid')
        btn_mark = wx.Button(self.toolbar, wx.NewId(), 'Mark selection')
        #btn_rem = wx.Button(parent, wx.NewId(), 'Remove_graph')
        self.cursor_pos = wx.StaticText(self.toolbar, wx.NewId(), 
            'x=0.0000, y=0.0000            ',
            style=wx.ALIGN_RIGHT | wx.ST_ELLIPSIZE_END | wx.ST_NO_AUTORESIZE)
        
        ####add extra controls to toolbar####
        self.toolbar.AddControl(self.cb_grid)
        self.toolbar.AddControl(btn_mark)
        self.toolbar.AddStretchableSpace()
        self.toolbar.AddControl(self.cursor_pos)
        #self.toolbar.AddStretchableSpace()
        
        #needed to update the layout
        self.toolbar.Realize()

        
        #######Main layout#######
        v_sizer = wx.BoxSizer(wx.VERTICAL)
        v_sizer.Add(self.canvas, 1, wx.EXPAND)
        v_sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
        #Add to self
        self.Add(v_sizer, 1, wx.EXPAND)
        
        ###Set title and other things###
        self.orientation = orientation
        #layout of plots (height, width, count)
        self.layout = (1,1,1)
        self.cb_grid.SetValue(True)
        self.sub_plots.show_grid(True)
        
        #connect the buttons to event handlers
        self.cb_grid.Connect(-1, -1,
                            wx.wxEVT_COMMAND_CHECKBOX_CLICKED, 
                            self._on_cb_grid)
        btn_mark.Connect(-1, -1, wx.wxEVT_COMMAND_BUTTON_CLICKED, self._on_mark)
        #btn_rem.Connect(-1, -1, wx.wxEVT_COMMAND_BUTTON_CLICKED, self.on_rem)
        
        self.canvas.mpl_connect('motion_notify_event', self._UpdateCursorInformation)
        
    
    ############Event handlers############
    def _on_cb_grid(self, evt):
        """
        Toggles if grid should be shown on sub-plots
        """
        self.sub_plots.show_grid(self.cb_grid.IsChecked())
        #redraw plots
        self.canvas.draw()
        
    def _on_mark(self, evt):
        """
        Draws or removes a selection outline on current sub-plot selection
        """
        mark_color = 'k'
        if self.sub_plots.color.lower() == 'black':
            mark_color = 'white'
        if self.sub_plots.has_selection:
            #delete markers
            for sub_plot in self.sub_plots.sub_plots:
                for line in sub_plot.selection:
                    sub_plot.axes.lines.remove(line)
            self.canvas.draw()
        else:
            for i, sub_plot in enumerate(self.sub_plots.sub_plots):
                x1, x2, y1, y2 = sub_plot.axes.axis()
                x = [x1, x2, x2, x1, x1]
                y = [y1, y1, y2, y2, y1]
                sub_plot.selection = self.redraw(x,y, hold = True,
                                        limits = (x1,x2,y1,y2),
                                        index = i,
                                        color = mark_color, linewidth = 2.0)
        self.sub_plots.has_selection = not self.sub_plots.has_selection
        
        
    def _UpdateCursorInformation(self, evt):
        if evt.inaxes:
            x, y = evt.xdata, evt.ydata
            txt = 'x={0:.4g}, y={1:.4g}'.format(x, y)
            self.cursor_pos.SetLabel(txt)
    
    ############Worker functions############
    def add_secondary_y_axis(self, label = '', index = None):
        """
        Creates a secondary y_axis on the specified sub-plots
        
        keyword arguments:
        label -- (optional) axis label of the second y-axis (default: '')
        index -- (optional) a integer or list of integers with the index of 
            sub-plots for which a secondary y-axis should be created. When 
            'None' the formatter is set for all sub-plots (default: None)
        """
        
        if type(index) == list:
            for i in index:
                self.sub_plots(i).create_y2_axis(label)
        elif type(index) == int:
            self.sub_plots(index).create_y2_axis(label)
        else:
            #do all
            count = self.layout[-1]
            for sub_plot in self.sub_plots.sub_plots:
                sub_plot.create_y2_axis(label)
        
    
    def add_subplot(self, title='', orientation=None):
        """
        Adds an additional subplot. If more than one row exists and it will
        not be filled, than the plots on the last row will be expanded to
        fill all horizontal space. All plots will be recreated
        
        keyword arguments:
        title -- (optional) title text of new subplot (default: '')
        orientation -- (optional) direction to add subplot, valid data is:
            wx.VERTICAL or wx.HORIZONTAL (default: Graph.orientation)
        
        return -- index of created plot
        """
        
        orientation = self.orientation if orientation == None else orientation
        count = self.layout[-1] + 1
        size = self.layout[0] * self.layout[1]
        #check if there is room for another subplot
        if size >= count:
            self.layout = self.layout[:2] + (count, )
        else:
            #expand layout
            if orientation == wx.VERTICAL:
                self.layout = (self.layout[0] + 1, self.layout[1], count)
            else:
                self.layout = (self.layout[0], self.layout[1] + 1, count)
            
        #Clear away old axes
        self.sub_plots.clear_axes()
        #recreate axes and add new one
        size = self.layout[0] * self.layout[1]
        for i in range(1,count+1):
            if count < size and i > self.layout[1] * (self.layout[0]-1):
                #expand graphs on last row
                exp_layout = (self.layout[0], self.layout[1] - (size-count))
                exp_i = exp_layout[0] * exp_layout[1] - (count - i)
                
                axes = self.figure.add_subplot(*exp_layout + (exp_i,))
                #check if to rebind axes or append new object
                if i == count:
                    self.sub_plots.append(axes, title)
                else:
                    self.sub_plots.set_axes(axes, i-1)
            else:
                axes = self.figure.add_subplot(*self.layout[:2] + (i, ))
                #check if to rebind axes or append new object
                if i == count:
                    self.sub_plots.append(axes, title)
                else:
                    self.sub_plots.set_axes(axes, i-1)
        
        self.canvas.draw()
        #return sub-plot index
        return count - 1
                
        
    def cleanse_fontcache(self):
        """
        Shouldn't be used. Can fix bug when using frozen programs under windows.
        Better to modify the setup script so that font files are left out of the
        matplotlib data files.
        """
        file_path = path.join(path.expanduser('~'), \
                    '.matplotlib', \
                    'fontList.cache')
        if path.exists(file_path):
            remove(file_path)
    
    
    def clear_lines(self, index = 0):
        """
        Removes all lines from the selected sub-plot
        
        keyword arguments:
        index -- (optional) index of subplot, which should be cleared from all
            lines (default: 0)
        """
        self.sub_plots(index).axes.cla()
        self.sub_plots(index).lines = []
        
    def get_lines(self, index = 0):
        """
        Retrieves all the lines of the specified sub-plot
        
        keyword arguments:
        index -- (optional) index of subplot from, which the lines should be
            retrieved from (default: 0)
        """
        return self.sub_plots(index).axes.get_lines()
        
        
    def redraw(self, x, y,
            index = 0,
            hold=False,
            xmin = None, ymin = None,
            limits=None,
            limit_selector = None,
            alpha = 1.0,
            draw = True,
            **kwarg):
        """
        Updates plot with new vectors
        keyword arguments:
        x -- the x-axis values
        y -- the y-axis values
        index -- (optional) index of subplot to plot the vector in (default: 0)
        hold -- (optional) should old vectors be kept (default: False)
        xmin -- (optional) set minimum value of x-axis (default: None)
        ymin -- (optional) set minimum value of y-axis (default: None)
        limits -- (optional) list to set the limits of x and y-axis. overrides
            the xmin and ymin arguments (default: None)
        limit_selector -- (optional) a fucntion which given the arguments:
            *(x1, x2, y1, y2) will return a list with the axis limits
            overrides the xmin, ymin and the limits argument (default: None)
            e.g. sel = lambda x1, x2, y1, y2: [x1, x2, min(y1, 0), y2]
        alpha -- (optional) sets the alpha of the line (default: 1.0)
        draw -- (optional) should the canvas be updated to show the new lines
        
        **kwarg -- all extra keyword arguments are sent to the plot function
        """
        #set plot to update
        try:
            plot = self.sub_plots(index)
        except IndexError:
            raise(IndexError,
                "The sub-plot of index:{0:d} doesn't exist".format(index))
            
        plot.axes.hold(hold)
        lines = plot.axes.plot(x,y, alpha = alpha, **kwarg)
        
        
        #Create a legend if label was given
        if not lines[0].get_label()[0] == "_":
            plot.axes.legend() #label must be sent through kwarg
        
        #if not ymin == None:
        x1, x2, y1, y2 = plot.axes.axis()
        ymin = y1 if ymin == None else ymin
        xmin = x1 if xmin == None else xmin
        plot.axes.axis([xmin, x2, ymin, y2])
        if not limits == None:
            plot.axes.axis(limits)
        if not limit_selector == None:
            plot.axes.axis(limit_selector(x1, x2, y1, y2))
        
        #plot it
        #plot.axes.grid(self.sub_plots.grid)
        plot.reload()
        if draw:
            self.canvas.draw()
        #store lines in a list
        #return line object
        #plot.lines.extend(lines)
        return lines
        
        
    def redraw_secondary_y(self, x, y, index = 0, **kwarg):
        """
        Update secondary y-axis with a new vector
        keyword arguments:
        x -- the x-axis values
        y -- the y-axis values
        index -- (optional) index of subplot to plot the vector in (default: 0)
        style -- (optional) line style (default: 'r.')
        **kwarg -- all extra keyword arguments are sent to the plot function
        """
        sub_plot = self.sub_plots(index)
        lines = sub_plot.y2_axis.plot(x, y, style, **kwarg)
        #show it
        self.canvas.draw()
        return lines
    
    def remove_lines(self, lines, index = 0):
        """
        Re
        
        keyword arguments:
        lines -- A list of matplotlib lines as given by the redraw function
        index -- (optional) index of subplot from, which the lines should be
            retrieved from (default: 0)
        """
        for line in lines:
            self.sub_plots(index).remove_line(line)
        self.canvas.draw()
        
    def remove_subplot(self):
        """
        Removes the last sub-plot.
        Note that plots in the last row aren't expanded to fill the entire row.
        """
        count = self.layout[-1] - 1
        if count < 0:
            raise ValueError, "There is no sub-plot to remove"
        
        self.layout = (self.layout[0], self.layout[1], count)
        
        if count > 0:
            layout_change = True
            #check if layout of plots can be decreased
            if self.layout[0] > 1 and self.layout[1] > 1:
                if self.layout[0] < self.layout[1]:
                    lrg = 1
                    sml = 0
                else:
                    lrg = 0
                    sml = 1
                #check if a decrease is possible on the major axis
                size = (self.layout[lrg] - 1) * (self.layout[sml])
                if size >= count:
                    if lrg == 0:
                        self.layout = (self.layout[0] - 1, self.layout[1], count)
                    else:
                        self.layout = (self.layout[0], self.layout[1] - 1, count)
                else:
                    #check the minor axis
                    size = (self.layout[lrg]) * (self.layout[sml] - 1)
                    if size >= count:
                        if sml == 0:
                            self.layout = (self.layout[0] - 1, self.layout[1], count)
                        else:
                            self.layout = (self.layout[0], self.layout[1] - 1, count)
                    else:
                        layout_change = False
            else:
                if self.layout[0] > self.layout[1]:
                    self.layout = (self.layout[0] - 1, self.layout[1], count)
                else:
                    self.layout = (self.layout[0], self.layout[1] - 1, count)
        else:
            layout_change = False
        
        #remove the last sub-plot
        self.sub_plots.remove()
        if layout_change:
            #clear figure and recreate plots
            self.sub_plots.clear_axes()
            
            for i in range(1,count+1):
                plot_index = i - 1
                self.sub_plots.set_axes(self.figure.add_subplot(*self.layout[:2] + (i, )), plot_index)
       
        #redraw screen
        self.canvas.draw()
    
    
    def set_formatter(self, frmt = 'sci', axes = 'all', useOffset = True,
            limits = (-3, 3), index=None):
        """
        Sets the formatter of the axes. Default is to set scientific notation
        for all axes of all subplots.
        
        keyword arguments:
        frmt -- Sets the type of formatter used, valid values are:
            'sci', 'log', 'plain' (default: 'sci')
        axes -- which axes should the formatter be used for, valid values are:
            'all', 'x', 'y' (default: 'all')
        useOffset -- Should offset be used to make the tickers more meaningful 
            (default: True)
        limits -- Limits for scientific notation as a tuple (default: (-3, 3))
        index -- a integer or list of integers with the index of sub-plots for
            which the formatter should set. When 'None' the formatter is set
            for all sub-plots (default: None)
        """
        
        frmt = frmt.lower()
        axes = axes.lower()
        
        if frmt == 'log':
            formatter = LogFormatter()
        else:
            sci = frmt == 'sci'
            formatter = ScalarFormatter(useOffset = useOffset)
            formatter.set_powerlimits(limits)
            formatter.set_scientific(sci)
            
        # format axes
        if type(index) == list:
            for i in index:
                self.sub_plots(i).set_formatter(formatter, axes)
        elif type(index) == int:
            self.sub_plots(index).set_formatter(formatter, axes)
        else:
            # do all
            for sub_plot in self.sub_plots.sub_plots:
                sub_plot.set_formatter(formatter, axes)
            #set default formatter
            self.sub_plots.set_default_formatter(formatter, axes)
        
        # redraw screen
        self.canvas.draw()
        
        
    def set_label(self, xlabel='', ylabel='', index = None):
        """
        Set labels of the specified plot axes
        
        keyword arguments:
        xlabel -- (optional) sets the label of the x-axis (default: '')
        ylabel -- (optional) sets the label of the y-axis (default: '')
        index -- (optional) a integer or list of integers with the index of 
            sub-plots for which a the labels should be set. When 'None' the
            labels is set for all sub-plots (default: None)
        """
        
        if type(index) == list:
            for i in index:
                self.sub_plots.set_label(xlabel, ylabel, i)
        elif type(index) == int:
            self.sub_plots.set_label(xlabel, ylabel, index)
        else:
            # do all
            count = self.layout[-1]
            for i in range(count):
                self.sub_plots.set_label(xlabel, ylabel, i)
        # Redraw screen
        self.canvas.draw()
        
        
    def set_limits(self, limits, index = 0):
        """
        Sets the axis limits of the specified sub-plot
        
        keyword arguments:
        limits -- A list to set the limits of x and y-axis: [x1, x2, y1, y2]
        index -- (optional) index of subplot to set axis limits (default: 0)
        """
        self.sub_plots(index).axes.axis(limits)
        self.canvas.draw()
        
        
    def set_title(self, titles = '', index = 0):
        """
        Set titles of the sub-plots
        
        keyword arguments:
        titles -- should be a list of title strings or a single
            string, in which case an index should be supplied (default: '')
        index -- (optional) Is only needed when titles is a single string
            specifies for which sub-plot to set the title
        """
        if type(titles) == list:
            for i, title in enumerate(titles):
                self.sub_plots(i).set_title(title)
        else:
            self.sub_plots(index).set_title(titles)
        
        self.canvas.draw()
        
        
    def update(self):
        """
        Will send a draw command to the canvas uppdating the graphs
        """
        self.canvas.draw()
        self.canvas.flush_events()
        
    def update_plot_only(self, lines, index=0):
        """
        Will redraw the background and plot lines only
        
        keyword arguments:
        lines -- a list of line objects for the plot
        index -- (optional) index of subplot to set axis limits (default: 0)
        """
        try:
            plot = self.sub_plots(index)
        except IndexError:
            raise(IndexError,
                "The sub-plot of index:{0:d} doesn't exist".format(index))
        ax = plot.axes
        #draw the background
        ax.draw_artist(ax.patch)
        #draw the lines
        for line in lines:
            ax.draw_artist(line)
        #draw the x grid
        for line in ax.get_xgridlines():
            ax.draw_artist(line)
        #draw the y grid
        for line in ax.get_ygridlines():
            ax.draw_artist(line)
        #redraw display selectively
        self.canvas.blit(ax.bbox)
        #should flush_events be used a bunch of erros seem to occur on this?
        #self.canvas.flush_events()
        
示例#23
0
class PlotFigure(wx.Frame):
    """Matplotlib wxFrame with animation effect"""
    global t
    global static_map, fix_point, grid_point

    def __init__(self):

        wx.Frame.__init__(self,
                          None,
                          wx.ID_ANY,
                          title="!!!",
                          size=(1000, 1000))
        # Matplotlib Figure
        self.fig = Figure((10, 10), 100)
        # bind the Figure to the backend specific canvas
        self.canvas = FigureCanvas(self, wx.ID_ANY, self.fig)
        # add a subplot
        self.ax = self.fig.add_subplot(111)
        # limit the X and Y axes dimensions
        self.ax.set_ylim([-10, 10])
        self.ax.set_xlim([-5, 15])

        self.ax.set_autoscale_on(False)
        # self.ax.set_xticks([])
        # # we want a tick every 10 point on Y (101 is to have 10
        # self.ax.set_yticks(range(0, 101, 10))
        # # disable autoscale, since we don't want the Axes to ad
        # # draw a grid (it will be only for Y)
        self.ax.grid(True)
        # generates first "empty" plots
        # self.user = [None] * POINTS
        self.user = self.ax.plot(static_map.data[0, :],
                                 static_map.data[1, :],
                                 'o',
                                 label='map')

        # add the legend
        self.ax.legend(loc='upper center',
                       ncol=4,
                       prop=font_manager.FontProperties(size=10))
        # force a draw on the canvas()
        # trick to show the grid and the legend
        self.canvas.draw()
        # save the clean background - everything but the line
        # is drawn and saved in the pixel buffer background
        self.bg = self.canvas.copy_from_bbox(self.ax.bbox)
        # bind events coming from timer with id = TIMER_ID
        # to the onTimer callback function
        wx.EVT_TIMER(self, TIMER_ID, self.onTimer)

    def onTimer(self, evt):
        """callback function for timer events"""
        # restore the clean background, saved at the beginning
        self.canvas.restore_region(self.bg)
        # update the data
        # temp = np.random.randint(10, 80)
        # self.user = self.user[1:] + [temp]
        # update the plot
        # self.l_user.set_ydata(self.user)
        self.user, = self.ax.plot(fix_point.point[0, :], fix_point.point[1, :],
                                  'or')
        # just draw the "animated" objects
        self.ax.draw_artist(self.user)
        ###
        global odom_msg
        laser_range = 10
        xlim = [-0.2, laser_range]
        ylim = [-laser_range / 2.0, laser_range / 2.0]
        frame_ori = np.array([[xlim[0], ylim[0]], [xlim[0], ylim[1]],
                              [xlim[1], ylim[1]], [xlim[1], ylim[0]],
                              [xlim[0], ylim[0]]]).transpose()
        T = np.array([[odom_msg.pose.pose.position.x],
                      [odom_msg.pose.pose.position.y]])
        R = quaternion_matrix((odom_msg.pose.pose.orientation.x,
                               odom_msg.pose.pose.orientation.y,
                               odom_msg.pose.pose.orientation.z,
                               odom_msg.pose.pose.orientation.w))[0:2, 0:2]
        frame = np.dot(R, frame_ori) + np.dot(T,
                                              np.ones((1, frame_ori.shape[1])))
        # delta = 0.3
        # xlim = [fix_point.point[0, :].min() - delta, fix_point.point[0, :].max() + delta]
        # ylim = [fix_point.point[1, :].min() - delta, fix_point.point[1, :].max() + delta]
        # frame = np.array([[xlim[0], ylim[0]],[xlim[0], ylim[1]],[xlim[1], ylim[1]],[xlim[1], ylim[0]],[xlim[0], ylim[0]]]).transpose()
        self.user, = self.ax.plot(frame[0, :], frame[1, :], 'k')
        # just draw the "animated" objects
        self.ax.draw_artist(self.user)
        ###
        # It is used to efficiently update Axes data (axis ticks, labels, etc are not updated)
        self.user, = self.ax.plot(grid_point.point[0, :],
                                  grid_point.point[1, :],
                                  'og',
                                  label='2')
        # just draw the "animated" objects
        self.ax.draw_artist(self.user)
        # It is used to efficiently update Axes data (axis ticks, labels, etc are not updated)
        self.canvas.blit(self.ax.bbox)

    def __del__(self):
        t.Stop()
示例#24
0
class NaoPanel(wx.Panel):
    def _init_ctrls(self, prnt):
        # generated method, don't edit
        wx.Panel.__init__(self,
                          id=wxID_LEFTPANEL,
                          name='NaoPanel',
                          parent=prnt,
                          pos=wx.Point(208, 8),
                          size=wx.Size(800, 400),
                          style=wx.NO_BORDER | wx.TAB_TRAVERSAL)
        self.SetClientSize(wx.Size(800, 400))
        self.SetBackgroundColour(wx.Colour(0, 0, 255))
        self.Bind(wx.EVT_PAINT, self.OnNaoPanelPaint)

    def __init__(self, parent, id, pos, size, style, name):
        self._init_ctrls(parent)
        ##Create a matplotlib figure/canvas in this panel
        ##the background colour will be the same as the panel
        ##the size will also be the same as the panel
        ##calculate size in inches
        pixels_width, pixels_height = self.GetSizeTuple()
        self.dpi = 96.0
        inches_width = pixels_width / self.dpi
        inches_height = pixels_height / self.dpi

        ##calculate colour in RGB 0 to 1
        colour = self.GetBackgroundColour()
        self.fig = Figure(figsize=(inches_width,inches_height), dpi = self.dpi\
            ,facecolor=(colour.Red()/255.0, colour.Green()/255.0, colour.Blue()/255.0)\
            ,edgecolor=(colour.Red()/255.0, colour.Green()/255.0, colour.Blue()/255.0))

        ##left : the left side of the subplots of the figure
        ##     |      right : the right side of the subplots of the figure
        ##     |      bottom : the bottom of the subplots of the figure
        ##     |      top : the top of the subplots of the figure
        ##     |      wspace : the amount of width reserved for blank space between subplots
        ##     |      hspace : the amount of height reserved for white space between subplots
        ##     |

        self.canvas = FigureCanvasWxAgg(self, -1, self.fig)

        ##now put everything in a sizer
        sizer = wx.BoxSizer(wx.VERTICAL)
        # This way of adding to sizer allows resizing
        sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
        self.SetSizer(sizer)
        self.Fit()

        ##now finally create the actual plot
        ##self.axes = self.fig.add_subplot(111)
        self.axes = self.fig.add_axes(
            (0.08, 0.08, 0.90, 0.85))  ##left,bottom,width,height
        self.naohistoryplot = self.axes.plot([0, 0], [0, 0],
                                             'r',
                                             animated=True)
        self.naohistoryx = list()
        self.naohistoryy = list()

        self.positionmeasurementplot = self.axes.plot([0, 0], [0, 0],
                                                      'blue',
                                                      marker='o',
                                                      markersize=5,
                                                      linewidth=0,
                                                      markeredgewidth=0,
                                                      animated=True)
        self.orientationmeasurementplot = self.axes.plot([0, 0], [0, 0],
                                                         'blue',
                                                         linewidth=2,
                                                         animated=True)
        self.shapeplot = self.axes.plot([0, 0], [0, 0],
                                        'blue',
                                        marker='o',
                                        markersize=2,
                                        linewidth=0,
                                        markeredgewidth=0,
                                        animated=True)
        self.estimateplot = self.axes.plot([0, 0], [0, 0],
                                           'red',
                                           linewidth=2,
                                           animated=True)
        self.particleplot = self.axes.quiver([0, 0], [0, 0], [1, 1],
                                             [0.5, -0.5], [1, 1],
                                             cmap=pylab.gray(),
                                             animated=True)

        ##plot formatting
        self.axes.set_title('Nao Image', fontsize='10')
        self.axes.set_xlabel('y (cm)', fontsize='10')
        self.axes.set_ylabel('x (cm)', fontsize='10')
        ticks = numpy.arange(-25, 25 + 5, 5)
        labels = [str(tick) for tick in ticks]
        self.axes.set_yticks(ticks)
        self.axes.set_yticklabels(labels, fontsize=8)
        self.axes.set_ylim(ticks[0], ticks[-1])
        ticks = -numpy.arange(-50, 50 + 5, 5)
        labels = [str(tick) for tick in ticks]
        self.axes.set_xticks(ticks)
        self.axes.set_xticklabels(labels, fontsize=8)
        self.axes.set_xlim(ticks[0], ticks[-1])

        self.canvas.draw()
        self.canvas.gui_repaint()

        # save the clean slate background -- everything but the animated line
        # is drawn and saved in the pixel buffer background
        self.background = self.canvas.copy_from_bbox(self.axes.bbox)

        #self.leftedgeplot = self.axes.plot([0,0],[0,0], 'orange', marker='o', markersize=4, linewidth=0, animated=True)
        #self.rightedgeplot = self.axes.plot([0,0],[0,0], 'purple', marker='o', markersize=4, linewidth=0, animated=True)

    def setNaoFinder(self, finder):
        """ """
        self.NAOFinder = finder

    def setLocalisation(self, localisation):
        """ """
        self.Localisation = localisation

    def updateData(self, data):
        """updateData. Updates the data that this panel is displaying.
        """
        # Note the x values are plotted on the y-axis, and the y values are plotted on the x-axis
        naox = self.Localisation.X
        naoy = self.Localisation.Y
        naoorientation = self.Localisation.Orientation

        measurednaox = self.NAOFinder.NaoX
        measurednaoy = self.NAOFinder.NaoY
        measurednaoorientation = self.NAOFinder.NaoOrientation

        self.positionmeasurementplot[0].set_data([measurednaoy, measurednaoy],
                                                 [measurednaox, measurednaox])
        self.orientationmeasurementplot[0].set_data([
            measurednaoy + 10 * numpy.sin(measurednaoorientation - numpy.pi),
            measurednaoy + 10 * numpy.sin(measurednaoorientation)
        ], [
            measurednaox + 10 * numpy.cos(measurednaoorientation - numpy.pi),
            measurednaox + 10 * numpy.cos(measurednaoorientation)
        ])
        self.shapeplot[0].set_data(self.NAOFinder.ShapeY,
                                   self.NAOFinder.ShapeX)
        self.naohistoryx.append(naox)
        self.naohistoryy.append(naoy)
        if len(self.naohistoryx) > 20:
            del self.naohistoryx[0]
            del self.naohistoryy[0]
        self.naohistoryplot[0].set_data(self.naohistoryy, self.naohistoryx)

        self.estimateplot[0].set_data(
            [naoy, naoy + 10 * numpy.sin(self.Localisation.Orientation)],
            [naox, naox + 10 * numpy.cos(self.Localisation.Orientation)])
        #self.particleplot = self.axes.quiver(numpy.array(self.Localisation.States[:,Localisation.Y]), numpy.array(self.Localisation.States[:,Localisation.X]), -numpy.sin(self.Localisation.States[:,Localisation.THETA]), numpy.cos(self.Localisation.States[:,Localisation.THETA]), 1.0 - self.Localisation.GUIWeights, headlength=10, headwidth=10, width=0.001, scale=50.0)

        self.axes.set_xlim(naoy + 50, naoy - 50)
        self.axes.set_ylim(naox - 25, naox + 25)
        # restore the clean slate background
        self.canvas.restore_region(self.background)
        # just draw the animated artist
        self.axes.draw_artist(self.shapeplot[0])
        #self.axes.draw_artist(self.particleplot)
        self.axes.draw_artist(self.naohistoryplot[0])
        self.axes.draw_artist(self.orientationmeasurementplot[0])
        self.axes.draw_artist(self.positionmeasurementplot[0])
        self.axes.draw_artist(self.estimateplot[0])

        # just redraw the axes rectangle
        self.canvas.blit(self.axes.bbox)

        #leftx = list()
        #lefty = list()
        #for leftedge in self.NAOFinder.LeftEdges:
        #    leftx.append(data[0][leftedge])
        #    lefty.append(data[1][leftedge])

        #rightx = list()
        #righty = list()
        #for rightedge in self.NAOFinder.RightEdges:
        #    rightx.append(data[0][rightedge])
        #    righty.append(data[1][rightedge])

        #self.leftedgeplot[0].set_data(lefty, leftx)
        #self.rightedgeplot[0].set_data(righty, rightx)

    def OnNaoPanelPaint(self, event):
        pass
class CartesianPanel(wx.Panel):
    def _init_ctrls(self, prnt):
        # generated method, don't edit
        wx.Panel.__init__(self, id=wxID_LEFTPANEL, name='CartesianPanel',
              parent=prnt, pos=wx.Point(8, 8), size=wx.Size(200, 400),
              style=wx.NO_BORDER | wx.TAB_TRAVERSAL)
        self.SetClientSize(wx.Size(200, 400))
        self.SetBackgroundColour(wx.Colour(0, 0, 255))
        self.Bind(wx.EVT_PAINT, self.OnCartesianPanelPaint)

    def __init__(self, parent, id, pos, size, style, name):
        self._init_ctrls(parent)
    ##Create a matplotlib figure/canvas in this panel
    ##the background colour will be the same as the panel
    ##the size will also be the same as the panel
        ##calculate size in inches
        pixels_width,pixels_height = self.GetSizeTuple()
        self.dpi = 96.0
        inches_width = pixels_width/self.dpi
        inches_height = pixels_height/self.dpi
        
        ##calculate colour in RGB 0 to 1
        colour = self.GetBackgroundColour()
        self.fig = Figure(figsize=(inches_width,inches_height), dpi = self.dpi\
            ,facecolor=(colour.Red()/255.0, colour.Green()/255.0, colour.Blue()/255.0)\
            ,edgecolor=(colour.Red()/255.0, colour.Green()/255.0, colour.Blue()/255.0))
            
        ##left : the left side of the subplots of the figure
##     |      right : the right side of the subplots of the figure
##     |      bottom : the bottom of the subplots of the figure
##     |      top : the top of the subplots of the figure
##     |      wspace : the amount of width reserved for blank space between subplots
##     |      hspace : the amount of height reserved for white space between subplots
##     |      

        self.canvas = FigureCanvasWxAgg(self, -1, self.fig)

        ##now put everything in a sizer
        sizer = wx.BoxSizer(wx.VERTICAL)
        # This way of adding to sizer allows resizing
        sizer.Add(self.canvas, 1, wx.LEFT|wx.TOP|wx.GROW)
        self.SetSizer(sizer)
        self.Fit()
        
        ##now finally create the actual plot
        ##self.axes = self.fig.add_subplot(111)
        self.axes = self.fig.add_axes((0.16,0.08,0.90,0.85))               ##left,bottom,width,height
        self.plot = self.axes.plot([0,0],[0,0], 'b', animated=True)
        self.naohistoryplot = self.axes.plot([0,0],[0,0], 'r', animated=True)
        self.naohistoryx = list()
        self.naohistoryy = list()
        self.naoplot = self.axes.plot([0,0],[0,0], 'r', marker='o', markersize=4, animated=True)
        
        self.leftedgeplot = self.axes.plot([0,0],[0,0], 'orange', marker='o', markersize=4, linewidth=0, animated=True) 
        self.rightedgeplot = self.axes.plot([0,0],[0,0], 'purple', marker='o', markersize=4, linewidth=0, animated=True) 

        ##plot formatting
        self.axes.set_title('Laser Image', fontsize='10')
        #self.axes.set_xlabel('y (cm)', fontsize='10')
        #self.axes.set_ylabel('x (cm)', fontsize='10')
        ticks = numpy.arange(-450, 450+100, 100)
        labels = [str(tick) for tick in ticks]
        self.axes.set_yticks(ticks)
        self.axes.set_yticklabels(labels, fontsize=8)
        self.axes.set_ylim(ticks[0], ticks[-1])
        ticks = numpy.arange(0, 450+100, 100)
        labels = [str(tick) for tick in ticks]
        self.axes.set_xticks(ticks)
        self.axes.set_xticklabels(labels,fontsize=8)
        self.axes.set_xlim(ticks[0], ticks[-1])
        
        self.canvas.draw()
        self.canvas.gui_repaint()
        
        # save the clean slate background -- everything but the animated line
        # is drawn and saved in the pixel buffer background
        self.background = self.canvas.copy_from_bbox(self.axes.bbox)
        
    def setNaoFinder(self, finder):
        """ """
        self.NAOFinder = finder
    
    def updateData(self, data, naox, naoy):
        """updateData. Updates the data that this panel is displaying.
        """
        self.x = data[0]
        self.y = data[1]
        
        self.plot[0].set_data(self.x, self.y)
        self.naoplot[0].set_data([naox,naox], [naoy, naoy])
        self.naohistoryx.append(naox)
        self.naohistoryy.append(naoy)
        if len(self.naohistoryx) > 400:
            del self.naohistoryx[0]
            del self.naohistoryy[0]
        self.naohistoryplot[0].set_data(self.naohistoryx, self.naohistoryy)
        
        leftx = list()
        lefty = list()
        for leftedge in self.NAOFinder.LeftEdges:
            leftx.append(data[0][leftedge])
            lefty.append(data[1][leftedge])
        
        rightx = list()
        righty = list()
        for rightedge in self.NAOFinder.RightEdges:
            rightx.append(data[0][rightedge])
            righty.append(data[1][rightedge])
        
        self.leftedgeplot[0].set_data(leftx, lefty)
        self.rightedgeplot[0].set_data(rightx, righty)
                
        # restore the clean slate background
        self.canvas.restore_region(self.background)
        # just draw the animated artist
        self.axes.draw_artist(self.plot[0])
        self.axes.draw_artist(self.naoplot[0])
        self.axes.draw_artist(self.naohistoryplot[0])
        
        self.axes.draw_artist(self.leftedgeplot[0])
        self.axes.draw_artist(self.rightedgeplot[0])

        # just redraw the axes rectangle
        self.canvas.blit(self.axes.bbox)

    def OnCartesianPanelPaint(self, event):
        pass
示例#26
0
class MonitorFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, parent=None, id=-1,
                title=__app_name__,
                pos=(10, 10), size=(1200, 620))
        self.LoadParam()
        self.BuildUI()
        self.InitUiParam()
        self.proc_name_value.SetFocus()
        self.t = wx.Timer(self, TIMER_ID)

    def LoadParam(self):
        self.settings = param.load_param('config.json')
        if 'xmin' not in self.settings:
            self.settings['xmin'] = 0
        if 'xmax' not in self.settings:
            self.settings['xmax'] = self.settings['points']

    def BuildUI(self):
        # ------- config box ------------
        # process name
        self.proc_name_label = wx.StaticText(parent=self, label='Process Name: ', style=wx.ALIGN_CENTER)
        self.proc_name_value = wx.TextCtrl(parent=self, value='', style=wx.TE_PROCESS_ENTER)
        self.proc_name_box = wx.BoxSizer(wx.HORIZONTAL)
        self.proc_name_box.Add(self.proc_name_label, 1, wx.ALIGN_CENTER, 5, 0)
        self.proc_name_box.Add(self.proc_name_value, 2, wx.ALIGN_CENTER, 5, 0)
        # input response
        self.proc_msg = wx.StaticText(parent=self, label='', size=(800, 30), style=wx.ALIGN_LEFT|wx.ST_NO_AUTORESIZE)
        # add to config box
        self.configBox= wx.BoxSizer(wx.VERTICAL)
        self.configBox.Add(self.proc_name_box, 1, wx.LEFT|wx.ALIGN_CENTER_VERTICAL, 5, 0)
        self.configBox.Add(self.proc_msg, 1, wx.LEFT|wx.ALIGN_CENTER_VERTICAL, 5, 0)

        # ------- control box ------------
        self.startBtn = wx.Button(parent=self, label="Start", size=(60, 60))
        self.stopBtn = wx.Button(parent=self, label="Stop")
        self.showBtn = wx.Button(parent=self, label="Show")
        self.controlBox = wx.BoxSizer(wx.HORIZONTAL)
        self.controlBox.Add(self.startBtn, 1, wx.ALL|wx.EXPAND|wx.ALIGN_CENTER_VERTICAL, 5, 0)
        self.controlBox.Add(self.showBtn, 1, wx.ALL|wx.EXPAND|wx.ALIGN_CENTER_VERTICAL, 5, 0)
        self.controlBox.Add(self.stopBtn, 1, wx.ALL|wx.EXPAND|wx.ALIGN_CENTER_VERTICAL, 5, 0)

        self.startBtn.Enable()
        self.stopBtn.Disable()

        # ------- tool box(config, control) -------
        self.toolbox = wx.BoxSizer(wx.HORIZONTAL)
        self.toolbox.AddSpacer(20)
        self.toolbox.Add(self.configBox, 5, wx.ALL|wx.ALIGN_CENTER, 5, 0)
        self.toolbox.Add(self.controlBox, 2, wx.ALL|wx.ALIGN_CENTER, 5, 0)
        # ------- track log box -------------------
        self.track_log = wx.TextCtrl(parent=self, style=wx.TE_AUTO_SCROLL | wx.TE_MULTILINE)
        self.track_log.SetEditable(False)
        self.fig = self.InitPlotUI()
        self.canvas = FigureCanvas(self, wx.ID_ANY, self.fig)
        self.canvas.draw()
        self.bg = self.canvas.copy_from_bbox(self.ax.bbox)
        self.dispbox = wx.BoxSizer(wx.HORIZONTAL)
        self.dispbox.Add(self.track_log, 1, wx.ALL|wx.EXPAND, 5, 5)
        self.dispbox.Add(self.canvas, 0, wx.ALL|wx.EXPAND, 5, 5)
        # ------- main box(tool, tracklog) --------
        self.mainbox = wx.BoxSizer(wx.VERTICAL)
        self.mainbox.Add(self.toolbox, 1, wx.NORMAL, 0, 0)
        self.mainbox.Add(self.dispbox, 0, wx.EXPAND, 5, 5)

        self.SetSizer(self.mainbox)
        self.CenterOnScreen()

        self.startBtn.Bind(wx.EVT_BUTTON, self.OnStartTrack)
        self.stopBtn.Bind(wx.EVT_BUTTON, self.OnStopTrack)
        self.proc_name_value.Bind(wx.EVT_TEXT, self.OnProcInputChanged)
        self.proc_name_value.Bind(wx.EVT_TEXT_ENTER, self.OnStartTrack)
        self.Bind(wx.EVT_ACTIVATE, self.OnWindowActivate)
        wx.EVT_TIMER(self, TIMER_ID, self.onTimer)

    def InitUiParam(self):
        self.proc_name_value.SetValue(self.settings['process_name'])
        self.proc_tracking = None
        self.is_track_running = False

    def OnStartTrack(self, event):
        if self.is_track_running:
            return

        proc_name = self.proc_name_value.GetValue().strip()

        if 0 == len(proc_name):
            msg = 'Please input a process name!'
            dlg = wx.MessageDialog(None, msg, "%s Error" % __app_name__, wx.ICON_ERROR)
            dlg.ShowModal()
            return None

        if self.proc_tracking is None:
            self.MatchProcName(proc_name)
            if self.proc_tracking is None:
                msg = 'No such process!\nGo on to track %s?' % proc_name
                dlg = wx.MessageDialog(None, msg, "%s Error" % __app_name__, wx.YES_NO|wx.ICON_QUESTION)
                if dlg.ShowModal() != wx.ID_YES:
                    return None

        # transfer button status
        self.startBtn.Disable()
        self.showBtn.Disable()
        self.stopBtn.Enable()
        self.proc_name_value.Disable()
        # clear log
        self.track_log.SetValue('')
        wx.CallAfter(self.StartTrack, self.proc_tracking, self.proc_name_value.GetValue())

    def update_log(self, disp_data):
        global _log_cache
        _log_cache.append(disp_data)
        if len(_log_cache) >= (1000.0/self.settings['interval']):
            wx.CallAfter(self.track_log.AppendText, '%s | %.4f MB\n' % (timestamp(), avg(_log_cache)))
            _log_cache = []

    def StartTrack(self, proc, proc_name):
        self.is_track_running = True
        self.t.Start(self.settings['interval'])

    def OnStopTrack(self, event):
        self.startBtn.Enable()
        self.showBtn.Enable()
        self.stopBtn.Disable()
        self.proc_name_value.Enable()
        # stop thread
        self.t.Stop()
        self.is_track_running = False

    def OnWindowActivate(self, event):
        if not self.is_track_running:
            self.MatchProcName(self.proc_name_value.GetValue().strip())

    def OnProcInputChanged(self, event):
        self.MatchProcName(self.proc_name_value.GetValue().strip())

    def MatchProcName(self, pname):
        self.proc_tracking = None
        if 0 == len(pname):
            self.proc_msg.SetLabel('Please input a process name')
            return None
        procs = monitor.get_procs(pname)
        if 0 == len(procs):
            self.proc_msg.SetLabel('Process not exists or AccessDenied')
            return None
        self.proc_tracking = procs[0]
        if len(procs) > 1:
            self.proc_msg.SetLabel('Warning! Multi Processes Match. use %s' % format_proc(self.proc_tracking))
        else:
            self.proc_msg.SetLabel(format_proc(self.proc_tracking))
        return self.proc_tracking

    def InitPlotUI(self):
        plot_points = self.settings['points']
        fig = Figure(figsize=(9, 5), dpi=100)
        self.ax = fig.add_subplot(111)

        self.ax.set_ylim([self.settings['ymin'], self.settings['ymax']])
        self.ax.set_xlim([self.settings['xmin'], self.settings['xmax']])
        self.ax.set_autoscale_on(False)

        self.ax.set_xticks([])
        self.ax.set_yticks(range(self.settings['ymin'], self.settings['ymax']+1, self.settings['ystep']))

        self.ax.grid(True)

        self.mem_rss_data = [None] * plot_points
        self.l_mem_rss,=self.ax.plot(range(plot_points), self.mem_rss_data, label='Memory(RSS) %')

        # add the legend
        self.ax.legend(loc='upper center',
                           ncol=4,
                           prop=font_manager.FontProperties(size=10))
        return fig

    def onTimer(self, evt):
        """callback function for timer events"""
        # restore the clean background, saved at the beginning
        self.canvas.restore_region(self.bg)
        # get new perf data
        if self.proc_tracking is None:
            proc_name = self.proc_name_value.GetValue().strip()
            self.proc_tracking = monitor.find_proc(proc_name)
        rss_mem = getSizeInMb(monitor.get_rss_mem(self.proc_tracking))
        # update log
        wx.CallAfter(self.update_log, rss_mem)
        # plot
        self.mem_rss_data = self.mem_rss_data[1:] + [rss_mem]
        self.l_mem_rss.set_ydata(self.mem_rss_data)
        self.ax.draw_artist(self.l_mem_rss)
        self.canvas.blit(self.ax.bbox)
示例#27
0
class PanelGraph(wx.Panel):
    def __init__(self, panel, notify, settings, status, remoteControl):
        self.panel = panel
        self.notify = notify
        self.plot = None
        self.settings = settings
        self.status = status
        self.remoteControl = remoteControl
        self.spectrum = None
        self.isLimited = None
        self.limit = None
        self.extent = None
        self.annotate = None

        self.isDrawing = False

        self.toolTip = wx.ToolTip('')

        self.mouseSelect = None
        self.mouseZoom = None
        self.measureTable = None

        self.background = None

        self.selectStart = None
        self.selectEnd = None

        self.menuClearSelect = []

        self.measure = None
        self.show = None

        self.doDraw = False

        wx.Panel.__init__(self, panel)

        self.figure = matplotlib.figure.Figure(facecolor='white')
        self.figure.set_size_inches(0, 0)
        self.canvas = FigureCanvas(self, -1, self.figure)
        self.canvas.SetToolTip(self.toolTip)

        self.measureTable = PanelMeasure(self, settings)

        self.toolbar = NavigationToolbar(self.canvas, self, settings,
                                         self.__hide_overlay)
        self.toolbar.Realize()

        vbox = wx.BoxSizer(wx.VERTICAL)
        vbox.Add(self.canvas, 1, wx.EXPAND)
        vbox.Add(self.measureTable, 0, wx.EXPAND)
        vbox.Add(self.toolbar, 0, wx.EXPAND)
        self.SetSizer(vbox)
        vbox.Fit(self)

        self.create_plot()

        self.canvas.mpl_connect('button_press_event', self.__on_press)
        self.canvas.mpl_connect('figure_enter_event', self.__on_enter)
        self.canvas.mpl_connect('axes_leave_event', self.__on_leave)
        self.canvas.mpl_connect('motion_notify_event', self.__on_motion)
        self.canvas.mpl_connect('draw_event', self.__on_draw)
        self.canvas.mpl_connect('idle_event', self.__on_idle)
        self.Bind(wx.EVT_SIZE, self.__on_size)

        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.__on_timer, self.timer)

    def __set_fonts(self):
        axes = self.plot.get_axes()
        if axes is not None:
            axes.xaxis.label.set_size('small')
            axes.yaxis.label.set_size('small')
            if self.settings.display == Display.SURFACE:
                axes.zaxis.label.set_size('small')
            axes.tick_params(axis='both', which='major', labelsize='small')
        axes = self.plot.get_axes_bar()
        if axes is not None:
            axes.tick_params(axis='both', which='major', labelsize='small')

    def __enable_menu(self, state):
        for menu in self.menuClearSelect:
            menu.Enable(state)

    def __on_press(self, event):
        if self.settings.clickTune and matplotlib.__version__ >= '1.2' and event.dblclick:
            frequency = int(event.xdata * 1e6)
            self.remoteControl.tune(frequency)
        elif isinstance(self.plot, PlotterPreview):
            self.plot.to_front()

    def __on_enter(self, _event):
        self.toolTip.Enable(False)

    def __on_leave(self, _event):
        self.toolTip.Enable(True)
        self.status.set_info('', level=None)

    def __on_motion(self, event):
        axes = self.plot.get_axes()
        axesBar = self.plot.get_axes_bar()
        xpos = event.xdata
        ypos = event.ydata
        text = ""

        if (xpos is None or ypos is None or self.spectrum is None
                or event.inaxes is None):
            spectrum = None
        elif event.inaxes == axesBar:
            spectrum = None
            level = self.plot.get_bar().norm.inverse(ypos)
            text = "{}".format(format_precision(self.settings, level=level))
        elif self.settings.display == Display.PLOT:
            timeStamp = max(self.spectrum)
            spectrum = self.spectrum[timeStamp]
        elif self.settings.display == Display.SPECT:
            timeStamp = num2epoch(ypos)
            if timeStamp in self.spectrum:
                spectrum = self.spectrum[timeStamp]
            else:
                nearest = min(self.spectrum.keys(),
                              key=lambda k: abs(k - timeStamp))
                spectrum = self.spectrum[nearest]
        elif self.settings.display == Display.SURFACE:
            spectrum = None
            coords = axes.format_coord(event.xdata, event.ydata)
            match = re.match('x=([-|0-9|\.]+).*y=([0-9|\:]+).*z=([-|0-9|\.]+)',
                             coords)
            if match is not None and match.lastindex == 3:
                freq = float(match.group(1))
                level = float(match.group(3))
                text = "{}, {}".format(
                    *format_precision(self.settings, freq, level))
        else:
            spectrum = None

        if spectrum is not None and len(spectrum) > 0:
            x = min(spectrum.keys(), key=lambda freq: abs(freq - xpos))
            if min(spectrum.keys(), key=float) <= xpos <= max(spectrum.keys(),
                                                              key=float):
                y = spectrum[x]
                text = "{}, {}".format(*format_precision(self.settings, x, y))
            else:
                text = format_precision(self.settings, xpos)

            markers = find_artists(self.figure, 'peak')
            markers.extend(find_artists(self.figure, 'peakThres'))
            hit = False
            for marker in markers:
                if isinstance(marker, Line2D):
                    location = marker.get_path().vertices[0]
                    markX, markY = axes.transData.transform(location)
                    dist = abs(math.hypot(event.x - markX, event.y - markY))
                    if dist <= 5:
                        if self.settings.display == Display.PLOT:
                            tip = "{}, {}".format(*format_precision(
                                self.settings, location[0], location[1]))
                        else:
                            tip = "{}".format(
                                format_precision(self.settings, location[0]))
                        self.toolTip.SetTip(tip)
                        hit = True
                        break
            self.toolTip.Enable(hit)

        self.status.set_info(text, level=None)

    def __on_size(self, event):
        ppi = wx.ScreenDC().GetPPI()
        size = [float(v) for v in self.canvas.GetSize()]
        width = size[0] / ppi[0]
        height = size[1] / ppi[1]
        self.figure.set_figwidth(width)
        self.figure.set_figheight(height)
        self.figure.set_dpi(ppi[0])
        event.Skip()

    def __on_draw(self, _event):
        axes = self.plot.get_axes()
        if axes is not None:
            self.background = self.canvas.copy_from_bbox(axes.bbox)
            self.__draw_overlay()

    def __on_idle(self, _event):
        if self.doDraw and self.plot.get_plot_thread() is None:
            self.__hide_overlay()
            self.doDraw = False
            if os.name == 'nt':
                threading.Thread(target=self.__draw_canvas,
                                 name='Draw').start()
            else:
                self.__draw_canvas()

    def __on_timer(self, _event):
        self.timer.Stop()
        self.set_plot(None, None, None, None, self.annotate)

    def __draw_canvas(self):
        try:
            self.isDrawing = True
            self.canvas.draw()
        except wx.PyDeadObjectError:
            pass

        self.isDrawing = False
        wx.CallAfter(self.status.set_busy, False)

    def __draw_overlay(self):
        if self.background is not None:
            self.canvas.restore_region(self.background)
            self.__draw_select()
            self.draw_measure()
            axes = self.plot.get_axes()
            if axes is not None:
                self.canvas.blit(axes.bbox)

    def __draw_select(self):
        if self.selectStart is not None and self.selectEnd is not None:
            self.mouseSelect.draw(self.selectStart, self.selectEnd)

    def __hide_overlay(self):
        if self.plot is not None:
            self.plot.hide_measure()
        self.__hide_select()

    def __hide_select(self):
        if self.mouseSelect is not None:
            self.mouseSelect.hide()

    def create_plot(self):
        if self.plot is not None:
            self.plot.close()

        self.toolbar.set_auto(True)

        if self.settings.display == Display.PLOT:
            self.plot = Plotter(self.notify, self.figure, self.settings)
        elif self.settings.display == Display.SPECT:
            self.plot = Spectrogram(self.notify, self.figure, self.settings)
        elif self.settings.display == Display.SURFACE:
            self.plot = Plotter3d(self.notify, self.figure, self.settings)
        elif self.settings.display == Display.STATUS:
            self.plot = PlotterStatus(self.notify, self.figure, self.settings)
        elif self.settings.display == Display.TIMELINE:
            self.plot = PlotterTime(self.notify, self.figure, self.settings)
        elif self.settings.display == Display.PREVIEW:
            self.plot = PlotterPreview(self.notify, self.figure, self.settings)
            self.plot.set_window(self)

        self.__set_fonts()

        self.toolbar.set_plot(self.plot)
        self.toolbar.set_type(self.settings.display)
        self.measureTable.set_type(self.settings.display)

        self.set_plot_title()
        self.figure.subplots_adjust(top=0.85)
        self.redraw_plot()
        self.plot.scale_plot(True)
        self.mouseZoom = MouseZoom(self.toolbar,
                                   plot=self.plot,
                                   callbackHide=self.__hide_overlay)
        self.mouseSelect = MouseSelect(self.plot, self.on_select,
                                       self.on_selected)
        self.measureTable.show(self.settings.showMeasure)
        self.panel.SetFocus()

    def on_select(self):
        self.hide_measure()

    def on_selected(self, start, end):
        self.__enable_menu(True)
        self.selectStart = start
        self.selectEnd = end
        self.measureTable.set_selected(self.spectrum, start, end)

    def add_menu_clear_select(self, menu):
        self.menuClearSelect.append(menu)
        menu.Enable(False)

    def draw(self):
        self.doDraw = True

    def show_measure_table(self, show):
        self.measureTable.show(show)
        self.Layout()

    def set_plot(self, spectrum, isLimited, limit, extent, annotate=False):
        if spectrum is not None and extent is not None:
            if isLimited is not None and limit is not None:
                self.spectrum = copy.copy(spectrum)
                self.extent = extent
                self.annotate = annotate
                self.isLimited = isLimited
                self.limit = limit

        if self.plot.get_plot_thread() is None and not self.isDrawing:
            self.timer.Stop()
            self.measureTable.set_selected(self.spectrum, self.selectStart,
                                           self.selectEnd)

            if isLimited:
                self.spectrum = reduce_points(spectrum, limit)

            self.status.set_busy(True)
            self.plot.set_plot(self.spectrum, self.extent, annotate)
            if self.settings.display == Display.PREVIEW:
                self.status.set_busy(False)

        else:
            self.timer.Start(200, oneShot=True)

    def set_plot_title(self):
        if len(self.settings.devicesRtl) > 0:
            gain = self.settings.devicesRtl[self.settings.indexRtl].gain
        else:
            gain = 0
        self.plot.set_title("Frequency Spectrogram\n{} - {} MHz,"
                            " gain = {}dB".format(self.settings.start,
                                                  self.settings.stop, gain))

    def redraw_plot(self):
        if self.spectrum is not None:
            self.set_plot(self.spectrum, self.settings.pointsLimit,
                          self.settings.pointsMax, self.extent,
                          self.settings.annotate)

    def set_grid(self, on):
        self.plot.set_grid(on)

    def set_selected(self, start, end):
        self.selectStart = start
        self.selectEnd = end
        self.__draw_select()

    def hide_toolbar(self, hide):
        self.toolbar.Show(not hide)

    def hide_measure(self):
        if self.plot is not None:
            self.plot.hide_measure()

    def draw_measure(self):
        if self.measure is not None and self.measure.is_valid():
            self.plot.draw_measure(self.measure, self.show)

    def update_measure(self, measure=None, show=None):
        if not measure and not show:
            self.measureTable.update_measure()
        else:
            self.measure = measure
            self.show = show
            self.__draw_overlay()

    def get_figure(self):
        return self.figure

    def get_axes(self):
        return self.plot.get_axes()

    def get_canvas(self):
        return self.canvas

    def get_toolbar(self):
        return self.toolbar

    def get_mouse_select(self):
        return self.mouseSelect

    def scale_plot(self, force=False):
        self.plot.scale_plot(force)

    def clear_plots(self):
        self.plot.clear_plots()
        self.spectrum = None
        self.doDraw = True

    def clear_selection(self):
        self.measure = None
        self.measureTable.clear_measurement()
        self.selectStart = None
        self.selectEnd = None
        self.mouseSelect.clear()
        self.__enable_menu(False)

    def close(self):
        self.plot.close()
        close_modeless()
class PlotFigure(wx.Frame):
    """Matplotlib wxFrame with animation effect"""

    def __init__(self):
        # initialize the super class
        wx.Frame.__init__(self, None, wx.ID_ANY, title="CPU Usage Monitor", size=(600, 400))

        # Matplotlib Figure
        self.fig = Figure((6, 4), 100)
        # bind the Figure to the backend specific canvas
        self.canvas = FigureCanvas(self, wx.ID_ANY, self.fig)
        # add a subplot
        self.ax = self.fig.add_subplot(111)

        # limit the X and Y axes dimensions
        # we prefer 2 separate functions for clarity
        self.ax.set_ylim([0, 100])
        self.ax.set_xlim([0, POINTS])
        # but we want a "frozen" window (defined by y/xlim functions)
        self.ax.set_autoscale_on(False)

        # we do not want ticks on X axis
        self.ax.set_xticks([])
        # we want a tick every 10 point on Y (101 is to have 100 too)
        self.ax.set_yticks(range(0, 101, 10))
        # disable autoscale, since we don't want the Axes to adapt
        # draw a grid (it will be only for Y)
        self.ax.grid(True)

        # generates first "empty" plots
        self.user = [None] * POINTS
        self.nice = [None] * POINTS
        self.sys  = [None] * POINTS
        self.idle = [None] * POINTS

        self.l_user, = self.ax.plot(range(POINTS), self.user, label='User %')
        self.l_nice, = self.ax.plot(range(POINTS), self.nice, label='Nice %')
        self.l_sys,  = self.ax.plot(range(POINTS),  self.sys,  label='Sys %')
        self.l_idle, = self.ax.plot(range(POINTS), self.idle, label='Idle %')

        # add the legend
        self.ax.legend(loc='upper center',
                           ncol=4,
                           prop=font_manager.FontProperties(size=10))

        # force a draw on the canvas()
        # trick to show the grid and the legend
        self.canvas.draw()

        # save the clean background - everything but the line
        # is drawn and saved in the pixel buffer background
        self.bg = self.canvas.copy_from_bbox(self.ax.bbox)

        # take a snapshot of CPU usage, needed for the update algorithm
        self.before = self.prepare_cpu_usage()

        # bind events coming from timer with id = TIMER_ID
        # to the onTimer callback function
        wx.EVT_TIMER(self, TIMER_ID, self.onTimer)


    def prepare_cpu_usage(self):
        """helper function to return CPU usage info"""

        # get the CPU times using psutil module
        t = p.cpu_times()

        # return only the values we're interested in
        if hasattr(t, 'nice'):
            return [t.user, t.nice, t.system, t.idle]
        else:
            # special case for Windows, without 'nice' value
            return [t.user, 0, t.system, t.idle]


    def get_cpu_usage(self):
        """Compute CPU usage comparing previous and current measurements"""

        # take the current CPU usage information
        now = self.prepare_cpu_usage()
        # compute deltas between current and previous measurements
        delta = [now[i]-self.before[i] for i in range(len(now))]
        # compute the total (needed for percentages calculation)
        total = sum(delta)
        # save the current measurement to before object
        self.before = now
        # return the percentage of CPU usage for our 4 categories
        return [(100.0*dt)/total for dt in delta]


    def onTimer(self, evt):
        """callback function for timer events"""

        # get the CPU usage information
        tmp = self.get_cpu_usage()

        # restore the clean background, saved at the beginning
        self.canvas.restore_region(self.bg)

        # update the data
        self.user = self.user[1:] + [tmp[0]]
        self.nice = self.nice[1:] + [tmp[1]]
        self.sys  = self.sys[1:]  + [tmp[2]]
        self.idle = self.idle[1:] + [tmp[3]]

        # update the plot
        self.l_user.set_ydata(self.user)
        self.l_nice.set_ydata(self.nice)
        self.l_sys.set_ydata( self.sys)
        self.l_idle.set_ydata(self.idle)

        # just draw the "animated" objects
        self.ax.draw_artist(self.l_user)
        self.ax.draw_artist(self.l_nice)
        self.ax.draw_artist(self.l_sys)
        self.ax.draw_artist(self.l_idle)

        # "blit" the background with the animated lines
        self.canvas.blit(self.ax.bbox)
class PlotFigure(wx.Frame):
    def __init__(self):
        self.screen_size = wx.DisplaySize()
        #print("the screen size is {0}".format(self.screen_size))
        self.screen_dpi = 100
        self.frame_length = int(self.screen_size[0])
        self.frame_width = int(self.screen_size[1])
        self.fig_length = self.frame_length //  self.screen_dpi
        self.fig_width = self.frame_width // self.screen_dpi
        self.frame_length = self.fig_length * self.screen_dpi
        self.frame_width = self.fig_width * self.screen_dpi
        wx.Frame.__init__(self, None, wx.ID_ANY,
                          title='CP1/X86 TPCC Performance Comparison',
                          size=(self.frame_length, self.frame_width)
                          #size=(1900, 1000)
                        )
        # Matplotlib Figure, x/y-size should size_in_Frame/dpi
        #eg: 1800 = 15 * 120, 600 = 5 * 120
        #self.fig = Figure((19, 10), 100)
        self.fig = Figure((self.fig_length, self.fig_width), self.screen_dpi)

        #print(self.frame_length, self.frame_width)
        #print(self.fig_length, self.fig_width)

        self.canvas = FigureCanvas(self, wx.ID_ANY, self.fig)

        self.ax = self.fig.add_subplot(211)
        self.ax.set_ylim([Y_MIN_VALUE, Y_MAX_VALUE])
        self.ax.set_xlim([X_MIN_VALUE, X_MAX_VALUE])

        self.ax.set_autoscale_on(False)

        #self.ax.set_xticks([])
        self.ax.set_xticks(range(0, 61, 10))
        #self.ax.set_xticks(range(X_MIN_VALUE, X_MAX_VALUE + 1, X_STEP_VALUE))
        self.ax.set_yticks(range(Y_MIN_VALUE, Y_MAX_VALUE + 1, Y_STEP_VALUE))

        self.ax.set_xlabel("Time(second)")
        self.ax.set_ylabel("Transactions Per Minute(tpmC)")
        self.ax.grid(True)

        self.power8_current_all_values = [None] * EMPTY_NUMBER
        self.x86_current_all_values = [None] * EMPTY_NUMBER
        self.power8_plot, = self.ax.plot(range(EMPTY_NUMBER),
                #self.power8_current_all_values, label='CP1 Value',
                self.power8_current_all_values, label='CP1 TPC-C',
                #color='red', linestyle = ':', linewidth = 2, marker = 'o'
                color='red', marker = '.'
                )
        self.x86_plot, = self.ax.plot(range(EMPTY_NUMBER),
                #self.x86_current_all_values, label='X86 Value',
                self.x86_current_all_values, label='X86 TPC-C',
                color='green', marker = '.'
                )

        self.ax.legend(loc='upper center', ncol=4,
                prop=font_manager.FontProperties(size=16)
                #prop=font_manager.FontProperties(size=10)
                )

        # for 2nd subplot
        self.average = self.fig.add_subplot(212)
        self.average.set_ylim(0, 6)
        #self.average.set_xlim(Y_MIN_VALUE, Y_MAX_VALUE)
        self.average.set_xlim(Y_MIN_VALUE, 300000)

        #self.average.set_ylabel("yHello world")
        self.average.set_xlabel("Transactions Per Minute(tpmC)")

        self.power8_accumulate_value = 0
        self.x86_accumulate_value = 0
        self.power8_previous_value = 0
        self.x86_previous_value = 0

        self.power8_ave_index = [3]
        self.x86_ave_index = [1]
        self.power8_ave_value = [0]
        self.x86_ave_value = [0]
        self.power8_barh, = self.average.barh(bottom=self.power8_ave_index,
                width=self.power8_ave_value, height=1.0,
                color='red', label='CP1 TPC-C (Average)')
        self.x86_barh, = self.average.barh(bottom=self.x86_ave_index,
                width=self.x86_ave_value, height=1.0,
                color='green', label="X86 TPC-C (Average)")

        self.average.grid(True)
        self.average.legend(loc='upper center', ncol=4,
                prop=font_manager.FontProperties(size=16)
                #prop=font_manager.FontProperties(size=10)
                )
        self.average.set_yticks([])

        self.fig.subplots_adjust(left=0.08, right=0.95, bottom=0.05, top=0.95)

        ##########################################################################################

        # TODO: resize the subplot in figure
        self.ax.set_position([0.08, 0.40, 0.85, 0.55])
        self.average.set_position([0.08, 0.05, 0.85, 0.28])

        self.canvas.draw()
        # save the clean background
        self.background_1st = self.canvas.copy_from_bbox(self.ax.bbox)
        self.background_2nd = self.canvas.copy_from_bbox(self.average.bbox)

        self.global_timer_index = 0
        self.local_timer_index = 0
        self.power8_current_all_values = []
        self.x86_current_all_values = []

        wx.EVT_TIMER(self, TIMER_ID, self.on_timer)

    def on_timer(self, event):
        # restore the clean background, saved at the beginning
        self.canvas.restore_region(self.background_1st)
        self.canvas.restore_region(self.background_2nd)

        #copyfile(power8_source_filename, power8_input_filename)
        #copyfile(x86_source_filename, x86_input_filename)
        #print(time.strftime("%s"))

        self.global_timer_index += 1
        self.local_timer_index += 1

        line_index = self.global_timer_index - 1
        less_number = EMPTY_NUMBER - self.local_timer_index
        needed_number = self.local_timer_index - 1

        # get the value of current index from file
        power8_current_value = self.read_from_file_by_index(
                power8_input_filename, line_index)
        x86_current_value = self.read_from_file_by_index(
                x86_input_filename, line_index)

        # normal return: accumulate the return value directly.
        # abnormal return: accumulate the previous one.
        if power8_current_value:
            self.power8_accumulate_value += power8_current_value
            self.power8_previous_value = power8_current_value
        else:
            # TODO: new add for error character
            power8_current_value = self.power8_previous_value
            self.power8_accumulate_value += self.power8_previous_value
        if x86_current_value:
            self.x86_accumulate_value += x86_current_value
            self.x86_previous_value = x86_current_value
        else:
            # TODO: new add for error character
            x86_current_value = self.x86_previous_value
            self.x86_accumulate_value += self.x86_previous_value
        #print("==> accumulate = {0} and previous = {1} and current ="
        #        "{2}".format(self.power8_accumulate_value,
        #            self.power8_previous_value,
        #            power8_current_value))

        # update the new data into 1st subplot
        self.power8_current_all_values = \
            self.power8_current_all_values[:needed_number] + \
            [power8_current_value] + [None] * less_number
        self.x86_current_all_values = \
            self.x86_current_all_values[:needed_number] + \
            [x86_current_value] + [None] * less_number
        self.power8_plot.set_ydata(self.power8_current_all_values)
        self.x86_plot.set_ydata(self.x86_current_all_values)

        # update the new data into 2nd subplot
        self.power8_ave_value = self.power8_accumulate_value / \
            self.global_timer_index
        self.x86_ave_value = self.x86_accumulate_value / \
            self.global_timer_index
        self.power8_barh.set_width(self.power8_ave_value)
        self.x86_barh.set_width(self.x86_ave_value)

        self.ax.draw_artist(self.power8_plot)
        self.ax.draw_artist(self.x86_plot)
        self.average.draw_artist(self.power8_barh)
        self.average.draw_artist(self.x86_barh)

        # clean the data on screen
        if self.local_timer_index == EMPTY_NUMBER:
            #print("local_timer_index is full")
            self.power8_current_all_values = []
            self.x86_current_all_values = []
            self.local_timer_index = 0

        self.canvas.blit(self.ax.bbox)
        self.canvas.blit(self.average.bbox)

    def read_from_file_by_index(self, filename, line_number):
        try:
            with open(filename, 'r') as file_object:
                all_content = file_object.read().split('\n')[:-1]
                file_length = len(all_content)
        except IOError, e:
            print("Error->[read_from_file_by_index]: CAN NOT find the"
                  "filename:[{0}]".format(filename))
        except Exception as ex:
            print("Error->[read_from_file_by_index]: {0}".format(str(ex)))
示例#30
0
        class CanvasPanel(wx.Panel):
            def __init__(self, parent):
                wx.Panel.__init__(self, parent)

                self.figure = Figure(figsize=(2, 1),
                                     dpi=256,
                                     facecolor='#000000')
                self.ax = self.figure.add_subplot(111,
                                                  xmargin=0,
                                                  ymargin=0,
                                                  ylim=[1, 32767])
                self.ax.set_axis_off()
                self.ax.set_yscale('log', nonposy='clip', basey=10.0)
                self.figure.set_tight_layout({'pad': 0})

                defaultData = ([0, 1], [0, 1])
                self.ctrl_lines = [
                    self.ax.plot(*defaultData, c=c, lw=0.5)[0]
                    for c in ['#ff0000', '#ffffff', '#ffffff']
                ]
                self.graph_lines = [
                    None,
                    self.ax.step(*defaultData, c='#ffff00', lw=0.3)[0]
                ]
                self.background = None
                self.canvas = FigureCanvas(self, -1, self.figure)

            def __restore_if_possible(self):
                if not (self.background is None):
                    self.canvas.restore_region(self.background)

            def __draw_lines(self):
                for line in self.ctrl_lines:
                    self.ax.draw_artist(line)

            def set_lines_content(self, h=None, l=None, r=None):
                if not (h is None):
                    self.ctrl_lines[0].set_ydata([h, h])
                if not (l is None and r is None):
                    ymin, ymax = self.ax.get_ylim()
                if not (l is None):
                    self.ctrl_lines[1].set_data([l, l], [ymin, ymax])
                if not (r is None):
                    self.ctrl_lines[2].set_data([r, r], [ymin, ymax])

                self.__restore_if_possible()
                self.__draw_lines()
                self.canvas.blit(self.ax.bbox)

            def set_graph_content(self, accurate_data=None, steps_data=None):
                if not (accurate_data is None):
                    datalen = len(accurate_data)
                    fact = 1.0 / datalen
                    self.graph_lines[0] = self.ax.stackplot(
                        [i * fact for i in range(datalen)],
                        accurate_data,
                        colors=['#00ff00'],
                        lw=0)[0]
                if not (steps_data is None):
                    self.graph_lines[1].set_data(steps_data)
                    self.graph_lines[1].set_visible(True)
                else:
                    self.graph_lines[1].set_visible(False)

                for line in self.ctrl_lines:
                    line.set_visible(False)

                self.canvas.draw()
                self.background = self.canvas.copy_from_bbox(self.ax.bbox)

                for line in self.ctrl_lines:
                    line.set_visible(True)
                self.set_lines_content()
                if not (accurate_data is None):
                    self.graph_lines[0].remove()

            def mark_regions(self, data):
                self.__restore_if_possible()
                ymin, ymax = self.ax.get_ylim()
                for xpair in data:
                    polygon, = self.ax.fill(
                        [xpair[0], xpair[0], xpair[1], xpair[1]],
                        [ymin, ymax, ymax, ymin],
                        '#0000ff',
                        alpha=0.2)
                    self.ax.draw_artist(polygon)
                    polygon.remove()
                self.__draw_lines()
                self.canvas.blit(self.ax.bbox)
示例#31
0
文件: cpc.py 项目: lopezpdvn/cerca
class PlotPanel(wx.Panel):
    def __init__(self, *args, **kwds):
        # begin wxGlade: PlotPanel.__init__
        uc = kwds.pop('uc')
        kwds["style"] = wx.DOUBLE_BORDER|wx.TAB_TRAVERSAL
        wx.Panel.__init__(self, *args, **kwds)

        self.__set_properties()
        self.__do_layout()
        # end wxGlade

        # ``PlotPanel`` size is (600, 400).
        self.figure = Figure(figsize=(6, 4), dpi=100)

        self.ax = self.figure.add_subplot(111)
        self.canvas = FigureCanvas(self, wx.ID_ANY, self.figure)
        #self.ax.set_ylim([0.0, 1023.0])
        self.ax.set_ylim([0.0, 80.0])
        self.ax.set_xlim([0.0, POINTS])
        self.ax.set_autoscale_on(False)  # Disable autoscale.
        self.ax.set_xticks([])
        self.ax.grid(True, animated=True, linewidth=1, antialiased=True,
                     fillstyle='full')
        self.ax.set_title(u'Distance vs time')
        self.ax.set_ylabel('distance (cm)')
        self.ax.set_xlabel('time')

        # Initial empty plot.
        self.distance = [None] * POINTS
        self.distance_plot, = self.ax.plot(range(POINTS), self.distance,
                                          label='Distance')
        self.canvas.draw()

        # Save the clean background - everything but the line is drawn and
        # saved in the pixel buffer background.
        self.bg = self.canvas.copy_from_bbox(self.ax.bbox)

        # Represents UC interfaced through the serial port.
        self.uc = uc

        assert self.uc.port.isOpen()
        assert self.uc.status == OK_STATUS

        self.uc.set_mode(SERIAL_MODE)

        # Take a snapshot of voltage, needed for the update algorithm.
        self.before = self.uc.distance

        wx.EVT_TIMER(self, TIMER_ID, self.onTimer)

        # Initialize the timer.
        self.t = wx.Timer(self, TIMER_ID)

        self.samples = 0

    def __set_properties(self):
        # begin wxGlade: PlotPanel.__set_properties
        self.SetMinSize((600, 400))
        self.SetToolTipString("Distance plot.")
        # end wxGlade

    def __do_layout(self):
        # begin wxGlade: PlotPanel.__do_layout
        pass
        # end wxGlade

    def onTimer(self, evt):
        # Get distance.
        distance = self.uc.distance
        if distance <= 80.0:
            distance_str = str(distance)
        else:
            distance = 80.0
            distance_str = u"OUT OF RANGE"

        mainframe.distance_label.SetLabel(distance_str)

        self.samples += 1

        # Restore the clean background, saved at the beginning.
        self.canvas.restore_region(self.bg)

        # Update data array.
        self.distance = self.distance[1:] + [distance]

        # Update plot.
        self.distance_plot.set_ydata(self.distance)

        # Just draw the "animated" objects.
        self.ax.draw_artist(self.distance_plot)

        # Blit the background with the animated lines.
        self.canvas.blit(self.ax.bbox)

        with open(LOG_FILE_PATH, 'a+') as f:
            f.write("{0},{1}\n".format(str(self.samples * TIME_DELTA),
                                       str(distance)))
示例#32
0
class PlotFigure(wx.Frame):  
    """Matplotlib wxFrame with animation effect"""  
    def __init__(self):  
        self.count=1
        wx.Frame.__init__(self, None, wx.ID_ANY, title="CPU Usage Monitor", size=(1280, 720))  
        # Matplotlib Figure  
        self.fig = Figure((16, 9), 80)  
        # bind the Figure to the backend specific canvas  
        self.canvas = FigureCanvas(self, wx.ID_ANY, self.fig)  
        # add a subplot  
        self.ax1 = self.fig.add_subplot(411) 
        self.ax2 = self.fig.add_subplot(412)
        self.ax3 = self.fig.add_subplot(413)
        self.ax4 = self.fig.add_subplot(414) 
        # limit the X and Y axes dimensions  
        self.ax1.set_ylim([-0.05, 1.2])  
        self.ax1.set_xlim([0, POINTS]) 

        self.ax2.set_ylim([-0.05, 1.2])  
        self.ax2.set_xlim([0, POINTS]) 

        self.ax3.set_ylim([-0.05, 1.2])  
        self.ax3.set_xlim([0, POINTS])

        self.ax4.set_ylim([-0.05, 1.2])  
        self.ax4.set_xlim([0, POINTS])
         
        self.ax1.set_autoscale_on(False)  
        self.ax1.set_xticks([])  

        self.ax2.set_autoscale_on(False)  
        self.ax2.set_xticks([]) 

        self.ax3.set_autoscale_on(False)  
        self.ax3.set_xticks([]) 

        self.ax4.set_autoscale_on(False)  
        self.ax4.set_xticks([]) 
        # we want a tick every 10 point on Y (101 is to have 10  
        self.ax1.set_yticks(range(0, 2, 10)) 
        self.ax2.set_yticks(range(0, 2, 10))
        self.ax3.set_yticks(range(0, 2, 10))
        self.ax4.set_yticks(range(0, 2, 10))
        # disable autoscale, since we don't want the Axes to ad  
        # draw a grid (it will be only for Y)  
        self.ax1.grid(True)
        self.ax2.grid(True)
        self.ax3.grid(True)  
        self.ax4.grid(True)
        # generates first "empty" plots  
        self.s1e = [None] * POINTS
        self.s1s = [None] * POINTS
        self.s1w = [None] * POINTS
        self.s2e = [None] * POINTS
        self.s2s = [None] * POINTS
        self.s2w = [None] * POINTS
        self.s3e = [None] * POINTS
        self.s3s = [None] * POINTS
        self.s3w = [None] * POINTS
        self.s4e = [None] * POINTS
        self.s4s = [None] * POINTS
        self.s4w = [None] * POINTS
 
        self.s1_e,=self.ax1.plot(range(POINTS),self.s1e,label='ECMP',linewidth=3) 
        self.s1_s,=self.ax1.plot(range(POINTS),self.s1s,label='STAT',linewidth=3)
        self.s1_w,=self.ax1.plot(range(POINTS),self.s1w,label='LBAS',linewidth=3) 

        self.s2_e,=self.ax2.plot(range(POINTS),self.s2e,label='ECMP %',linewidth=3) 
        self.s2_s,=self.ax2.plot(range(POINTS),self.s2s,label='STAT %',linewidth=3)
        self.s2_w,=self.ax2.plot(range(POINTS),self.s2w,label='WEIG %',linewidth=3)

        self.s3_e,=self.ax3.plot(range(POINTS),self.s3e,label='ECMP %',linewidth=3) 
        self.s3_s,=self.ax3.plot(range(POINTS),self.s3s,label='STAT %',linewidth=3)
        self.s3_w,=self.ax3.plot(range(POINTS),self.s3w,label='WEIG %',linewidth=3)

        self.s4_e,=self.ax4.plot(range(POINTS),self.s4e,label='ECMP %',linewidth=3) 
        self.s4_s,=self.ax4.plot(range(POINTS),self.s4s,label='STAT %',linewidth=3)
        self.s4_w,=self.ax4.plot(range(POINTS),self.s4w,label='WEIG %',linewidth=3)
        # add the legend  
        self.ax1.legend(loc='upper center', 
                           bbox_to_anchor=(0.5,1.5),
                           ncol=4,  
                           prop=font_manager.FontProperties(size=10))  
        # force a draw on the canvas()  
        # trick to show the grid and the legend  
        self.canvas.draw()  
        # save the clean background - everything but the line  
        # is drawn and saved in the pixel buffer background  
        self.bg1 = self.canvas.copy_from_bbox(self.ax1.bbox) 
        self.bg2 = self.canvas.copy_from_bbox(self.ax2.bbox)
        self.bg3 = self.canvas.copy_from_bbox(self.ax3.bbox)
        self.bg4 = self.canvas.copy_from_bbox(self.ax4.bbox)
        # bind events coming from timer with id = TIMER_ID  
        # to the onTimer callback function  
        self.timer = wx.Timer(self) 
        self.timer.Start(500)
        self.Bind(wx.EVT_TIMER, self.onTimer,self.timer)
  
    def onTimer(self, evt):  
        """callback function for timer events"""  
        # restore the clean background, saved at the beginning
        if self.count<=46:
            self.count+=1
        else : self.timer.Stop() 
        self.canvas.restore_region(self.bg1)
        self.canvas.restore_region(self.bg2)
        self.canvas.restore_region(self.bg3)
        self.canvas.restore_region(self.bg4)  
        # update the data  
        with open('cpu_record_ecmp','r') as fecmp:
            dataecmp=fecmp.read().split("\n")[:-1]

        ecmp1=[s.split(" ")[0] for s in dataecmp]
        ecmp2=[s.split(" ")[1] for s in dataecmp]
        ecmp3=[s.split(" ")[2] for s in dataecmp]
        ecmp4=[s.split(" ")[3] for s in dataecmp]

        with open('cpu_record_static','r') as fstatic:
            datastatic=fstatic.read().split("\n")[:-1]

        static1=[s.split(" ")[0] for s in datastatic]
        static2=[s.split(" ")[1] for s in datastatic]
        static3=[s.split(" ")[2] for s in datastatic]
        static4=[s.split(" ")[3] for s in datastatic]

        with open('cpu_record_weight','r') as fweight:
            dataweight=fweight.read().split("\n")[:-1]

        weight1=[s.split(" ")[0] for s in dataweight]
        weight2=[s.split(" ")[1] for s in dataweight]
        weight3=[s.split(" ")[2] for s in dataweight]
        weight4=[s.split(" ")[3] for s in dataweight]
  
        self.s1e = self.s1e[1:] + [ecmp1[self.count]]
        self.s1s = self.s1s[1:] + [static1[self.count]]
        self.s1w = self.s1w[1:] + [weight1[self.count]] 
        self.s2e = self.s2e[1:] + [ecmp2[self.count]] 
        self.s2s = self.s2s[1:] + [static2[self.count]]
        self.s2w = self.s2w[1:] + [weight2[self.count]] 
        self.s3e = self.s3e[1:] + [ecmp3[self.count]] 
        self.s3s = self.s3s[1:] + [static3[self.count]]
        self.s3w = self.s3w[1:] + [weight3[self.count]] 
        self.s4e = self.s4e[1:] + [ecmp4[self.count]] 
        self.s4s = self.s4s[1:] + [static4[self.count]]
        self.s4w = self.s4w[1:] + [weight4[self.count]] 
        # update the plot  

        self.s1_e.set_ydata(self.s1e)
        self.s1_s.set_ydata(self.s1s)
        self.s1_w.set_ydata(self.s1w)
        self.s2_e.set_ydata(self.s2e)
        self.s2_s.set_ydata(self.s2s)
        self.s2_w.set_ydata(self.s2w)
        self.s3_e.set_ydata(self.s3e)
        self.s3_s.set_ydata(self.s3s)
        self.s3_w.set_ydata(self.s3w)
        self.s4_e.set_ydata(self.s4e)
        self.s4_s.set_ydata(self.s4s)
        self.s4_w.set_ydata(self.s4w)

        # just draw the "animated" objects  
        self.ax1.draw_artist(self.s1_e)
        self.ax1.draw_artist(self.s1_s)
        self.ax1.draw_artist(self.s1_w)

        self.ax2.draw_artist(self.s2_e)
        self.ax2.draw_artist(self.s2_s)
        self.ax2.draw_artist(self.s2_w)

        self.ax3.draw_artist(self.s3_e)
        self.ax3.draw_artist(self.s3_s)
        self.ax3.draw_artist(self.s3_w)

        self.ax4.draw_artist(self.s4_e)
        self.ax4.draw_artist(self.s4_s)
        self.ax4.draw_artist(self.s4_w)

        # It is used to efficiently update Axes data (axis ticks, labels, etc are not updated)  
        self.canvas.blit(self.ax1.bbox)
        self.canvas.blit(self.ax2.bbox)
        self.canvas.blit(self.ax3.bbox) 
        self.canvas.blit(self.ax4.bbox) 
示例#33
0
文件: specgram.py 项目: idfah/cebl
class Spectrogram(StandardMonitorPage):
    """Main class for a page that generates real-time spectrogram plots of EEG.
    """
    def __init__(self, *args, **kwargs):
        """Construct a new Spectrogram page.

        Args:
            *args, **kwargs:  Arguments to pass to the Page base class.
        """
        self.initConfig()

        # initialize Page base class
        StandardMonitorPage.__init__(self,
                                     name='Spectrogram',
                                     configPanelClass=ConfigPanel,
                                     *args,
                                     **kwargs)

        self.initCanvas()
        self.initLayout()

    def initConfig(self):
        self.filter = True  # use raw or filtered signal
        self.chanIndex = 0  # index of channel to show
        self.width = 5.0  # width of window to use for computing PSD

        self.decimationFactor = 1  # decimation factor, e.g., 2 will decimate to half sampRate

        self.interpolation = 'none'

        self.normScale = 'log'
        self.scale = -2

        self.method = 'Wavelet'

        self.setRefreshDelay(200)

        self.waveletConfig = util.Holder(nFreq=100, span=10)

        self.fourierConfig = util.Holder()

    def initCanvas(self):
        """Initialize a new matplotlib canvas, figure and axis.
        """
        self.plotPanel = wx.Panel(self)
        self.plotPanel.SetBackgroundColour('white')
        plotSizer = wx.BoxSizer(orient=wx.VERTICAL)
        self.plotPanel.SetSizer(plotSizer)

        self.fig = plt.Figure(facecolor='white')
        #self.canvas = FigureCanvas(parent=self, id=wx.ID_ANY, figure=self.fig)
        self.canvas = FigureCanvas(parent=self.plotPanel,
                                   id=wx.ID_ANY,
                                   figure=self.fig)

        self.ax = self.fig.add_subplot(1, 1, 1)
        self.ax.set_xlabel('Time (s)')
        self.ax.set_ylabel('Frequency (Hz)')

        self.cbAx = self.fig.add_axes([0.91, 0.05, 0.03, 0.93])

        #self.fig.subplots_adjust(hspace=0.0, wspace=0.0,
        #    left=0.035, right=0.92, top=0.98, bottom=0.05)

        self.adjustMargins()

        self.firstPlot()

        self.lastSize = (0, 0)
        self.needsResizePlot = True
        self.canvas.Bind(wx.EVT_SIZE, self.resizePlot)
        self.canvas.Bind(wx.EVT_IDLE, self.idleResizePlot)

        ##self.plotToolbar = widgets.PyPlotNavbar(self.canvas)
        ##plotSizer.Add(self.plotToolbar, proportion=0, flag=wx.EXPAND)
        plotSizer.Add(self.canvas, proportion=1, flag=wx.EXPAND)

        #self.plotToolbar.Hide()

    def initLayout(self):
        self.initStandardLayout()

        plotPaneAuiInfo = aui.AuiPaneInfo().Name('canvas').Caption(
            'Spectrogram').CenterPane()
        #self.auiManager.AddPane(self.canvas, plotPaneAuiInfo)
        self.auiManager.AddPane(self.plotPanel, plotPaneAuiInfo)

        self.auiManager.Update()

        self.canvas.Hide()

    def afterUpdateSource(self):
        self.configPanel.updateChannels()

    def afterStart(self):
        # make sure canvas is visible
        self.canvas.Show()
        self.plotPanel.Layout()

        # trigger initial plot update
        self.needsFirstPlot = True

    def getCap(self):
        cap = self.src.getEEGSecs(self.width, filter=self.filter, copy=False)
        if self.decimationFactor > 1:
            cap.decimate(self.decimationFactor)

        return cap

    def getSpectrum(self, cap):
        # configurable XXX - idfah
        data = cap.data[:, self.chanIndex] * sig.windows.tukey(
            cap.data.shape[0])  # tukey or hann? XXX - idfah

        freqs, powers, phases = self.cwt.apply(data)

        # configurable XXX - idfah
        powers = np.clip(powers, 1.0e-10, np.inf)

        return freqs, powers

    def firstPlot(self, event=None):
        cap = self.getCap()

        self.cwt = sig.CWT(sampRate=cap.getSampRate(),
                           freqs=self.waveletConfig.nFreq,
                           span=self.waveletConfig.span)

        if self.isRunning():
            freqs, powers = self.getSpectrum(cap)
        else:
            freqs = np.arange(1, self.src.getSampRate() // 2 + 1)
            powers = np.zeros((128, 10, 1))
            powers[0, 0, 0] = 1.0

        self.ax.cla()
        self.cbAx.cla()

        self.ax.set_xlabel('Time (s)')
        self.ax.set_ylabel('Frequency (Hz)')

        self.wimg = self.ax.imshow(powers[:, :, 0].T,
                                   interpolation=self.interpolation,
                                   origin='lower',
                                   aspect='auto',
                                   norm=self.getNorm(),
                                   extent=self.getExtent(cap, freqs),
                                   cmap=plt.cm.get_cmap('jet'),
                                   animated=True)

        self.cbar = self.fig.colorbar(self.wimg, cax=self.cbAx)
        self.cbar.set_label(r'Power Density ($V^2 / Hz$)')

        #self.updateNorm(powers)

        self.canvas.draw()

        #self.background = self.canvas.copy_from_bbox(self.fig.bbox)
        self.background = self.canvas.copy_from_bbox(self.ax.bbox)

        self.needsFirstPlot = False

    def adjustMargins(self):
        self.fig.subplots_adjust(hspace=0.0,
                                 wspace=0.0,
                                 left=0.045,
                                 right=0.90,
                                 top=0.98,
                                 bottom=0.07)

    def resizePlot(self, event):
        # prevents handling extra resize events, hack XXX - idfah
        size = self.canvas.GetSize()
        if self.lastSize == size:
            return
        else:
            self.lastSize = size

        # this is all a hack to do resizing on idle when page is not running
        # should this be a custom FigureCanvas derived widget? XXX - idfah
        if self.isRunning():
            # when running, just do event.Skip() this will
            # call canvas._onSize since it is second handler
            self.needsResizePlot = False
            event.Skip()
        else:
            # flag to resize on next idle event
            self.needsResizePlot = True

    def idleResizePlot(self, event):
        # if not running and flagged for resize
        if not self.isRunning() and self.needsResizePlot:
            ##self.adjustMargins()
            self.needsResizePlot = False
            # call canvas resize method manually
            # hack alert, we just pass None as event
            # since it's not used anyway
            self.canvas._onSize(None)

    def getExtent(self, cap, freqs):
        return (0.0, cap.getNObs() / float(cap.getSampRate()), np.min(freqs),
                np.max(freqs))

    def getNorm(self):
        mx = 10**self.scale

        if self.normScale == 'linear':
            mn = 0.0
            norm = pltLinNorm(mn, mx)

        elif self.normScale == 'log':
            mn = 1e-10
            norm = pltLogNorm(mn, mx)

        else:
            raise RuntimeError('Invalid norm %s.' % norm)

        return norm

    def updatePlot(self, event=None):
        """Draw the spectrogram plot.
        """
        if self.needsFirstPlot:
            self.firstPlot()

        else:
            cap = self.getCap()
            freqs, powers = self.getSpectrum(cap)

            #self.updateNorm(powers)

            self.canvas.restore_region(self.background)
            self.wimg.set_array(powers[:, :, 0].T)
            self.wimg.set_extent(self.getExtent(cap, freqs))
            self.ax.draw_artist(self.wimg)

            ##self.cbAx.draw_artist(self.cbar.patch)
            ##self.cbAx.draw_artist(self.cbar.solids)

            #self.cbar.draw_all()
            #self.canvas.blit(self.cbAx.bbox)

            #self.canvas.blit(self.fig.bbox)
            self.canvas.blit(self.ax.bbox)

            # for debugging, redraws everything
            ##self.canvas.draw()

    def captureImage(self, event=None):
        ## Parts borrowed from backends_wx.py from matplotlib
        # Fetch the required filename and file type.
        filetypes, exts, filter_index = self.canvas._get_imagesave_wildcards()
        default_file = self.canvas.get_default_filename()
        dlg = wx.FileDialog(self, "Save to file", "", default_file, filetypes,
                            wx.SAVE | wx.OVERWRITE_PROMPT)
        dlg.SetFilterIndex(filter_index)
        if dlg.ShowModal() == wx.ID_OK:
            dirname = dlg.GetDirectory()
            filename = dlg.GetFilename()
            format = exts[dlg.GetFilterIndex()]
            basename, ext = os.path.splitext(filename)
            if ext.startswith('.'):
                ext = ext[1:]
            if ext in ('svg', 'pdf', 'ps', 'eps', 'png') and format != ext:
                #looks like they forgot to set the image type drop
                #down, going with the extension.
                format = ext
            self.canvas.print_figure(os.path.join(dirname, filename),
                                     format=format)
示例#34
0
class PanelGraph(wx.Panel):
    def __init__(self, panel, notify, settings, callbackMotion, remoteControl):
        self.panel = panel
        self.notify = notify
        self.plot = None
        self.settings = settings
        self.remoteControl = remoteControl
        self.spectrum = None
        self.isLimited = None
        self.limit = None
        self.extent = None
        self.annotate = None

        self.mouseSelect = None
        self.mouseZoom = None
        self.measureTable = None

        self.background = None

        self.selectStart = None
        self.selectEnd = None

        self.menuClearSelect = []

        self.measure = None
        self.show = None

        self.doDraw = False

        wx.Panel.__init__(self, panel)

        self.figure = matplotlib.figure.Figure(facecolor='white')
        self.canvas = FigureCanvas(self, -1, self.figure)

        self.measureTable = PanelMeasure(self, settings)

        self.toolbar = NavigationToolbar(self.canvas, self, settings,
                                         self.__hide_overlay)
        self.toolbar.Realize()

        vbox = wx.BoxSizer(wx.VERTICAL)
        vbox.Add(self.canvas, 1, wx.EXPAND)
        vbox.Add(self.measureTable, 0, wx.EXPAND)
        vbox.Add(self.toolbar, 0, wx.EXPAND)
        self.SetSizer(vbox)
        vbox.Fit(self)

        self.create_plot()

        self.canvas.mpl_connect('button_press_event', self.__on_press)
        self.canvas.mpl_connect('motion_notify_event', callbackMotion)
        self.canvas.mpl_connect('draw_event', self.__on_draw)
        self.canvas.mpl_connect('idle_event', self.__on_idle)
        self.Bind(wx.EVT_SIZE, self.__on_size)

        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.__on_timer, self.timer)

    def __set_fonts(self):
        axes = self.plot.get_axes()
        if axes is not None:
            axes.xaxis.label.set_size('small')
            axes.yaxis.label.set_size('small')
            if self.settings.display == Display.SURFACE:
                axes.zaxis.label.set_size('small')
            axes.tick_params(axis='both', which='major', labelsize='small')
        axes = self.plot.get_axes_bar()
        if axes is not None:
            axes.tick_params(axis='both', which='major', labelsize='small')

    def __enable_menu(self, state):
        for menu in self.menuClearSelect:
            menu.Enable(state)

    def __on_press(self, event):
        if self.settings.clickTune and matplotlib.__version__ >= '1.2' and event.dblclick:
            frequency = int(event.xdata * 1e6)
            self.remoteControl.tune(frequency)

    def __on_size(self, event):
        ppi = wx.ScreenDC().GetPPI()
        size = [float(v) for v in self.canvas.GetSize()]
        width = size[0] / ppi[0]
        height = size[1] / ppi[1]
        self.figure.set_figwidth(width)
        self.figure.set_figheight(height)
        self.figure.set_dpi(ppi[0])
        event.Skip()

    def __on_draw(self, _event):
        axes = self.plot.get_axes()
        if axes is not None:
            self.background = self.canvas.copy_from_bbox(axes.bbox)
            self.__draw_overlay()

    def __on_idle(self, _event):
        if self.doDraw and self.plot.get_plot_thread() is None:
            self.__hide_overlay()
            self.canvas.draw()
            self.doDraw = False

    def __on_timer(self, _event):
        self.timer.Stop()
        self.set_plot(None, None, None, None, self.annotate)

    def __draw_overlay(self):
        if self.background is not None:
            self.canvas.restore_region(self.background)
            self.__draw_select()
            self.draw_measure()
            axes = self.plot.get_axes()
            if axes is None:
                self.canvas.draw()
            else:
                self.canvas.blit(axes.bbox)

    def __draw_select(self):
        if self.selectStart is not None and self.selectEnd is not None:
            self.mouseSelect.draw(self.selectStart, self.selectEnd)

    def __hide_overlay(self):
        if self.plot is not None:
            self.plot.hide_measure()
        self.__hide_select()

    def __hide_select(self):
        if self.mouseSelect is not None:
            self.mouseSelect.hide()

    def create_plot(self):
        if self.plot is not None:
            self.plot.close()

        self.toolbar.set_auto(True)

        if self.settings.display == Display.PLOT:
            self.plot = Plotter(self.notify, self.figure, self.settings)
        elif self.settings.display == Display.SPECT:
            self.plot = Spectrogram(self.notify, self.figure, self.settings)
        elif self.settings.display == Display.SURFACE:
            self.plot = Plotter3d(self.notify, self.figure, self.settings)
        elif self.settings.display == Display.STATUS:
            self.plot = PlotterStatus(self.notify, self.figure, self.settings)
        else:
            self.plot = PlotterTime(self.notify, self.figure, self.settings)

        self.__set_fonts()

        self.toolbar.set_plot(self.plot)
        self.toolbar.set_type(self.settings.display)
        self.measureTable.set_type(self.settings.display)

        self.set_plot_title()
        self.figure.subplots_adjust(top=0.85)
        self.redraw_plot()
        self.plot.scale_plot(True)
        self.mouseZoom = MouseZoom(self.toolbar,
                                   plot=self.plot,
                                   callbackHide=self.__hide_overlay)
        self.mouseSelect = MouseSelect(self.plot, self.on_select,
                                       self.on_selected)
        self.measureTable.show(self.settings.showMeasure)
        self.panel.SetFocus()

    def on_select(self):
        self.hide_measure()

    def on_selected(self, start, end):
        self.__enable_menu(True)
        self.selectStart = start
        self.selectEnd = end
        self.measureTable.set_selected(self.spectrum, start, end)

    def add_menu_clear_select(self, menu):
        self.menuClearSelect.append(menu)
        menu.Enable(False)

    def draw(self):
        self.doDraw = True

    def show_measure_table(self, show):
        self.measureTable.show(show)
        self.Layout()

    def set_plot(self, spectrum, isLimited, limit, extent, annotate=False):
        if spectrum is not None and extent is not None:
            if isLimited is not None and limit is not None:
                self.spectrum = copy.copy(spectrum)
                self.extent = extent
                self.annotate = annotate
                self.isLimited = isLimited
                self.limit = limit

        if self.plot.get_plot_thread() is None:
            self.timer.Stop()
            self.measureTable.set_selected(self.spectrum, self.selectStart,
                                           self.selectEnd)
            if isLimited:
                spectrum = reduce_points(spectrum, limit)
            self.plot.set_plot(self.spectrum, self.extent, annotate)

        else:
            self.timer.Start(200, oneShot=True)

    def set_plot_title(self):
        if len(self.settings.devicesRtl) > 0:
            gain = self.settings.devicesRtl[self.settings.indexRtl].gain
        else:
            gain = 0
        self.plot.set_title("Frequency Spectrogram\n{} - {} MHz,"
                            " gain = {}dB".format(self.settings.start,
                                                  self.settings.stop, gain))

    def redraw_plot(self):
        if self.spectrum is not None:
            self.set_plot(self.spectrum, self.settings.pointsLimit,
                          self.settings.pointsMax, self.extent,
                          self.settings.annotate)

    def set_grid(self, on):
        self.plot.set_grid(on)

    def hide_measure(self):
        if self.plot is not None:
            self.plot.hide_measure()

    def draw_measure(self):
        if self.measure is not None and self.measure.is_valid():
            self.plot.draw_measure(self.measure, self.show)

    def update_measure(self, measure=None, show=None):
        if not measure and not show:
            self.measureTable.update_measure()
        else:
            self.measure = measure
            self.show = show
            self.__draw_overlay()

    def get_figure(self):
        return self.figure

    def get_axes(self):
        return self.plot.get_axes()

    def get_canvas(self):
        return self.canvas

    def get_toolbar(self):
        return self.toolbar

    def scale_plot(self, force=False):
        self.plot.scale_plot(force)

    def clear_plots(self):
        self.plot.clear_plots()
        self.spectrum = None
        self.doDraw = True

    def clear_selection(self):
        self.measure = None
        self.measureTable.clear_measurement()
        self.selectStart = None
        self.selectEnd = None
        self.mouseSelect.clear()
        self.__enable_menu(False)

    def close(self):
        close_modeless()
示例#35
0
class PanelGraph(wx.Panel):
    def __init__(self, panel, notify, settings, callbackMotion):
        self.panel = panel
        self.notify = notify
        self.plot = None
        self.settings = settings
        self.spectrum = None
        self.isLimited = None
        self.limit = None
        self.extent = None

        self.mouseSelect = None
        self.mouseZoom = None
        self.measureTable = None

        self.background = None

        self.selectStart = None
        self.selectEnd = None

        self.menuClearSelect = []

        self.measure = None
        self.show = None

        self.doDraw = False

        wx.Panel.__init__(self, panel)

        self.figure = matplotlib.figure.Figure(facecolor='white')
        self.canvas = FigureCanvas(self, -1, self.figure)

        self.measureTable = PanelMeasure(self)

        self.toolbar = NavigationToolbar(self.canvas, self, settings,
                                         self.hide_overlay)
        self.toolbar.Realize()

        vbox = wx.BoxSizer(wx.VERTICAL)
        vbox.Add(self.canvas, 1, wx.EXPAND)
        vbox.Add(self.measureTable, 0, wx.EXPAND)
        vbox.Add(self.toolbar, 0, wx.EXPAND)
        self.SetSizer(vbox)
        vbox.Fit(self)

        self.create_plot()

        self.canvas.mpl_connect('motion_notify_event', callbackMotion)
        self.canvas.mpl_connect('draw_event', self.on_draw)
        self.canvas.mpl_connect('idle_event', self.on_idle)
        self.Bind(wx.EVT_SIZE, self.on_size)

        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.on_timer, self.timer)

    def create_plot(self):
        if self.plot is not None:
            self.plot.close()

        self.toolbar.set_auto(True)

        if self.settings.display == Display.PLOT:
            self.plot = Plotter(self.notify, self.figure, self.settings)
        elif self.settings.display == Display.SPECT:
            self.plot = Spectrogram(self.notify, self.figure, self.settings)
        else:
            self.plot = Plotter3d(self.notify, self.figure, self.settings)

        self.set_fonts()

        self.toolbar.set_plot(self.plot)
        self.toolbar.set_type(self.settings.display)
        self.measureTable.set_type(self.settings.display)

        self.set_plot_title()
        self.figure.tight_layout()
        self.figure.subplots_adjust(top=0.85)
        self.redraw_plot()
        self.plot.scale_plot(True)
        self.mouseZoom = MouseZoom(self.plot, self.toolbar, self.hide_overlay)
        self.mouseSelect = MouseSelect(self.plot, self.on_select,
                                       self.on_selected)
        self.measureTable.show(self.settings.showMeasure)
        self.panel.SetFocus()

    def set_fonts(self):
        axes = self.plot.get_axes()
        axes.xaxis.label.set_size('small')
        axes.yaxis.label.set_size('small')
        if self.settings.display == Display.SURFACE:
            axes.zaxis.label.set_size('small')
        axes.tick_params(axis='both', which='major', labelsize='small')
        axes = self.plot.get_axes_bar()
        axes.tick_params(axis='both', which='major', labelsize='small')

    def add_menu_clear_select(self, menu):
        self.menuClearSelect.append(menu)
        menu.Enable(False)

    def enable_menu(self, state):
        for menu in self.menuClearSelect:
            menu.Enable(state)

    def on_size(self, event):
        ppi = wx.ScreenDC().GetPPI()
        size = [float(v) for v in self.canvas.GetSize()]
        width = size[0] / ppi[0]
        height = size[1] / ppi[1]
        self.figure.set_figwidth(width)
        self.figure.set_figheight(height)
        self.figure.set_dpi(ppi[0])
        event.Skip()

    def on_draw(self, _event):
        axes = self.plot.get_axes()
        self.background = self.canvas.copy_from_bbox(axes.bbox)
        self.draw_overlay()

    def on_select(self):
        self.hide_measure()

    def on_selected(self, start, end):
        self.enable_menu(True)
        self.selectStart = start
        self.selectEnd = end
        self.measureTable.set_selected(self.spectrum, start, end)

    def on_idle(self, _event):
        if self.doDraw and self.plot.get_plot_thread() is None:
            self.hide_overlay()
            self.canvas.draw()
            self.doDraw = False

    def on_timer(self, _event):
        self.timer.Stop()
        self.set_plot(None, None, None, None, self.annotate)

    def draw(self):
        self.doDraw = True

    def show_measureTable(self, show):
        self.measureTable.show(show)
        self.Layout()

    def set_plot(self, spectrum, isLimited, limit, extent, annotate=False):
        if spectrum is not None and extent is not None:
            if isLimited is not None and limit is not None:
                self.spectrum = copy.copy(spectrum)
                self.extent = extent
                self.annotate = annotate
                self.isLimited = isLimited
                self.limit = limit

        if self.plot.get_plot_thread() is None:
            self.timer.Stop()
            self.measureTable.set_selected(self.spectrum, self.selectStart,
                                           self.selectEnd)
            if isLimited:
                spectrum = reduce_points(spectrum, limit)
            self.plot.set_plot(self.spectrum, self.extent, annotate)

        else:
            self.timer.Start(200, oneShot=True)

    def set_plot_title(self):
        if len(self.settings.devices) > 0:
            gain = self.settings.devices[self.settings.index].gain
        else:
            gain = 0
        self.figure.suptitle("Frequency Spectrogram\n{0} - {1} MHz,"
                             " gain = {2}dB".format(self.settings.start,
                                                    self.settings.stop, gain))

    def redraw_plot(self):
        if self.spectrum is not None:
            self.set_plot(self.spectrum,
                          self.settings.pointsLimit,
                          self.settings.pointsMax,
                          self.extent, self.settings.annotate)

    def set_grid(self, on):
        self.plot.set_grid(on)

    def draw_overlay(self):
        if self.background is not None:
            self.canvas.restore_region(self.background)
            self.draw_select()
            self.draw_measure()
            self.canvas.blit(self.plot.get_axes().bbox)

    def draw_select(self):
        if self.selectStart is not None and self.selectEnd is not None:
            self.mouseSelect.draw(self.selectStart, self.selectEnd)

    def hide_overlay(self):
        if self.plot is not None:
            self.plot.hide_measure()
        self.hide_select()

    def hide_measure(self):
        if self.plot is not None:
            self.plot.hide_measure()

    def hide_select(self):
        if self.mouseSelect is not None:
            self.mouseSelect.hide()

    def draw_measure(self):
        if self.measure is not None and self.measure.is_valid():
            self.plot.draw_measure(self.measure, self.show)

    def update_measure(self, measure, show):
        self.measure = measure
        self.show = show
        self.draw_overlay()

    def get_figure(self):
        return self.figure

    def get_axes(self):
        return self.plot.get_axes()

    def get_canvas(self):
        return self.canvas

    def get_toolbar(self):
        return self.toolbar

    def scale_plot(self, force=False):
        self.plot.scale_plot(force)

    def clear_plots(self):
        self.plot.clear_plots()

    def clear_selection(self):
        self.measure = None
        self.measureTable.clear_measurement()
        self.selectStart = None
        self.selectEnd = None
        self.mouseSelect.clear()
        self.enable_menu(False)

    def close(self):
        close_modeless()
示例#36
0
class NaoPanel(wx.Panel):
    def _init_ctrls(self, prnt):
        # generated method, don't edit
        wx.Panel.__init__(self, id=wxID_LEFTPANEL, name='NaoPanel',
              parent=prnt, pos=wx.Point(208, 8), size=wx.Size(800, 400),
              style=wx.NO_BORDER | wx.TAB_TRAVERSAL)
        self.SetClientSize(wx.Size(800, 400))
        self.SetBackgroundColour(wx.Colour(0, 0, 255))
        self.Bind(wx.EVT_PAINT, self.OnNaoPanelPaint)

    def __init__(self, parent, id, pos, size, style, name):
        self._init_ctrls(parent)
    ##Create a matplotlib figure/canvas in this panel
    ##the background colour will be the same as the panel
    ##the size will also be the same as the panel
        ##calculate size in inches
        pixels_width,pixels_height = self.GetSizeTuple()
        self.dpi = 96.0
        inches_width = pixels_width/self.dpi
        inches_height = pixels_height/self.dpi
        
        ##calculate colour in RGB 0 to 1
        colour = self.GetBackgroundColour()
        self.fig = Figure(figsize=(inches_width,inches_height), dpi = self.dpi\
            ,facecolor=(colour.Red()/255.0, colour.Green()/255.0, colour.Blue()/255.0)\
            ,edgecolor=(colour.Red()/255.0, colour.Green()/255.0, colour.Blue()/255.0))
            
        ##left : the left side of the subplots of the figure
##     |      right : the right side of the subplots of the figure
##     |      bottom : the bottom of the subplots of the figure
##     |      top : the top of the subplots of the figure
##     |      wspace : the amount of width reserved for blank space between subplots
##     |      hspace : the amount of height reserved for white space between subplots
##     |      

        self.canvas = FigureCanvasWxAgg(self, -1, self.fig)

        ##now put everything in a sizer
        sizer = wx.BoxSizer(wx.VERTICAL)
        # This way of adding to sizer allows resizing
        sizer.Add(self.canvas, 1, wx.LEFT|wx.TOP|wx.GROW)
        self.SetSizer(sizer)
        self.Fit()
        
        ##now finally create the actual plot
        ##self.axes = self.fig.add_subplot(111)
        self.axes = self.fig.add_axes((0.08,0.08,0.90,0.85))               ##left,bottom,width,height
        self.naohistoryplot = self.axes.plot([0,0],[0,0], 'r', animated=True)
        self.naohistoryx = list()
        self.naohistoryy = list()
        
        self.positionmeasurementplot = self.axes.plot([0,0],[0,0], 'blue', marker='o', markersize=5, linewidth=0, markeredgewidth=0, animated=True)
        self.orientationmeasurementplot = self.axes.plot([0,0],[0,0], 'blue', linewidth=2, animated=True)
        self.shapeplot = self.axes.plot([0,0],[0,0], 'blue', marker='o', markersize=2, linewidth=0, markeredgewidth=0, animated=True)
        self.estimateplot = self.axes.plot([0,0],[0,0], 'red', linewidth=2, animated=True)
        self.particleplot = self.axes.quiver([0,0],[0,0], [1,1], [0.5, -0.5], [1, 1], cmap=pylab.gray(), animated=True)
        
        ##plot formatting
        self.axes.set_title('Nao Image', fontsize='10')
        self.axes.set_xlabel('y (cm)', fontsize='10')
        self.axes.set_ylabel('x (cm)', fontsize='10')
        ticks = numpy.arange(-25, 25 + 5, 5)
        labels = [str(tick) for tick in ticks]
        self.axes.set_yticks(ticks)
        self.axes.set_yticklabels(labels, fontsize=8)
        self.axes.set_ylim(ticks[0], ticks[-1])
        ticks = -numpy.arange(-50, 50+5, 5)
        labels = [str(tick) for tick in ticks]
        self.axes.set_xticks(ticks)
        self.axes.set_xticklabels(labels,fontsize=8)
        self.axes.set_xlim(ticks[0], ticks[-1])
        
        self.canvas.draw()
        self.canvas.gui_repaint()
        
        # save the clean slate background -- everything but the animated line
        # is drawn and saved in the pixel buffer background
        self.background = self.canvas.copy_from_bbox(self.axes.bbox)
        
        #self.leftedgeplot = self.axes.plot([0,0],[0,0], 'orange', marker='o', markersize=4, linewidth=0, animated=True) 
        #self.rightedgeplot = self.axes.plot([0,0],[0,0], 'purple', marker='o', markersize=4, linewidth=0, animated=True)
        
    def setNaoFinder(self, finder):
        """ """
        self.NAOFinder = finder
        
    def setLocalisation(self, localisation):
        """ """
        self.Localisation = localisation
    
    def updateData(self, data):
        """updateData. Updates the data that this panel is displaying.
        """
        # Note the x values are plotted on the y-axis, and the y values are plotted on the x-axis
        naox = self.Localisation.X
        naoy = self.Localisation.Y
        naoorientation = self.Localisation.Orientation
        
        measurednaox = self.NAOFinder.NaoX
        measurednaoy = self.NAOFinder.NaoY
        measurednaoorientation = self.NAOFinder.NaoOrientation
        
        self.positionmeasurementplot[0].set_data([measurednaoy, measurednaoy], [measurednaox, measurednaox])
        self.orientationmeasurementplot[0].set_data([measurednaoy + 10*numpy.sin(measurednaoorientation - numpy.pi), measurednaoy + 10*numpy.sin(measurednaoorientation)], [measurednaox + 10*numpy.cos(measurednaoorientation - numpy.pi), measurednaox + 10*numpy.cos(measurednaoorientation)])
        self.shapeplot[0].set_data(self.NAOFinder.ShapeY, self.NAOFinder.ShapeX)
        self.naohistoryx.append(naox)
        self.naohistoryy.append(naoy)
        if len(self.naohistoryx) > 20:
            del self.naohistoryx[0]
            del self.naohistoryy[0]
        self.naohistoryplot[0].set_data(self.naohistoryy, self.naohistoryx)

        self.estimateplot[0].set_data([naoy, naoy + 10*numpy.sin(self.Localisation.Orientation)], [naox, naox + 10*numpy.cos(self.Localisation.Orientation)])
        #self.particleplot = self.axes.quiver(numpy.array(self.Localisation.States[:,Localisation.Y]), numpy.array(self.Localisation.States[:,Localisation.X]), -numpy.sin(self.Localisation.States[:,Localisation.THETA]), numpy.cos(self.Localisation.States[:,Localisation.THETA]), 1.0 - self.Localisation.GUIWeights, headlength=10, headwidth=10, width=0.001, scale=50.0)

        self.axes.set_xlim(naoy + 50, naoy - 50)
        self.axes.set_ylim(naox - 25, naox + 25)
        # restore the clean slate background
        self.canvas.restore_region(self.background)
        # just draw the animated artist
        self.axes.draw_artist(self.shapeplot[0])
        #self.axes.draw_artist(self.particleplot)
        self.axes.draw_artist(self.naohistoryplot[0])
        self.axes.draw_artist(self.orientationmeasurementplot[0])
        self.axes.draw_artist(self.positionmeasurementplot[0]) 
        self.axes.draw_artist(self.estimateplot[0]) 

        # just redraw the axes rectangle
        self.canvas.blit(self.axes.bbox)
        
        
        #leftx = list()
        #lefty = list()
        #for leftedge in self.NAOFinder.LeftEdges:
        #    leftx.append(data[0][leftedge])
        #    lefty.append(data[1][leftedge])
        
        #rightx = list()
        #righty = list()
        #for rightedge in self.NAOFinder.RightEdges:
        #    rightx.append(data[0][rightedge])
        #    righty.append(data[1][rightedge])
        
        #self.leftedgeplot[0].set_data(lefty, leftx)
        #self.rightedgeplot[0].set_data(righty, rightx)

    def OnNaoPanelPaint(self, event):
        pass
示例#37
0
class BaseInteractorsPanel(wx.Panel):
    def __init__(self, parent=None):
        super().__init__(parent=parent)

        self.interactors: List = []
        self.factor = None
        self.image_id = None
        self.background = None

        self.BuildUI()

    def BuildUI(self):
        self.figure: Figure = Figure()
        self.axes: Axes = self.figure.add_subplot(1, 1, 1)
        self.axes.set_aspect("equal")
        self.canvas = FigureCanvas(self, id=wx.ID_ANY, figure=self.figure)
        self.figure.tight_layout()

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.canvas, flag=wx.EXPAND, proportion=1)
        self.SetSizer(sizer)

        self.canvas.mpl_connect("draw_event", self.DrawCallback)
        self.canvas.mpl_connect("button_press_event", self.OnClick)
        self.canvas.mpl_connect("button_release_event", self.OnMouseButtonUp)
        self.canvas.mpl_connect("motion_notify_event", self.OnMouseMoved)
        self.canvas.mpl_connect("key_press_event", self.OnKeyPress)
        self.canvas.mpl_connect("key_release_event", self.OnKeyRelease)

    def DrawCallback(self, event: MouseEvent):
        self.background = self.canvas.copy_from_bbox(self.axes.bbox)

        for interactor in self.interactors:
            interactor.draw_callback(event)

        self.canvas.blit(self.axes.bbox)

    def OnClick(self, event: MouseEvent):
        if event.inaxes != self.axes:
            return
        if event.inaxes.get_navigate_mode() is not None:
            return

        for interactor in self.interactors:
            interactor.button_press_callback(event)

    def OnMouseButtonUp(self, event: MouseEvent):
        if event.inaxes is not None and event.inaxes.get_navigate_mode(
        ) is not None:
            return

        for interactor in self.interactors:
            interactor.button_release_callback(event)

    def OnMouseMoved(self, event: MouseEvent):
        if event.inaxes != self.axes:
            return

        self.UpdateInteractors(event)

    def OnKeyPress(self, event: MouseEvent):
        if event.inaxes != self.axes:
            return
        if event.inaxes.get_navigate_mode() is not None:
            return

        for interactor in self.interactors:
            interactor.key_press_event(event)

        self.UpdateInteractors(event)

    def OnKeyRelease(self, event: MouseEvent):
        if event.inaxes != self.axes:
            return
        if event.inaxes.get_navigate_mode() is not None:
            return

        for interactor in self.interactors:
            interactor.key_release_event(event)

        self.UpdateInteractors(event)

    def UpdateInteractors(self, event: MouseEvent):
        if self.background is not None:
            self.canvas.restore_region(self.background)
        else:
            self.background = self.canvas.copy_from_bbox(self.axes.bbox)

        for interactor in self.interactors:
            interactor.motion_notify_callback(event)
            interactor.draw_callback(event)

        self.canvas.blit(self.axes.bbox)

    def Render(self, image: Image):
        self.axes.clear()
        self.axes.imshow(image, interpolation="lanczos", vmin=0, vmax=255)
示例#38
0
文件: netview.py 项目: JustasB/ACnet2
class PlotFrame(wx.Frame):
    """
        PlotFrame is a custom wxPython frame to hold the panel with a
        Figure and WxAgg backend canvas for matplotlib plots or other
        figures.  In this frame:

        self is an instance of a wxFrame;
        axes is an instance of MPL Axes;
        fig is an instance of MPL Figure;
        panel is an instance of wxPanel, used for the main panel, to hold
        canvas, an instance of MPL FigureCanvasWxAgg.
    """

    # Main function to set everything up when the frame is created
    def __init__(self, title, pos, size):

        """
           This will be executed when an instance of PlotFrame is created.
           It is the place to define any globals as "self.<name>".
        """
        wx.Frame.__init__(self, None, wx.ID_ANY, title, pos, size)

        if len(sys.argv) < 2:
            self.filename = ""
        else:
            self.filename =  sys.argv[1]

        # set some Boolean flags
        self.STOP = False
        self.data_loaded = False
        self.reverse_play = False

        self.step = 1

        #    Make the main Matplotlib panel for plots
        self.create_main_panel()  # creates canvas and contents

        # Then add wxPython widgets below the MPL canvas
	# Layout with box sizers

        self.sizer = wx.BoxSizer(wx.VERTICAL)
	self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.EXPAND)
	self.sizer.AddSpacer(10)
	self.sizer.Add(self.toolbar, 0, wx.EXPAND)
	self.sizer.AddSpacer(10)

        #    Make the control panel with a row of buttons
        self.create_button_bar()
        self.sizer.Add(self.button_bar_sizer, 0, flag = wx.ALIGN_CENTER | wx.TOP)

        #    Make a Status Bar
        self.statusbar = self.CreateStatusBar()
        self.sizer.Add(self.statusbar, 0, wx.EXPAND)

        self.SetStatusText("Frame created ...")

        # -------------------------------------------------------
        #	       set up the Menu Bar
        # -------------------------------------------------------
        menuBar = wx.MenuBar()

        menuFile = wx.Menu() # File menu
        menuFile.Append(1, "&Open", "Filename(s) or wildcard list to plot")
        menuFile.Append(3, "Save", "Save plot as a PNG image")
        menuFile.AppendSeparator()
        menuFile.Append(10, "E&xit")
        menuBar.Append(menuFile, "&File")

        menuHelp = wx.Menu() # Help menu
        menuHelp.Append(11, "&About Netview")
        menuHelp.Append(12, "&Usage and Help")
        menuHelp.Append(13, "Program &Info")

        menuBar.Append(menuHelp, "&Help")
        self.SetMenuBar(menuBar)

        self.panel.SetSizer(self.sizer)
        self.sizer.Fit(self)

        # -------------------------------------------------------
        #      Bind the menu items to functions
        # -------------------------------------------------------

        self.Bind(wx.EVT_MENU, self.OnOpen, id=1)
        self.Bind(wx.EVT_MENU, self.OnSave, id=3)
        self.Bind(wx.EVT_MENU, self.OnQuit, id=10)
        self.Bind(wx.EVT_MENU, self.OnAbout, id=11)
	self.Bind(wx.EVT_MENU, self.OnUsage, id=12)
        self.Bind(wx.EVT_MENU, self.OnInfo, id=13)
	
        # methods defined below to get and plot the data
        # Normally do the plot on request, and not here
        # self.get_data_params()
        # self.init_plot()
        # self.get_xyt_data()
        # plot_data()

	# ---------- end of __init__ ----------------------------

    # -------------------------------------------------------
    #   Function to make the main Matplotlib panel for plots
    # -------------------------------------------------------

    def create_main_panel(self):
        """ create_main_panel creates the main mpl panel with instances of:
             * mpl Canvas 
             * mpl Figure 
             * mpl Figure
             * mpl Axes with subplot
             * mpl Widget class Sliders and Button
             * mpl navigation toolbar
           self.axes is the instance of MPL Axes, and is where it all happens
        """

        self.panel = wx.Panel(self)
        
        # Create the mpl Figure and FigCanvas objects. 
        # 3.5 x 5 inches, 100 dots-per-inch
        #
        self.dpi = 100
        self.fig = Figure((3.5, 5.0), dpi=self.dpi)
        self.canvas = FigCanvas(self.panel, wx.ID_ANY, self.fig)
        
        # Since we have only one plot, we could use add_axes 
        # instead of add_subplot, but then the subplot
        # configuration tool in the navigation toolbar wouldn't work.


        self.axes = self.fig.add_subplot(111)
        # (111) == (1,1,1) --> row 1, col 1, Figure 1)
        # self.axes.set_title("View from: "+self.filename)

        # Now create some sliders below the plot after making room
        self.fig.subplots_adjust(left=0.1, bottom=0.20)

        self.axtmin = self.fig.add_axes([0.2, 0.10, 0.5, 0.03])
        self.axtmax = self.fig.add_axes([0.2, 0.05, 0.5, 0.03])

        self.stmin = Slider(self.axtmin, 't_min:', 0.0, 1.0, valinit = 0.0)
        self.stmax = Slider(self.axtmax, 't_max:', 0.0, 1.0, valinit = 1.0)
        self.stmin.on_changed(self.update_trange)
        self.stmax.on_changed(self.update_trange)

        self.axbutton = self.fig.add_axes([0.8, 0.07, 0.1, 0.07])
        self.reset_button = Button(self.axbutton, 'Reset')
        self.reset_button.color = 'skyblue'
        self.reset_button.hovercolor = 'lightblue'
        self.reset_button.on_clicked(self.reset_trange)

        # Create the navigation toolbar, tied to the canvas

        self.toolbar = NavigationToolbar(self.canvas)

    def update_trange(self, event):
        self.t_min = self.stmin.val
        self.t_max = self.stmax.val
        # print(self.t_min, self.t_max)

    def reset_trange(self, event):
        self.stmin.reset()
        self.stmax.reset()

    def create_button_bar(self):
	"""
	create_button_bar makes a control panel bar with buttons and
	toggles for

	New Data - Play - STOP - Single Step - Forward/Back - Normal/Fast

	It does not create a Panel container, but simply creates Button
	objects with bindings, and adds  them to a horizontal BoxSizer
	self.button_bar_sizer.	This is added to the PlotFrame vertical
	BoxSizer, after the MPL canvas, during initialization of the frame.

	"""
	rewind_button = wx.Button(self.panel, -1, "New Data")
	self.Bind(wx.EVT_BUTTON, self.OnRewind, rewind_button)

	replot_button = wx.Button(self.panel, -1, "Play")
	self.Bind(wx.EVT_BUTTON, self.OnReplot, replot_button)

	sstep_button = wx.Button(self.panel, -1, "Single Step")
	self.Bind(wx.EVT_BUTTON, self.OnSstep, sstep_button)

	stop_button = wx.Button(self.panel, -1, "STOP")
	self.Bind(wx.EVT_BUTTON, self.OnStop, stop_button)

	# The toggle buttons need to be globally accessible

	self.forward_toggle = wx.ToggleButton(self.panel, -1, "Forward")
	self.forward_toggle.SetValue(True)
	self.forward_toggle.SetLabel("Forward")
	self.Bind(wx.EVT_TOGGLEBUTTON, self.OnForward, self.forward_toggle)

	self.fast_toggle = wx.ToggleButton(self.panel, -1, " Normal ")
        self.fast_toggle.SetValue(True)
        self.fast_toggle.SetLabel(" Normal ")
        self.Bind(wx.EVT_TOGGLEBUTTON, self.OnFast, self.fast_toggle)

        # Set button colors to some simple colors that are likely
        # to be independent on X11 color definitions.  Some nice
        # bit maps (from a media player skin?) should be used
        # or the buttons and toggle state colors in OnFast() below

        rewind_button.SetBackgroundColour('skyblue')
        replot_button.SetBackgroundColour('skyblue')
        sstep_button.SetBackgroundColour('skyblue')
        stop_button.SetBackgroundColour('skyblue')
        self.forward_toggle.SetForegroundColour('black')
        self.forward_toggle.SetBackgroundColour('yellow')
        self.fast_toggle.SetForegroundColour('black')
        self.fast_toggle.SetBackgroundColour('yellow')
        self.button_bar_sizer = wx.BoxSizer(wx.HORIZONTAL)
        flags = wx.ALIGN_CENTER | wx.ALL
        self.button_bar_sizer.Add(rewind_button, 0, border=3, flag=flags)
        self.button_bar_sizer.Add(replot_button, 0, border=3, flag=flags)
        self.button_bar_sizer.Add(sstep_button, 0, border=3, flag=flags)
        self.button_bar_sizer.Add(stop_button, 0, border=3, flag=flags)
        self.button_bar_sizer.Add(self.forward_toggle, 0, border=3, flag=flags)
        self.button_bar_sizer.Add(self.fast_toggle, 0, border=3, flag=flags)

    # -------------------------------------------------------
    #	Functions to generate or read (x,y) data and plot it
    # -------------------------------------------------------

    def get_data_params(self):
        #  These parameters  would normally be provided in a file header,
        # past as arguments in a function, or from other file information
        #  Next version will bring up a dialog for dt NX NY if no file header

        # Here check to see if a filename should be entered from File/Open
        # self.filename = 'Ex_net_Vm_0001.txt'
        if len(self.filename) == 0:
            # fake a button press of File/Open
            self.OnOpen(wx.EVT_BUTTON)

        # should check here if file exists as specified [path]/filename

        # assume it is a bzip2 compressed file
        try:
      	    fp = bz2.BZ2File(self.filename)
	    line = fp.readline()
        except IOError:
            # then assume plain text
            fp = open(self.filename)
	    line = fp.readline()
       
        fp.close()

        # check if first line is a header line starting with '#'
        header = line.split()
        if header[0][0] == "#": 
            self.Ntimes = int(header[1])
            self.t_min =  float(header[2])
            self.dt = float(header[3])
            self.NX = int(header[4])
            self.NY = int(header[5])
        else:
            pdentry = self.ParamEntryDialog()
            if pdentry.ShowModal() ==  wx.ID_OK:
                self.Ntimes = int(pdentry.Ntimes_dialog.entry.GetValue())
		self.t_min = float(pdentry.tmin_dialog.entry.GetValue())
		self.dt = float(pdentry.dt_dialog.entry.GetValue())
                self.NX	= int(pdentry.NX_dialog.entry.GetValue())
                self.NY = int(pdentry.NY_dialog.entry.GetValue())
                print 'Ntimes = ', self.Ntimes, ' t_min = ', self.t_min
                print 'NX = ', self.NX, ' NY = ', self.NY
            pdentry.Destroy()
        self.t_max = (self.Ntimes - 1)*self.dt
        # reset slider max and min
        self.stmin.valmax = self.t_max
        self.stmin.valinit = self.t_min
        self.stmax.valmax = self.t_max
        self.stmax.valinit = self.t_max
        self.stmax.set_val(self.t_max)
        self.stmin.reset()
        self.stmax.reset()
        fp.close()

    def init_plot(self):
        ''' 
        init_plot creates the initial plot display. A normal MPL plot
	would be created here with a command "self.axes.plot(x, y)" in
	order to create a plot of points in the x and y arrays on the
	Axes subplot.  Here, we create an AxesImage instance with
	imshow(), instead.  The initial image is a blank one of the
	proper dimensions, filled with zeroes.

        '''
        self.t_max = (self.Ntimes - 1)*self.dt
        self.axes.set_title("View of "+self.filename)
        # Note that NumPy array (row, col) = image (y, x)
        data0 = np.zeros((self.NY,self.NX))

        # Define a 'cold' to 'hot' color scale based in GENESIS 2 'hot'
        hotcolors = ['#000032', '#00003c', '#000046',
        '#000050', '#00005a', '#000064', '#00006e', '#000078', '#000082',
        '#00008c', '#000096', '#0000a0', '#0000aa', '#0000b4', '#0000be',
        '#0000c8', '#0000d2', '#0000dc', '#0000e6', '#0000f0', '#0000fa',
        '#0000ff', '#000af6', '#0014ec', '#001ee2', '#0028d8', '#0032ce',
        '#003cc4', '#0046ba', '#0050b0', '#005aa6', '#00649c', '#006e92',
        '#007888', '#00827e', '#008c74', '#00966a', '#00a060', '#00aa56',
        '#00b44c', '#00be42', '#00c838', '#00d22e', '#00dc24', '#00e61a',
        '#00f010', '#00fa06', '#00ff00', '#0af600', '#14ec00', '#1ee200',
        '#28d800', '#32ce00', '#3cc400', '#46ba00', '#50b000', '#5aa600',
        '#649c00', '#6e9200', '#788800', '#827e00', '#8c7400', '#966a00',
        '#a06000', '#aa5600', '#b44c00', '#be4200', '#c83800', '#d22e00',
        '#dc2400', '#e61a00', '#f01000', '#fa0600', '#ff0000', '#ff0a00',
        '#ff1400', '#ff1e00', '#ff2800', '#ff3200', '#ff3c00', '#ff4600',
        '#ff5000', '#ff5a00', '#ff6400', '#ff6e00', '#ff7800', '#ff8200',
        '#ff8c00', '#ff9600', '#ffa000', '#ffaa00', '#ffb400', '#ffbe00',
        '#ffc800', '#ffd200', '#ffdc00', '#ffe600', '#fff000', '#fffa00',
        '#ffff00', '#ffff0a', '#ffff14', '#ffff1e', '#ffff28', '#ffff32',
        '#ffff3c', '#ffff46', '#ffff50', '#ffff5a', '#ffff64', '#ffff6e',
        '#ffff78', '#ffff82', '#ffff8c', '#ffff96', '#ffffa0', '#ffffaa',
        '#ffffb4', '#ffffbe', '#ffffc8', '#ffffd2', '#ffffdc', '#ffffe6',
        '#fffff0']

        cmap = matplotlib.colors.ListedColormap(hotcolors)

        self.im = self.axes.imshow(data0, cmap=cmap, origin='lower')

        # http://matplotlib.sourceforge.net/examples/pylab_examples/show_colormaps.html
        # shows examples to use as a 'cold' to 'hot' mapping of value to color
        # cm.jet, cm.gnuplot and cm.afmhot are good choices, but are unlike G2 'hot'

        self.im.cmap=cmap

        # Not sure how to properly add a colorbar
        # self.cb = self.fig.colorbar(self.im, orientation='vertical')

        # refresh the canvas
        self.canvas.draw()      

    def get_xyt_data(self):
        # Create scaled (0-1) luminance(x,y) array from ascii G-2 disk_out file
        # get the data to plot from the specified filename
        # Note that NumPy loadtxt transparently deals with bz2 compression
        self.SetStatusText('Data loading - please wait ....')
        rawdata = np.loadtxt(self.filename)
        # Note the difference between NumPy [row, col] order and network
        # x-y grid (x, y) = (col, row). We want a NumPy NY x NX, not 
        # NX x NY, array to be used by the AxesImage object.

        xydata = np.resize(rawdata, (self.Ntimes, self.NY, self.NX))
        # imshow expects the data to be scaled to range 0-1.
        Vmin = xydata.min()
        Vmax = xydata.max()
        self.ldata = (xydata - Vmin)/(Vmax - Vmin)
        self.data_loaded = True
        self.SetStatusText('Data has been loaded - click Play')

    def plot_data(self):
        ''' plot_data() shows successive frames of the data that was loaded
            into the ldata array.  Creating a new self.im AxesImage instance
            for each frame is extremely slow, so the set_data method of
            AxesImage is used to load new data into the existing self.im for
            each frame.  Normally 'self.canvas.draw()' would be used to
            display a frame, but redrawing the entire canvas, redraws the
            axes, labels, sliders, buttons, or anything else on the canvas.
            This uses a method taken from an example in Ch 7, p. 192
            Matplotlib for Python developers, with draw_artist() and blit()
            redraw only the part that was changed.

        '''
        if self.data_loaded == False:
            # bring up a warning dialog
            msg = """
            Data for plotting has not been loaded!
            Please enter the file to plot with File/Open, unless
            it was already specified, and then click on 'New Data'
            to load the data to play back, before clicking 'Play'.
            """
            wx.MessageBox(msg, "Plot Warning", wx.OK | wx.ICON_ERROR,self)
            return

        # set color limits
        self.im.set_clim(0.0, 1.0)
        self.im.set_interpolation('nearest')
        # 'None' is is slightly faster, but not implemented for MPL ver < 1.1
        # self.im.set_interpolation('None')

        # do an initial draw, then save the empty figure axes
        self.canvas.draw()      

        # self.bg = self.canvas.copy_from_bbox(self.axes.bbox)
        # However the save and restore is only  needed if I change
        # axes legends, etc.  The draw_artist(artist), and blit
        # are much faster than canvas.draw() and are sufficient.

        print 'system time (seconds) = ', time.time()

        # round frame_min down and frame_max up for the time window
        frame_min = int(self.t_min/self.dt)
        frame_max = min(int(self.t_max/self.dt) + 1, self.Ntimes)
        frame_step = self.step

        # Displaying simulation time to the status bar is much faster
        # than updating a slider progress bar, but location isn't optimum.
        # The check for the STOP button doesn't work because the button
        # click is not registered until this function exits.

        # check to see if self.reverse_play == True
        # then interchange frame_min, frame_max, and use negative step
        if self.reverse_play == True:
            frame_min = min(int(self.t_max/self.dt) + 1, self.Ntimes) - 1
            frame_max = int(self.t_min/self.dt) - 1
            frame_step = -self.step
        for frame_num in range(frame_min, frame_max, frame_step):
            self.SetStatusText('time: '+str(frame_num*self.dt))
            if self.STOP == True:
                self.t_min = frame_num*self.dt
                # set t_min slider ?
                self.STOP = False
                break
            self.im.set_data(self.ldata[frame_num])
            self.axes.draw_artist(self.im)
            self.canvas.blit(self.axes.bbox)

        print 'system time (seconds) = ', time.time()

    #  ------------------------------------------------------------------
    #	Define the classes and functions for getting parameter values
    #  --------------------------------------------------------------

    class ParamEntryDialog(wx.Dialog):
        def __init__(self):
	    wx.Dialog.__init__(self, None, wx.ID_ANY)
	    self.SetSize((250, 200))
	    self.SetTitle('Enter Data File Parameters')
	    vbox = wx.BoxSizer(wx.VERTICAL)
	    self.Ntimes_dialog = XDialog(self)
	    self.Ntimes_dialog.entry_label.SetLabel('Number of entries')
	    self.Ntimes_dialog.entry.ChangeValue(str(2501))
	    self.tmin_dialog = XDialog(self)
	    self.tmin_dialog.entry_label.SetLabel('Start time (sec)')
	    self.tmin_dialog.entry.ChangeValue(str(0.0))

	    self.dt_dialog = XDialog(self)
	    self.dt_dialog.entry_label.SetLabel('Output time step (sec)')
	    self.dt_dialog.entry.ChangeValue(str(0.0002))

	    self.NX_dialog = XDialog(self)
	    self.NX_dialog.entry_label.SetLabel('Number of cells on x-axis')
            self.NX_dialog.entry.ChangeValue(str(32))
            self.NY_dialog = XDialog(self)
            self.NY_dialog.entry_label.SetLabel('Number of cells on y-axis')
            self.NY_dialog.entry.ChangeValue(str(32))

            vbox.Add(self.Ntimes_dialog, 0, wx.EXPAND|wx.ALL, border=5)
            vbox.Add(self.tmin_dialog, 0, wx.EXPAND|wx.ALL, border=5)
            vbox.Add(self.dt_dialog, 0, wx.EXPAND|wx.ALL, border=5)
            vbox.Add(self.NX_dialog, 0, wx.EXPAND|wx.ALL, border=5)
            vbox.Add(self.NY_dialog, 0, wx.EXPAND|wx.ALL, border=5)

            okButton = wx.Button(self, wx.ID_OK,'Ok')
	    # vbox.Add(okButton,flag=wx.ALIGN_CENTER|wx.TOP|wx.BOTTOM, border=10)
	    vbox.Add(okButton,flag=wx.ALIGN_CENTER, border=10)

            self.SetSizer(vbox)
	    self.SetSizerAndFit(vbox)

    #  ------------------------------------------------------------------
    #	Define the functions executed on menu choices
    #  ---------------------------------------------------------------
         
    def OnQuit(self, event):
        self.Close()

    def OnSave(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 OnAbout(self, event):
	msg = """

                      G-3 Netview ver. 1.7

Netview is a stand-alone Python application for viewing
the output of GENESIS 2 and 3 network simulations.
It is intended to replace GENESIS 2 SLI scripts that use the
XODUS 'xview' widget.

The design and operation is based on the G3Plot application
for creating 2D plots of y(t) or y(x) from data files.
Unlike G3Plot, the image created with Netview is an animated
representation of a rectangular network with colored squares
used to indicate the value of some variable at that position
and time.  Typically, this would be the membrane potenial of
a cell soma, or a synaptic current in a dendrite segment.

Help/Usage gives HTML help for using Netview.
This is the main Help page.

Help/Program Info provides some information about the
objects and functions, and the wxPython and matplotlib
classes used here.

Dave Beeman, August 2012
	"""
        dlg = wx.MessageDialog(self, msg, "About G-3 Netview",
            wx.OK | wx.ICON_QUESTION)
	dlg.ShowModal()
	dlg.Destroy()

    def OnOpen(self, event):
        dlg = wx.TextEntryDialog(self, "File with x,y data to plot",
	    "File Open", self.filename, style=wx.OK|wx.CANCEL)
        if dlg.ShowModal() == wx.ID_OK:
            self.filename = dlg.GetValue()
            # A new filename has been entered, but the data has not been read
            self.data_loaded = False
            # print "You entered: %s" % self.filename     
        dlg.Destroy()

    #  This starts with the long string of HTML to display
    class UsageFrame(wx.Frame):
        text = """
<HTML>
<HEAD></HEAD>
<BODY BGCOLOR="#D6E7F7">

<CENTER><H1>Using G-3 Netview</H1></CENTER>

<H2>Introduction and Quick Start</H2>

<p>Netview is a stand-alone Python application for viewing the output of
GENESIS 2 and 3 network simulations.  It is intended to replace GENESIS 2
SLI scripts that use the XODUS 'xview' widget.</p>

<p>The design and operation is based on the G3Plot application for creating 2D
plots of y(t) or y(x) from data files.  As with G3Plot, the main class
PlotFrame uses a basic wxPython frame to embed a matplotlib figure for
plotting.  It defines some basic menu items and a control panel of buttons
and toggles, each with bindings to a function to execute on a mouse click.</p>

<p>Unlike G3Plot, the image created with Netview is an animated
representation of a rectangular network with colored squares
used to indicate the value of some variable at that position
and time.  Typically, this would be the membrane potenial of
a cell soma, or a synaptic current in a dendrite segment.</p>

<h2>Usage</h2>

<p>The Menu Bar has <em>File/Open</em>, <em>File/Save</em>, and
<em>File/Exit</em> choices.  The Help Menu choices <em>About</em> and
<em>Usage</em> give further information.  The <em>Program Info</em>
selection shows code documentation that is contained in some of the main
function <em>docstrings</em>.</p>

<p>After starting the <em>netview</em> program, enter a data file name
in the dialog for File/Open, unless the filename was given as a
command line argument.  Then click on <strong>New Data</strong> to load the new
data and initialize the plot.  When the plot is cleared to black,
press <strong>Play</strong>.</p>

<p>The file types recognized are plain text or text files compressed with
bzip2.  The expected data format is one line for each output time step,
with each line having the membrane potential value of each cell in the net.
No time value should be given on the line.  In order to properly display
the data, netview needs some additional information about the network and
the data.  This can optionally be contained in a header line that precedes
the data.  If a header is not detected, a dialog will appear asking for the
needed parameters.</p>

<p>It is assumed that the cells are arranged on a NX x NY grid, numbered
from 0 (bottom left corner) to NX*NY - 1 (upper right corner).
In order to provide this information to netview, the data file should
begin with a header line of the form:</p>

<pre>
    #optional_RUNID_string Ntimes start_time dt NX NY SEP_X SEP_Y x0 y0 z0
</pre>

<p>The line must start with &quot;#&quot; and can optionally be followed immediately by any
string.  Typically this is some identification string generated by the
simulation run.  The following parameters, separated by blanks or any
whitespace, are:</p>

<ul>
<li>Ntimes - the number of lines in the file, exclusive of the header</li>
<li>start_time - the simulation time for the first data line (default 0.0)</li>
<li>dt - the time step used for output</li>
<li>NX, NY - the integer dimensions of the network</li>
<li>SEP_X, SEP_Y - the x,y distances between cells (optional)</li>
<li>x0, y0, z0 - the location of the compartment (data source) relative to the
cell origin</li>
</ul>

<p>The RUNID string and the last five parameters are not read or used
by netview.  These are available for other data analysis tools that
need a RUNID and the location of each source.</p>

<p>The slider bars can be used to set a time window for display, and the
<strong>Reset</strong> button can set t_min and t_max back to the defaults.
Use the <strong>Forward/Back</strong> toggle to reverse direction of
<strong>Play</strong>, and the <strong>Normal/Fast</strong> toggle to show
every tenth frame.</p> <p>The <strong>Single Step</strong> button can be
used to advance a single step at a time (or 10, if in 'Fast' mode).</p>

<p>The <strong>STOP</strong> button is currently not implemented</p>
<p>To plot different data, enter a new filename with <strong>File/Open</strong> and
repeat with <strong>New Data</strong> and <strong>Play</strong>.</p>

<HR>
</BODY>
</HTML>
        """

        def __init__(self, parent):
            wx.Frame.__init__(self, parent, -1, "Usage and Help",
                size=(640,600), pos=(400,100))
            html = wx.html.HtmlWindow(self)
            html.SetPage(self.text)
            panel = wx.Panel(self, -1)
            button = wx.Button(panel, wx.ID_OK, "Close")
            self.Bind(wx.EVT_BUTTON, self.OnCloseMe, button)
            sizer = wx.BoxSizer(wx.VERTICAL)
            sizer.Add(html, 1, wx.EXPAND|wx.ALL, 5)
            sizer.Add(panel, 0, wx.ALIGN_CENTER|wx.ALL, 5)
            self.SetSizer(sizer)
            self.Layout()

	def OnCloseMe(self, event):
            self.Close(True)

        # ----------- end of class UsageFrame ---------------

    def OnUsage(self,event):
        usagewin = self.UsageFrame(self)
        usagewin.Show(True)

    def OnInfo(self,event):
        msg = "Program information for PlotFrame obtained from docstrings:"
        msg += "\n" + self.__doc__ + "\n" + self.create_main_panel.__doc__
        msg += self.create_button_bar.__doc__
        msg += self.init_plot.__doc__
        msg += self.plot_data.__doc__
        dlg = wx.lib.dialogs.ScrolledMessageDialog(self, msg,
            "PlotFrame Documentation")
        dlg.ShowModal()

    #  ---------------------------------------------------------------
    #	Define the functions executed on control button click
    #  ---------------------------------------------------------------

    def OnRewind(self,event):
        self.get_data_params()
        self.init_plot()
        self.get_xyt_data()

    def OnReplot(self,event):
        self.plot_data()
        self.canvas.draw()

    def OnSstep(self,event):
        if self.data_loaded == False:
            # bring up a warning dialog
            msg = """
            Data for plotting has not been loaded!
            Please enter the file to plot with File/Open, unless
            it was already specified, and then click on 'New Data'
            to load the data to play back, before clicking 'Play'.
            """
            wx.MessageBox(msg, "Plot Warning", wx.OK | wx.ICON_ERROR,self)
            return

        self.t_max = min(self.t_max + self.dt, (self.Ntimes - 1)*self.dt)
        self.stmax.set_val(self.t_max)
        frame_num = int(self.t_max/self.dt)
        self.SetStatusText('time: '+str(frame_num*self.dt))
        self.im.set_data(self.ldata[frame_num])
        self.axes.draw_artist(self.im)
        self.canvas.blit(self.axes.bbox)

    def OnStop(self,event):
        self.STOP = 'True'

    def OnForward(self,event):
        state =	 self.forward_toggle.GetValue()
        if state:
            self.reverse_play = False
            self.forward_toggle.SetLabel("Forward ")
            self.forward_toggle.SetForegroundColour('black')
            self.forward_toggle.SetBackgroundColour('yellow')
        else:
            self.reverse_play = True
            self.forward_toggle.SetLabel("  Back  ")
            self.forward_toggle.SetForegroundColour('red')
            self.forward_toggle.SetBackgroundColour('green')

    def OnFast(self,event):
        state =	 self.fast_toggle.GetValue()
        if state:
            # print state
            self.fast_toggle.SetLabel(" Normal ")
            self.fast_toggle.SetForegroundColour('black')
            self.fast_toggle.SetBackgroundColour('yellow')
            self.step = 1
        else:
            # print state
            self.fast_toggle.SetLabel("  Fast  ")
            self.fast_toggle.SetForegroundColour('red')
            self.fast_toggle.SetBackgroundColour('green')
            self.step = 10
示例#39
0
class PlotFigure(wx.Frame):
    def __init__(self):
        self.screen_size = wx.DisplaySize()
        #print("the screen size is {0}".format(self.screen_size))
        self.screen_dpi = 100
        self.frame_length = int(self.screen_size[0])
        self.frame_width = int(self.screen_size[1])
        self.fig_length = self.frame_length // self.screen_dpi
        self.fig_width = self.frame_width // self.screen_dpi
        self.frame_length = self.fig_length * self.screen_dpi
        self.frame_width = self.fig_width * self.screen_dpi
        wx.Frame.__init__(self,
                          None,
                          wx.ID_ANY,
                          title='CP1/X86 TPCC Performance Comparison',
                          size=(self.frame_length, self.frame_width)
                          #size=(1900, 1000)
                          )
        # Matplotlib Figure, x/y-size should size_in_Frame/dpi
        #eg: 1800 = 15 * 120, 600 = 5 * 120
        #self.fig = Figure((19, 10), 100)
        self.fig = Figure((self.fig_length, self.fig_width), self.screen_dpi)

        #print(self.frame_length, self.frame_width)
        #print(self.fig_length, self.fig_width)

        self.canvas = FigureCanvas(self, wx.ID_ANY, self.fig)

        self.ax = self.fig.add_subplot(211)
        self.ax.set_ylim([Y_MIN_VALUE, Y_MAX_VALUE])
        self.ax.set_xlim([X_MIN_VALUE, X_MAX_VALUE])

        self.ax.set_autoscale_on(False)

        #self.ax.set_xticks([])
        self.ax.set_xticks(range(0, 61, 10))
        #self.ax.set_xticks(range(X_MIN_VALUE, X_MAX_VALUE + 1, X_STEP_VALUE))
        self.ax.set_yticks(range(Y_MIN_VALUE, Y_MAX_VALUE + 1, Y_STEP_VALUE))

        self.ax.set_xlabel("Time(second)")
        self.ax.set_ylabel("Transactions Per Minute(tpmC)")
        self.ax.grid(True)

        self.power8_current_all_values = [None] * EMPTY_NUMBER
        self.x86_current_all_values = [None] * EMPTY_NUMBER
        self.power8_plot, = self.ax.plot(
            range(EMPTY_NUMBER),
            #self.power8_current_all_values, label='CP1 Value',
            self.power8_current_all_values,
            label='CP1 TPC-C',
            #color='red', linestyle = ':', linewidth = 2, marker = 'o'
            color='red',
            marker='.')
        self.x86_plot, = self.ax.plot(
            range(EMPTY_NUMBER),
            #self.x86_current_all_values, label='X86 Value',
            self.x86_current_all_values,
            label='X86 TPC-C',
            color='green',
            marker='.')

        self.ax.legend(loc='upper center',
                       ncol=4,
                       prop=font_manager.FontProperties(size=16)
                       #prop=font_manager.FontProperties(size=10)
                       )

        # for 2nd subplot
        self.average = self.fig.add_subplot(212)
        self.average.set_ylim(0, 6)
        #self.average.set_xlim(Y_MIN_VALUE, Y_MAX_VALUE)
        self.average.set_xlim(Y_MIN_VALUE, 300000)

        #self.average.set_ylabel("yHello world")
        self.average.set_xlabel("Transactions Per Minute(tpmC)")

        self.power8_accumulate_value = 0
        self.x86_accumulate_value = 0
        self.power8_previous_value = 0
        self.x86_previous_value = 0

        self.power8_ave_index = [3]
        self.x86_ave_index = [1]
        self.power8_ave_value = [0]
        self.x86_ave_value = [0]
        self.power8_barh, = self.average.barh(bottom=self.power8_ave_index,
                                              width=self.power8_ave_value,
                                              height=1.0,
                                              color='red',
                                              label='CP1 TPC-C (Average)')
        self.x86_barh, = self.average.barh(bottom=self.x86_ave_index,
                                           width=self.x86_ave_value,
                                           height=1.0,
                                           color='green',
                                           label="X86 TPC-C (Average)")

        self.average.grid(True)
        self.average.legend(loc='upper center',
                            ncol=4,
                            prop=font_manager.FontProperties(size=16)
                            #prop=font_manager.FontProperties(size=10)
                            )
        self.average.set_yticks([])

        self.fig.subplots_adjust(left=0.08, right=0.95, bottom=0.05, top=0.95)

        ##########################################################################################

        # TODO: resize the subplot in figure
        self.ax.set_position([0.08, 0.40, 0.85, 0.55])
        self.average.set_position([0.08, 0.05, 0.85, 0.28])

        self.canvas.draw()
        # save the clean background
        self.background_1st = self.canvas.copy_from_bbox(self.ax.bbox)
        self.background_2nd = self.canvas.copy_from_bbox(self.average.bbox)

        self.global_timer_index = 0
        self.local_timer_index = 0
        self.power8_current_all_values = []
        self.x86_current_all_values = []

        wx.EVT_TIMER(self, TIMER_ID, self.on_timer)

    def on_timer(self, event):
        # restore the clean background, saved at the beginning
        self.canvas.restore_region(self.background_1st)
        self.canvas.restore_region(self.background_2nd)

        #copyfile(power8_source_filename, power8_input_filename)
        #copyfile(x86_source_filename, x86_input_filename)
        #print(time.strftime("%s"))

        self.global_timer_index += 1
        self.local_timer_index += 1

        line_index = self.global_timer_index - 1
        less_number = EMPTY_NUMBER - self.local_timer_index
        needed_number = self.local_timer_index - 1

        # get the value of current index from file
        power8_current_value = self.read_from_file_by_index(
            power8_input_filename, line_index)
        x86_current_value = self.read_from_file_by_index(
            x86_input_filename, line_index)

        # normal return: accumulate the return value directly.
        # abnormal return: accumulate the previous one.
        if power8_current_value:
            self.power8_accumulate_value += power8_current_value
            self.power8_previous_value = power8_current_value
        else:
            # TODO: new add for error character
            power8_current_value = self.power8_previous_value
            self.power8_accumulate_value += self.power8_previous_value
        if x86_current_value:
            self.x86_accumulate_value += x86_current_value
            self.x86_previous_value = x86_current_value
        else:
            # TODO: new add for error character
            x86_current_value = self.x86_previous_value
            self.x86_accumulate_value += self.x86_previous_value
        #print("==> accumulate = {0} and previous = {1} and current ="
        #        "{2}".format(self.power8_accumulate_value,
        #            self.power8_previous_value,
        #            power8_current_value))

        # update the new data into 1st subplot
        self.power8_current_all_values = \
            self.power8_current_all_values[:needed_number] + \
            [power8_current_value] + [None] * less_number
        self.x86_current_all_values = \
            self.x86_current_all_values[:needed_number] + \
            [x86_current_value] + [None] * less_number
        self.power8_plot.set_ydata(self.power8_current_all_values)
        self.x86_plot.set_ydata(self.x86_current_all_values)

        # update the new data into 2nd subplot
        self.power8_ave_value = self.power8_accumulate_value / \
            self.global_timer_index
        self.x86_ave_value = self.x86_accumulate_value / \
            self.global_timer_index
        self.power8_barh.set_width(self.power8_ave_value)
        self.x86_barh.set_width(self.x86_ave_value)

        self.ax.draw_artist(self.power8_plot)
        self.ax.draw_artist(self.x86_plot)
        self.average.draw_artist(self.power8_barh)
        self.average.draw_artist(self.x86_barh)

        # clean the data on screen
        if self.local_timer_index == EMPTY_NUMBER:
            #print("local_timer_index is full")
            self.power8_current_all_values = []
            self.x86_current_all_values = []
            self.local_timer_index = 0

        self.canvas.blit(self.ax.bbox)
        self.canvas.blit(self.average.bbox)

    def read_from_file_by_index(self, filename, line_number):
        try:
            with open(filename, 'r') as file_object:
                all_content = file_object.read().split('\n')[:-1]
                file_length = len(all_content)
        except IOError, e:
            print("Error->[read_from_file_by_index]: CAN NOT find the"
                  "filename:[{0}]".format(filename))
        except Exception as ex:
            print("Error->[read_from_file_by_index]: {0}".format(str(ex)))
示例#40
0
class Plot(wx.Panel):
    """ Class to display a plot in wx 
        figure (mpl.figure.Figure): Figure that displays plots
        ax (mpl.axes.Axes): Axes inside figure
        canvas (FigureCanvasWxAgg): Canvas where the figure paints
        x_len (int): Maximum number of points to display at a time
        background (BufferRegion): Empty background to leverage blitting
        lines (list<mpl.lines.Line2D>): Each sensor of the same type has a line in this
            list. Used to update them later with different data
    """

    def __init__(self, parent, x_len, id=-1, dpi=100, **kwargs):
        """ Create empty plot """
        wx.Panel.__init__(self, parent, id=id, **kwargs)
        self.x_len = x_len
        self.figure = mpl.figure.Figure(dpi=dpi, figsize=(6.5, 6.5))
        self.ax = self.figure.add_axes([0.1, 0.1, 0.7, 0.85])
        self.ax.set_xlim(0, self.x_len)
        self.ax.autoscale(enable=True, axis="y", tight=True)
        self.canvas = FigureCanvas(self, -1, self.figure)
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.canvas, 0, wx.ALL)
        self.SetSizer(sizer)
        self.Fit()
        self.canvas.draw()
        self.background = self.canvas.copy_from_bbox(self.ax.bbox)
        self.lines = []

    def updateLines(self, plot_data):
        """ Redefine lines attribute as response to change in notebook """
        self.clear()
        self.lines = []
        for i in range(plot_data.data.shape[0]):
            self.lines.append(
                self.ax.plot(
                    range(self.x_len),
                    plot_data.data[i, :],
                    marker="o",
                    color="C" + str(i),
                    markerfacecolor="C" + str(i),
                )[0]
            )
        self.redoLegend(plot_data)

    def refresh(self, plot_data):
        """ Tell the Plot to actually implement the latest
            modifications

        Use canvas.blit() instead of canvas.draw_idle() to save time

        Documentation for this backend is kinda poor, but basically whenever
        something important needs to be done, it will only work if called from
        the FigureCanvas, not the Figure
        """
        self.canvas.restore_region(self.background)
        for line, data in zip(self.lines, plot_data.data):
            line.set_ydata(data)
            self.ax.add_line(line)
            self.ax.draw_artist(line)
        self.canvas.blit(self.ax.bbox)

    def clear(self):
        """ Function to clear the Axes of the Figure """
        self.ax.cla()
        self.canvas.draw_idle()

    def redoLegend(self, plot_data):
        """ Remove legend and create a new one

        Used when the number of sensors changes (from Ports dialog)
        """
        legend = self.ax.get_legend()
        if legend is not None:
            legend.remove()
        self.addCustomLegend(plot_data)

    def addCustomLegend(self, plot_data):
        """ Create legend for each variable

        Legend elements are defined for as many sensors as there are.
        The colors are given with the C0, C1, etc format, which allows to
        cycle. I suspect the current colormap goes up to 10 before repeating
        itself.
        The label is in the form of mL1, gR, etc.
        The legend will appear to the right of the Axes, outside the box,
        aligned with its top.
        """
        if plot_data.scaling:
            legend_elements_L = [
                Line2D(
                    [0],
                    [0],
                    marker="o",
                    color="C" + str(i),
                    label=plot_data.sensor_type + "L" + str(i + 1),
                    markerfacecolor="C" + str(i),
                )
                for i in range(plot_data.num_sensors)
            ]
            legend_elements_R = [
                Line2D(
                    [0],
                    [0],
                    marker="o",
                    color="C" + str(plot_data.num_sensors + i),
                    label=plot_data.sensor_type + "R" + str(i + 1),
                    markerfacecolor="C" + str(plot_data.num_sensors + i),
                )
                for i in range(plot_data.num_sensors)
            ]
            legend_elements = legend_elements_L + legend_elements_R
        else:
            legend_elements = [
                Line2D(
                    [0],
                    [0],
                    marker="o",
                    color="C0",
                    label=plot_data.sensor_type + "L",
                    markerfacecolor="C0",
                ),
                Line2D(
                    [0],
                    [0],
                    marker="o",
                    color="C1",
                    label=plot_data.sensor_type + "R",
                    markerfacecolor="C1",
                ),
            ]
        self.ax.legend(
            handles=legend_elements, loc="upper left", bbox_to_anchor=(1.04, 1)
        )
示例#41
0
class PanelGraph(wx.Panel):
    def __init__(self, panel, notify, settings, status, remoteControl):
        self.panel = panel
        self.notify = notify
        self.plot = None
        self.settings = settings
        self.status = status
        self.remoteControl = remoteControl
        self.spectrum = None
        self.isLimited = None
        self.limit = None
        self.extent = None
        self.annotate = None

        self.lockDraw = threading.Lock()

        self.toolTip = wx.ToolTip('')

        self.mouseSelect = None
        self.mouseZoom = None
        self.measureTable = None

        self.background = None

        self.selectStart = None
        self.selectEnd = None

        self.menuClearSelect = []

        self.measure = None
        self.show = None

        self.doDraw = False

        wx.Panel.__init__(self, panel)

        self.figure = matplotlib.figure.Figure(facecolor='white')
        self.canvas = FigureCanvas(self, -1, self.figure)
        self.canvas.SetToolTip(self.toolTip)

        self.measureTable = PanelMeasure(self, settings)

        self.toolbar = NavigationToolbar(self.canvas, self, settings,
                                         self.__hide_overlay)
        self.toolbar.Realize()

        vbox = wx.BoxSizer(wx.VERTICAL)
        vbox.Add(self.canvas, 1, wx.EXPAND)
        vbox.Add(self.measureTable, 0, wx.EXPAND)
        vbox.Add(self.toolbar, 0, wx.EXPAND)
        self.SetSizer(vbox)
        vbox.Fit(self)

        self.create_plot()

        self.canvas.mpl_connect('button_press_event', self.__on_press)
        self.canvas.mpl_connect('figure_enter_event', self.__on_enter)
        self.canvas.mpl_connect('figure_leave_event', self.__on_leave)
        self.canvas.mpl_connect('motion_notify_event', self.__on_motion)
        self.canvas.mpl_connect('draw_event', self.__on_draw)
        self.canvas.mpl_connect('idle_event', self.__on_idle)
        self.Bind(wx.EVT_SIZE, self.__on_size)

        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.__on_timer, self.timer)

    def __set_fonts(self):
        axes = self.plot.get_axes()
        if axes is not None:
            axes.xaxis.label.set_size('small')
            axes.yaxis.label.set_size('small')
            if self.settings.display == Display.SURFACE:
                axes.zaxis.label.set_size('small')
            axes.tick_params(axis='both', which='major', labelsize='small')
        axes = self.plot.get_axes_bar()
        if axes is not None:
            axes.tick_params(axis='both', which='major', labelsize='small')

    def __enable_menu(self, state):
        for menu in self.menuClearSelect:
            menu.Enable(state)

    def __on_press(self, event):
        if self.settings.clickTune and matplotlib.__version__ >= '1.2' and event.dblclick:
            frequency = int(event.xdata * 1e6)
            self.remoteControl.tune(frequency)

    def __on_enter(self, _event):
        self.toolTip.Enable(False)

    def __on_leave(self, _event):
        self.toolTip.Enable(True)

    def __on_motion(self, event):
        xpos = event.xdata
        ypos = event.ydata
        text = ""
        if xpos is None or ypos is None or self.spectrum is None:
            return

        if self.settings.display == Display.PLOT:
            timeStamp = max(self.spectrum)
            spectrum = self.spectrum[timeStamp]
        elif self.settings.display == Display.SPECT:
            timeStamp = num2epoch(ypos)
            if timeStamp in self.spectrum:
                spectrum = self.spectrum[timeStamp]
            else:
                nearest = min(self.spectrum.keys(),
                              key=lambda k: abs(k - timeStamp))
                spectrum = self.spectrum[nearest]
        elif self.settings.display == Display.SURFACE:
            spectrum = None
            coords = self.plot.get_axes().format_coord(event.xdata,
                                                       event.ydata)
            match = re.match('x=([-|0-9|\.]+).*y=([0-9|\:]+).*z=([-|0-9|\.]+)',
                             coords)
            if match is not None and match.lastindex == 3:
                freq = float(match.group(1))
                level = float(match.group(3))
                text = "{}, {}".format(*format_precision(self.settings,
                                                         freq, level))
        else:
            spectrum = None

        if spectrum is not None and len(spectrum) > 0:
            x = min(spectrum.keys(), key=lambda freq: abs(freq - xpos))
            if min(spectrum.keys(), key=float) <= xpos <= max(spectrum.keys(),
                                                              key=float):
                y = spectrum[x]
                text = "{}, {}".format(*format_precision(self.settings, x, y))
            else:
                text = format_precision(self.settings, xpos)

        self.status.set_info(text, level=None)

        axes = self.figure.get_axes()[0]
        markers = find_artists(self.figure, 'peak')
        markers.extend(find_artists(self.figure, 'peakThres'))
        hit = False
        for marker in markers:
            if isinstance(marker, Line2D):
                location = marker.get_path().vertices[0]
                markX, markY = axes.transData.transform(location)
                dist = abs(math.hypot(event.x - markX, event.y - markY))
                if dist <= 5:
                    if self.settings.display == Display.PLOT:
                        tip = "{}, {}".format(*format_precision(self.settings,
                                                                location[0],
                                                                location[1]))
                    else:
                        tip = "{}".format(format_precision(self.settings,
                                                           location[0]))
                    self.toolTip.SetTip(tip)
                    hit = True
                    break
        self.toolTip.Enable(hit)

    def __on_size(self, event):
        ppi = wx.ScreenDC().GetPPI()
        size = [float(v) for v in self.canvas.GetSize()]
        width = size[0] / ppi[0]
        height = size[1] / ppi[1]
        self.figure.set_figwidth(width)
        self.figure.set_figheight(height)
        self.figure.set_dpi(ppi[0])
        event.Skip()

    def __on_draw(self, _event):
        axes = self.plot.get_axes()
        if axes is not None:
            self.background = self.canvas.copy_from_bbox(axes.bbox)
            self.__draw_overlay()

    def __on_idle(self, _event):
        if self.doDraw and self.plot.get_plot_thread() is None:
            self.__hide_overlay()
            self.doDraw = False
            if os.name == 'nt':
                threading.Thread(target=self.__draw_canvas, name='Draw').start()
            else:
                with self.lockDraw:
                    self.canvas.draw()
                self.status.set_busy(False)

    def __on_timer(self, _event):
        self.timer.Stop()
        self.set_plot(None, None, None, None, self.annotate)

    def __draw_canvas(self):
        with self.lockDraw:
            try:
                self.canvas.draw()
            except wx.PyDeadObjectError:
                pass
        wx.CallAfter(self.status.set_busy, False)

    def __draw_overlay(self):
        if self.background is not None:
            self.canvas.restore_region(self.background)
            self.__draw_select()
            self.draw_measure()
            axes = self.plot.get_axes()
            if axes is None:
                self.canvas.draw()
            else:
                self.canvas.blit(axes.bbox)

    def __draw_select(self):
        if self.selectStart is not None and self.selectEnd is not None:
            self.mouseSelect.draw(self.selectStart, self.selectEnd)

    def __hide_overlay(self):
        if self.plot is not None:
            self.plot.hide_measure()
        self.__hide_select()

    def __hide_select(self):
        if self.mouseSelect is not None:
            self.mouseSelect.hide()

    def create_plot(self):
        if self.plot is not None:
            self.plot.close()

        self.toolbar.set_auto(True)

        if self.settings.display == Display.PLOT:
            self.plot = Plotter(self.notify, self.figure, self.settings)
        elif self.settings.display == Display.SPECT:
            self.plot = Spectrogram(self.notify, self.figure, self.settings)
        elif self.settings.display == Display.SURFACE:
            self.plot = Plotter3d(self.notify, self.figure, self.settings)
        elif self.settings.display == Display.STATUS:
            self.plot = PlotterStatus(self.notify, self.figure, self.settings)
        else:
            self.plot = PlotterTime(self.notify, self.figure, self.settings)

        self.__set_fonts()

        self.toolbar.set_plot(self.plot)
        self.toolbar.set_type(self.settings.display)
        self.measureTable.set_type(self.settings.display)

        self.set_plot_title()
        self.figure.subplots_adjust(top=0.85)
        self.redraw_plot()
        self.plot.scale_plot(True)
        self.mouseZoom = MouseZoom(self.toolbar, plot=self.plot,
                                   callbackHide=self.__hide_overlay)
        self.mouseSelect = MouseSelect(self.plot, self.on_select,
                                       self.on_selected)
        self.measureTable.show(self.settings.showMeasure)
        self.panel.SetFocus()

    def on_select(self):
        self.hide_measure()

    def on_selected(self, start, end):
        self.__enable_menu(True)
        self.selectStart = start
        self.selectEnd = end
        self.measureTable.set_selected(self.spectrum, start, end)

    def add_menu_clear_select(self, menu):
        self.menuClearSelect.append(menu)
        menu.Enable(False)

    def draw(self):
        self.doDraw = True

    def show_measure_table(self, show):
        self.measureTable.show(show)
        self.Layout()

    def set_plot(self, spectrum, isLimited, limit, extent, annotate=False):
        if spectrum is not None and extent is not None:
            if isLimited is not None and limit is not None:
                self.spectrum = copy.copy(spectrum)
                self.extent = extent
                self.annotate = annotate
                self.isLimited = isLimited
                self.limit = limit

        if self.plot.get_plot_thread() is None:
            self.timer.Stop()
            self.measureTable.set_selected(self.spectrum, self.selectStart,
                                           self.selectEnd)

            if isLimited:
                self.spectrum = reduce_points(spectrum, limit)

            self.status.set_busy(True)
            self.plot.set_plot(self.spectrum, self.extent, annotate)

        else:
            self.timer.Start(200, oneShot=True)

    def set_plot_title(self):
        if len(self.settings.devicesRtl) > 0:
            gain = self.settings.devicesRtl[self.settings.indexRtl].gain
        else:
            gain = 0
        self.plot.set_title("Frequency Spectrogram\n{} - {} MHz,"
                            " gain = {}dB".format(self.settings.start,
                                                  self.settings.stop, gain))

    def redraw_plot(self):
        if self.spectrum is not None:
            self.set_plot(self.spectrum,
                          self.settings.pointsLimit,
                          self.settings.pointsMax,
                          self.extent, self.settings.annotate)

    def set_grid(self, on):
        self.plot.set_grid(on)

    def hide_measure(self):
        if self.plot is not None:
            self.plot.hide_measure()

    def draw_measure(self):
        if self.measure is not None and self.measure.is_valid():
            self.plot.draw_measure(self.measure, self.show)

    def update_measure(self, measure=None, show=None):
        if not measure and not show:
            self.measureTable.update_measure()
        else:
            self.measure = measure
            self.show = show
            with self.lockDraw:
                self.__draw_overlay()

    def get_figure(self):
        return self.figure

    def get_axes(self):
        return self.plot.get_axes()

    def get_canvas(self):
        return self.canvas

    def get_toolbar(self):
        return self.toolbar

    def scale_plot(self, force=False):
        self.plot.scale_plot(force)

    def clear_plots(self):
        self.plot.clear_plots()
        self.spectrum = None
        self.doDraw = True

    def clear_selection(self):
        self.measure = None
        self.measureTable.clear_measurement()
        self.selectStart = None
        self.selectEnd = None
        self.mouseSelect.clear()
        self.__enable_menu(False)

    def close(self):
        close_modeless()
示例#42
0
class AnalyzeORBResult (wx.Panel) :

    def __init__ (self, parent):
        wx.Panel.__init__(self, parent=parent)
        
        splitter = wx.SplitterWindow (self)
        
        # XXX: we may need to place the canvas in its own Panel
        self.figure = Figure()
        self.canvas = FigureCanvas(splitter, wx.ID_ANY, self.figure)
        self.vehiclePointer = None
        self.imageTopic = None

        rightPanel = wx.Panel(splitter)
        cPanel = wx.BoxSizer (wx.VERTICAL)
        rightPanel.SetSizer(cPanel)

        self.orbResultChooser = FilePrompt(rightPanel, 'ORB-SLAM Result Bag', self.onClickOrbChoose)
        cPanel.Add(self.orbResultChooser, flag=wx.EXPAND)
        
        self.groundTruthChooser = FilePrompt(rightPanel, 'GroundTruth', self.onClickGtChoose)
        cPanel.Add(self.groundTruthChooser, flag=wx.EXPAND)

        timePosBox = wx.BoxSizer(wx.HORIZONTAL)        
        timePosBox.Add(wx.StaticText(rightPanel, label='Time Position'), flag=wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL, proportion=0)
        self.timeDisplay = wx.TextCtrl(rightPanel, style=wx.TE_READONLY)
        timePosBox.Add(self.timeDisplay, flag=wx.EXPAND|wx.ALIGN_CENTER, proportion=1)
        cPanel.Add(timePosBox, flag=wx.EXPAND)

        orbStatusBox = wx.BoxSizer(wx.HORIZONTAL)        
        orbStatusBox.Add(wx.StaticText(rightPanel, label="ORB Status"), flag=wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL, proportion=0)
        self.orbStatus = wx.StaticText(rightPanel, label="Init")
        orbStatusBox.Add(self.orbStatus, flag=wx.ALIGN_CENTER|wx.EXPAND, proportion=1)
        cPanel.Add(orbStatusBox, flag=wx.EXPAND)

        bagGroup = wx.StaticBoxSizer(wx.StaticBox(rightPanel, label='Image Source Bag'), wx.VERTICAL)
        askBag = FilePrompt(rightPanel, "Image Bag File", self.onBagChange)
        bagGroup.Add(askBag, flag=wx.EXPAND)
        self.imageTopicChooser = wx.ComboBox(rightPanel)
        bagGroup.Add(self.imageTopicChooser, flag=wx.EXPAND)
        self.imageTopicChooser.Bind(wx.EVT_COMBOBOX, self.onImageTopicChange)
        self.bagImageView = BagImagePreview (rightPanel)
        bagGroup.Add (self.bagImageView, flag=wx.EXPAND)
        cPanel.Add(bagGroup, flag=wx.EXPAND|wx.ALIGN_CENTER_HORIZONTAL)

        splitter.SplitVertically(self.canvas, rightPanel)
        splitter.SetMinimumPaneSize(30)

        mainLayout = wx.BoxSizer (wx.VERTICAL)
        self.SetSizer(mainLayout)  
        mainLayout.Add(splitter, proportion=1, flag=wx.EXPAND|wx.ALIGN_TOP)  
        
        self.timeChooser = wx.Slider(self)
        self.timeChooser.Bind(wx.EVT_SCROLL, self.onChangeTimePosition)
        mainLayout.Add(self.timeChooser, flag=wx.EXPAND|wx.ALIGN_BOTTOM)
        self.Fit()
        
    
    def onClickOrbChoose (self, bagPath):
        self.loadData()
    
    def onClickGtChoose (self, gtPath):
        self.loadData()
        
    def onChangeTimePosition (self, e):
        if self.currentORBTimestamp == None:
            return
#        print (self.timeChooser.GetValue())
        self.currentORBTimestamp = int(self.timeChooser.GetValue())
        self.redrawPosition()
        
    def onBagChange (self, bagPath):
        self.bagImageView.setBagPath (bagPath)
        self.imageTopicChooser.AppendItems(self.bagImageView.getAllTopics())
    
    def onImageTopicChange (self, e):
        self.imageTopic = (self.imageTopicChooser.GetValue())
        self.bagImageView.setTopic (self.imageTopic)
        self.redrawPosition()
        
        
    def loadData (self):
        if (self.orbResultChooser.GetValue()=='' or self.groundTruthChooser.GetValue()==''):
            print ("Select filenames first")
            return None
        print ("Wait...")
        
        # Load ground truth and plot it
        self.ax = self.figure.add_subplot(111)
        self.ax.set_autoscale_on(True)
        self.ax.grid(True)
        self.groundTruth = PoseTable.loadFromBagFile(self.groundTruthChooser.GetValue(), 'world', 'ndt_frame')
        gtTbl = self.groundTruth.toArray()
        self.groundTruthPlot, = self.ax.plot(gtTbl[:,0], gtTbl[:,1])
#        self.groundTruthPlot, = self.ax.plot([0,1,2], [4,5,6])
        
        self.orbResult = PoseTable.loadFromBagFile(self.orbResultChooser.GetValue(), '/ORB_SLAM/World', '/ORB_SLAM/ExtCamera')
        orbTbl = self.orbResult.toArray()
        self.orbResultPlot, = self.ax.plot(orbTbl[:,0], orbTbl[:,1])
        
        self.canvas.draw()
        self.background = self.canvas.copy_from_bbox(self.ax.bbox)
#        self.helpText.Show(True)
        
        self.timeChooser.SetRange(self.orbResult[0].timestamp, self.orbResult.last().timestamp)
        self.currentORBTimestamp = self.orbResult[0].timestamp
        self.redrawPosition()
        
    @staticmethod
    def readMessage (bag, topic, timestamp):
        tm = rospy.Time.from_sec(timestamp)
        for topic, msg, time in bag.read_messages(topics=topic, start_time=tm):
            return msg
        
    def redrawPosition (self):
        if self.currentORBTimestamp == None:
            return
        dp = datetime.datetime.fromtimestamp(self.currentORBTimestamp)
        self.timeDisplay.SetValue(str(dp))
        
        orbPose = self.orbResult.findNearestInTime (self.currentORBTimestamp, 0.1)
        
        self.canvas.restore_region(self.background)
        if (orbPose!=None):
            if (self.vehiclePointer==None):
                self.vehiclePointer = self.ax.scatter(orbPose.x, orbPose.y, s=100, c=[1,0,0,0.5], linewidths=0)
            else:
                self.vehiclePointer.set_offsets([orbPose.x, orbPose.y])
            self.orbStatus.SetLabel("OK")
        else:
            self.orbStatus.SetLabel("Lost")
        self.canvas.draw()
        self.canvas.blit(self.ax.bbox)
        
        if self.imageTopic != None:
            self.bagImageView.showTime (self.currentORBTimestamp)
示例#43
0
class CirclePanel(wx.Panel):
    def __init__(self, parent, **kwargs):
        wx.Panel.__init__(self, parent, **kwargs)
        self.SetBackgroundColour(wx.Colour(255, 255, 255))

        #set up widgets
        self.figure = Figure((5, 5), 80)
        self.figure.set_facecolor("#FFFFFF")
        self.canvas = FigureCanvas(self, -1, self.figure)
        self.canvas.SetBackgroundColour(wx.Colour(255,255,255))
        self.subplot = self.figure.add_subplot(111)
        self.subplot.set_ylim([-5, 5])
        self.subplot.set_xlim([-5, 5])
        self.toolbar = NavigationToolbar(self.canvas)
        self.toolbar.SetBackgroundColour(wx.Colour(255, 255, 255))

        #set up boxes
        self.box = wx.BoxSizer(wx.VERTICAL)
        self.box.Add(self.canvas, 1, wx.LEFT | wx.GROW) #the sizer automatically resizes the canvas
        self.box.Add(self.toolbar, 0, wx.CENTER)
        self.SetSizer(self.box)

        #set up the point dragging feature;
        #user can drag center and move circle
        self.canvas.mpl_connect("pick_event", self.OnPick)
        self.canvas.mpl_connect("motion_notify_event", self.OnMotion)
        self.canvas.mpl_connect("button_release_event", self.OnMouseUp)
        self.dragging = False

        #circle parameters
        self.h = 0.0
        self.k = 0.0
        self.r = 1.0

        #plot objects
        self.background = None
        self.circle = None
        self.points = None

        self.DrawFigure()

    #user picked a point/line in the plot
    def OnPick(self, event):
        #the user picked more than one point because
        #there is a point on top of another;
        #just pick the first point
        if not isinstance(event.ind, type(1)):
            event.ind = event.ind[0]

        #if the user picked the center point, enable translation
        #the center point is the first point of the point list (ind=0)
        if event.ind == 0:
            self.dragging = 1
            self.SaveBackground()
        #if the user picked the diameter point, enable dilation
        #the diameter point is the second point of the point list (ind=1)
        elif event.ind == 1:
            self.dragging = 2
            self.SaveBackground()

    #user moved the mouse in the plot
    def OnMotion(self, event):
        #make sure that the mouse is IN the plot!
        if not event.xdata == None:
            #if user is dragging the center point,
            #move the center point to mouse coordinates
            if self.dragging == 1:
                evt = FigureTransformEvent(typeEVT_FIGURE_TRANSLATE, self.GetId())
                evt.oldH = self.h
                evt.oldK = self.k
                evt.oldR = self.r
                evt.deltaH = self.h - event.xdata
                evt.deltaK = self.k - event.ydata
                self.h = event.xdata
                self.k = event.ydata
                evt.newH = self.h
                evt.newK = self.k
                self.UpdateFigure()
                self.GetEventHandler().ProcessEvent(evt)
            #if user is dragging the diameter point,
            #change the radius to the distance between the diameter and center point
            if self.dragging == 2:
                evt = FigureTransformEvent(typeEVT_FIGURE_DILATE, self.GetId())
                #make sure r is greater than 0
                if event.xdata - self.h > 0.0:
                    evt.oldH = self.h
                    evt.oldK = self.k
                    evt.oldR = self.r
                    self.r = event.xdata - self.h
                    evt.deltaR = evt.oldR - self.r
                    evt.newR = self.r
                    self.UpdateFigure()
                    self.GetEventHandler().ProcessEvent(evt)

    #user released button
    def OnMouseUp(self, event):
        #if the user is dragging the center point
        #and releases the button, stop dragging
        self.dragging = 0
        self.circle.set_animated(False)
        self.points.set_animated(False)

    #update the title, which shows the equation of the circle
    def UpdateTitle(self):
        titleText = "$(x{h})^2 + (y{k})^2 = {r}^2$"
        titleH, titleK, titleR = "-0.0", "-0.0", round(self.r, 2)

        #format signs correctly
        if self.h < 0.0:
            titleH = "+{val}".format(val=abs(round(self.h, 2)))
        elif self.h > 0.0:
            titleH = "-{val}".format(val=abs(round(self.h, 2)))
        if self.k < 0.0:
            titleK = "+{val}".format(val=abs(round(self.k, 2)))
        elif self.k > 0.0:
            titleK = "-{val}".format(val=abs(round(self.k, 2)))

        #show the students that they can omit h or k in the equation if it equals 0.0
        if self.h == 0.0 and not self.k == 0.0:
            titleText = titleText + " OR $x^2 + (y{k})^2 = {r}^2$"
        elif not self.h == 0.0 and self.k == 0.0:
            titleText = titleText + " OR $(x{h})^2 + y^2 = {r}^2$"
        elif self.h == 0.0 and self.k == 0.0:
            titleText = titleText + " OR $x^2 + y^2 = {r}^2$"

        self.subplot.set_title(titleText.format(h=titleH, k=titleK, r=titleR),
            fontproperties=mpl.font_manager.FontProperties(size="x-large"))

    #draw/redraw the canvas
    def DrawFigure(self):
        self.subplot.clear()

        #set the "window" of the plot
        self.subplot.set_ylim([-5, 5])
        self.subplot.set_xlim([-5, 5])

        #draw grid and axes lines
        self.subplot.grid(True)
        self.subplot.axhspan(0, 0)
        self.subplot.axvspan(0, 0)

        self.UpdateTitle()

        #draw the circles
        circleColor = (0, 0, 1, 1)
        #must multiply r by 2 b/c Arc takes the length (diameter) of the axes, not the radius

        #circle1 is the reference circle (red)
        """
        circle1 = patches.Arc((0, 0), 2, 2, edgecolor="#FF0000", alpha=0.8)
        self.subplot.plot([0.0, 1.0], [0.0, 0.0], marker="o", color="#FF0000", mec="#FF0000", mfc="#FF0000")
        self.subplot.add_patch(circle1)
        """

        #circle2 is the user-manipulated circle (blue)
        self.circle = patches.Arc((self.h, self.k), self.r*2, self.r*2, edgecolor=circleColor, alpha=0.8)
        self.points = self.subplot.plot([self.h, self.h+self.r], [self.k, self.k], marker="o", picker=5, color=circleColor, mec=circleColor, mfc=circleColor)
        #get the first (and only) line, not the list
        self.points = self.points[0]
        self.subplot.add_patch(self.circle)

        self.canvas.draw()

    def UpdateFigure(self):
        #update data
        self.circle.center = (self.h, self.k)
        self.circle.width = 2*self.r
        self.circle.height = 2*self.r
        self.points.set_xdata([self.h, self.h+self.r])
        self.points.set_ydata([self.k, self.k])
        self.UpdateTitle()

        #draw
        self.canvas.restore_region(self.background)
        self.subplot.draw_artist(self.subplot.title)
        self.subplot.draw_artist(self.circle)
        self.subplot.draw_artist(self.points)
        self.canvas.blit(self.figure.bbox)

    def SaveBackground(self):
        self.circle.set_animated(True)
        self.points.set_animated(True)

        #clear plot
        self.subplot.set_title(" ")
        self.canvas.draw()

        #save figure
        self.background = self.canvas.copy_from_bbox(self.figure.bbox)

        self.UpdateTitle()

        #blit figures back onto the plot
        self.subplot.draw_artist(self.circle)
        self.subplot.draw_artist(self.points)
        self.subplot.draw_artist(self.subplot.title)
        self.canvas.blit(self.figure.bbox)

    def SetParameters(self, h, k, r):
        self.h = h
        self.k = k
        self.r = r
示例#44
0
class _MonitorPlot(wx.Frame):
    """Class to provide live updated plotting to monitor the
    convergence of FlowVB
    """

    def __init__(self, data, scale=1):
        """Setup plotting environment
        """

        self.scale = scale
        self.data = data

        # Setup plotting window
        wx.Frame.__init__(self, None, wx.ID_ANY,
                          title="FlowVB Progress Monitor", size=(800, 600))
        self.fig = Figure((8, 6), 100)
        self.canvas = FigureCanvas(self, wx.ID_ANY, self.fig)
        self.ax = self.fig.add_subplot(111)

        # Set axis limits
        x_lims = [data[:, 0].min(), data[:, 0].max()]
        y_lims = [data[:, 1].min(), data[:, 1].max()]

        self.ax.set_xlim(x_lims)
        self.ax.set_ylim(y_lims)
        self.ax.set_autoscale_on(False)

        # Draw the data
        self.l_data = self.ax.plot(self.data[:, 0], self.data[:, 1],
                                   color='blue', linestyle='', marker='o')

        # Draw to screen
        self.canvas.draw()

        # Save background
        self.bg = self.canvas.copy_from_bbox(self.ax.bbox)

    def update_plot(self, pos, cov):
        """Update the plot
        """

        # Restore empty plot (but doesn't seem to do anything)
        self.canvas.restore_region(self.bg)

        # Remove previous elements from plot
        self.ax.lines = [self.ax.lines[0]]  # Delete everything except
                                            # scatterplot
        self.ax.patches = []

        K = pos.shape[0]
        for k in range(K):
            # Draw centers
            l_center, = self.ax.plot(pos[k, 0], pos[k, 1],
                                     color='red', marker='+')

            # Compute and draw error ellipses
            U, s, Vh = np.linalg.svd(cov[k, :, :])
            orient = math.atan2(U[1, 0], U[0, 0]) * 180 / pi
            ellipsePlot = Ellipse(xy=pos[k, :], width=2.0 * math.sqrt(s[0]),
                                  height=2.0 * math.sqrt(s[1]),
                                  angle=orient, facecolor='none',
                                  edgecolor='red', zorder=100)

            self.ax.add_patch(ellipsePlot)

        # Draw to screen
        self.canvas.draw()
        self.canvas.blit(self.ax.bbox)

    def end_of_iteration(self):
        self.button = wx.Button(self.canvas, label="Close Window",
                                pos=(680, 10))
        self.Bind(wx.EVT_BUTTON, self.OnButtonClick, self.button)
        at = AnchoredText("Iteration finished.",
                          prop=dict(size=8), frameon=True,
                          loc=2)
        at.patch.set_boxstyle("round,pad=0.,rounding_size=0.2")
        self.ax.add_artist(at)
        self.canvas.draw()

    def OnButtonClick(self, event):
        self.Close(True)
示例#45
0
class LeftGraphTop(wx.Panel):
    def __init__(self, parent, statusbar):
        wx.Panel.__init__(self, parent)
        self.statusbar = statusbar
        """
        An polygon editor.
        Key-bindings
          't' toggle vertex markers on and off.  When vertex markers are on,
              you can move them, delete them
          'd' delete the vertex under point
          'i' insert a vertex at point.  You must be within epsilon of the
              line connecting two existing vertices
        """
        self.fig = Figure((4.0, 3.0))
        self.canvas = FigCanvas(self, -1, self.fig)
        self.ax = self.fig.add_subplot(111)
        self.ax.set_ylabel("Strain", fontdict=font)
        self.ax.set_xlabel("Depth ($\AA$)", fontdict=font)
        self.toolbar = NavigationToolbar(self.canvas)
        self.toolbar.Hide()
        self.fig.patch.set_facecolor(colorBackgroundGraph)

        self._ind = None  # the active vert
        self.poly = []
        self.line = []
        self.showverts = True
        self.epsilon = 5   # max pixel distance to count as a vertex hit
        self.new_coord = {'indice': 0, 'x': 0, 'y': 0}
        self.modelpv = False

        xs = [-1]
        ys = [-1]
        poly = Polygon(list(zip(xs, ys)),
                       fill=False, closed=False, animated=True)
        self.ax.set_xlim([0, 1])
        self.ax.set_ylim([0, 1])
        self.c_strain = ""
        self.l_strain = ""

        self.canvas.mpl_connect('draw_event',
                                self.draw_callback)
        self.canvas.mpl_connect('button_press_event',
                                self.button_press_callback)
        self.canvas.mpl_connect('button_release_event',
                                self.button_release_callback)
        self.canvas.mpl_connect('scroll_event',
                                self.scroll_callback)
        self.canvas.mpl_connect('motion_notify_event',
                                self.motion_notify_callback)
        self.canvas.mpl_connect('motion_notify_event',
                                self.on_update_coordinate)

        mastersizer = wx.BoxSizer(wx.VERTICAL)
        mastersizer.Add(self.canvas, 1, wx.ALL|wx.EXPAND)
        mastersizer.Add(self.toolbar, 0, wx.ALL)
        pub.subscribe(self.OnDrawGraph, pubsub_Draw_Strain)
        pub.subscribe(self.scale_manual, pubsub_Update_Scale_Strain)
        pub.subscribe(self.on_color, pubsub_Graph_change_color_style)

        self.on_color()
        self.draw_c(poly, xs, ys)

        self.SetSizer(mastersizer)
        self.Fit()

    def on_color(self):
        a = P4Rm()
        self.c_strain = a.DefaultDict['c_strain']
        self.l_strain = a.DefaultDict['l_strain']
        self.c_bkg = a.DefaultDict['c_graph_background']

    def OnDrawGraph(self, b=None):
        a = P4Rm()
        self.modelpv = a.modelPv
        self.ax.clear()
        if a.AllDataDict['damaged_depth'] == 0:
            self.ax.text(0.5, 0.5, "No Damage", size=30, rotation=0.,
                         ha="center", va="center",
                         bbox=dict(boxstyle="round",
                                   ec='red',
                                   fc=self.c_strain,))
            xs = [-1]
            ys = [-1]
            x_sp = [-1]
            y_sp = [-1]
            self.ax.set_xticklabels([])
            self.ax.set_yticklabels([])
            self.ax.set_xlim([0, 1])
            self.ax.set_ylim([0, 1])
        else:
            if b != 2:
                x_sp = a.ParamDict['x_sp']
                y_sp = a.ParamDict['strain_shifted']
                xs = deepcopy(a.ParamDict['depth'])
                ys = deepcopy(a.ParamDict['strain_i']*100)
                P4Rm.DragDrop_Strain_x = x_sp
                P4Rm.DragDrop_Strain_y = y_sp
                ymin = min(ys) - min(ys)*10/100
                ymax = max(ys) + max(ys)*10/100
                self.ax.set_ylim([ymin, ymax])
                if a.ParamDict['x_sp'] is not "":
                    self.ax.set_xlim([a.ParamDict['depth'][-1],
                                      a.ParamDict['depth'][0]])
            elif b == 2:
                x_sp = [-1]
                y_sp = [-1]
                xs = [-1]
                ys = [-1]
                self.ax.set_xlim([0, 1])
                self.ax.set_ylim([-1, 1])
        poly = Polygon(list(zip(x_sp, y_sp)), lw=0, ls='dashdot',
                       color=self.c_strain, fill=False, closed=False,
                       animated=True)
        if self.modelpv is True:
            P4Rm.ParamDict['sp_pv_backup'] = a.ParamDict['sp']
        self.draw_c(poly, xs, ys)

    def draw_c(self, data, x, y):
        self.ax.plot(x[1:], y[1:], color=self.c_strain, lw=2.,
                     ls=self.l_strain)
        self.ax.set_ylabel("Strain", fontdict=font)
        self.ax.set_xticklabels([])
        self.ax.set_axis_bgcolor(self.c_bkg)
        self.poly = data
        xs, ys = zip(*self.poly.xy)
        self.line = Line2D(xs, ys, lw=0, ls='-.', color=self.c_strain,
                           marker='.', ms=32, markerfacecolor=self.c_strain,
                           markeredgecolor='k', mew=1.0)
        self.ax.add_line(self.line)
        self.ax.add_patch(self.poly)
        self.canvas.draw()
        self.Update()

    def draw_callback(self, event):
        self.background = self.canvas.copy_from_bbox(self.ax.bbox)
        self.ax.draw_artist(self.poly)
        self.ax.draw_artist(self.line)
        self.canvas.blit(self.ax.bbox)

    def get_ind_under_point(self, event):
        'get the index of the vertex under point if within epsilon tolerance'

        # display coords
        xy = np.asarray(self.poly.xy)
        xyt = self.poly.get_transform().transform(xy)
        xt, yt = xyt[:, 0], xyt[:, 1]
        d = np.sqrt((xt-event.x)**2 + (yt-event.y)**2)
        indseq = np.nonzero(np.equal(d, np.amin(d)))[0]
        ind = indseq[0]
        if d[ind] >= self.epsilon:
            ind = None
        return ind

    def button_press_callback(self, event):
        'whenever a mouse button is pressed'
        a = P4Rm()
        val = a.xrd_graph_loaded
        if self.canvas.HasCapture():
            self.canvas.ReleaseMouse()
            if not self.showverts:
                return
            if event.inaxes is None:
                return
            if event.button != 1:
                return
            if val == 1:
                self._ind = self.get_ind_under_point(event)
                self.new_coord['indice'] = self._ind

    def button_release_callback(self, event):
        'whenever a mouse button is released'
        a = P4Rm()
        val = a.xrd_graph_loaded
        if self.canvas.HasCapture():
            self.canvas.ReleaseMouse()
        else:
            if not self.showverts:
                return
            if event.button != 1:
                return
            if self.new_coord['indice'] is not None and val == 1:
                temp_1 = self.new_coord['y']
                temp_2 = self.new_coord['x']
                P4Rm.DragDrop_Strain_y[self.new_coord['indice']] = temp_1
                P4Rm.DragDrop_Strain_x[self.new_coord['indice']] = temp_2
                if a.AllDataDict['model'] == 0:
                    temp = self.new_coord['y']
                    P4Rm.DragDrop_Strain_y[self.new_coord['indice']] = temp
                    temp = [strain*scale/100 for strain,
                            scale in zip(a.DragDrop_Strain_y,
                                         a.ParamDict['scale_strain'])]
                    temp = [float(format(value, '.8f')) for value in temp]
                    temp2 = np.concatenate([temp, [a.ParamDict['stain_out']]])
                    P4Rm.ParamDict['sp'] = deepcopy(temp2)
                    P4Rm.ParamDictbackup['sp'] = deepcopy(temp2)
                elif a.AllDataDict['model'] == 1:
                    temp = self.new_coord['y']
                    P4Rm.DragDrop_Strain_y[self.new_coord['indice']] = temp
                    temp = [strain*scale/100 for strain,
                            scale in zip(a.DragDrop_Strain_y,
                                         a.ParamDict['scale_strain'])]
                    temp = [float(format(value, '.8f')) for value in temp]
                    temp2 = np.concatenate([[a.ParamDict['stain_out'][0]],
                                            temp,
                                            [a.ParamDict['stain_out'][1]]])
                    P4Rm.ParamDict['sp'] = deepcopy(temp2)
                    P4Rm.ParamDictbackup['sp'] = deepcopy(temp2)
                elif a.AllDataDict['model'] == 2:
                    t_temp = a.ParamDict['depth'] + a.ParamDict['z']
                    t = t_temp[0]
                    sp_temp = range(7)
                    sp_temp[0] = a.DragDrop_Strain_y[0]
                    sp_temp[1] = 1 - a.DragDrop_Strain_x[0]/t
                    sp_temp[2] = 2*(-1 + a.ParamDict['sp'][1] +
                                    a.DragDrop_Strain_x[1]/t)
                    sp_temp[3] = 2*(1 - a.ParamDict['sp'][1] -
                                    1*a.DragDrop_Strain_x[2]/t)
                    sp_temp[4] = a.ParamDict['sp'][4]
                    sp_temp[5] = a.ParamDict['sp'][5]
                    sp_temp[6] = a.DragDrop_Strain_y[3]
                    P4Rm.ParamDict['sp'] = deepcopy(sp_temp)
                    P4Rm.ParamDictbackup['sp'] = deepcopy(sp_temp)
                    P4Rm.ParamDict['sp_pv'] = deepcopy(sp_temp)
                pub.sendMessage(pubsub_Update_Fit_Live)
            self._ind = None

    def scroll_callback(self, event):
        if not event.inaxes:
            return
        a = P4Rm()
        if event.key == 'u' and event.button == 'up':
            temp = a.ParamDict['strain_multiplication'] + 0.01
            P4Rm.ParamDict['strain_multiplication'] = temp
        elif event.key == 'u' and event.button == 'down':
            temp = a.ParamDict['strain_multiplication'] - 0.01
            P4Rm.ParamDict['strain_multiplication'] = temp
        temp_1 = a.ParamDictbackup['sp']
        temp_2 = a.ParamDict['strain_multiplication']
        P4Rm.ParamDict['sp'] = multiply(temp_1, temp_2)
        pub.sendMessage(pubsub_Re_Read_field_paramters_panel, event=event)

    def scale_manual(self, event, val=None):
        a = P4Rm()
        if val is not None:
            P4Rm.ParamDict['strain_multiplication'] = val
        temp_1 = a.ParamDict['sp']
        temp_2 = a.ParamDict['strain_multiplication']
        P4Rm.ParamDict['sp'] = multiply(temp_1, temp_2)
        pub.sendMessage(pubsub_Re_Read_field_paramters_panel, event=event)

    def motion_notify_callback(self, event):
        'on mouse movement'
        a = P4Rm()
        if a.AllDataDict['damaged_depth'] == 0:
            return
        if not self.showverts:
            return
        if self._ind is None:
            return
        if event.inaxes is None:
            return
        if event.button != 1:
            return
        if self.modelpv is True:
            if self._ind == 0:
                y = event.ydata
                x = event.xdata
            elif self._ind == 1 or self._ind == 2:
                y = a.DragDrop_Strain_y[self.new_coord['indice']]
                x = event.xdata
            else:
                x = a.DragDrop_Strain_x[self.new_coord['indice']]
                y = event.ydata
        else:
            y = event.ydata
            x = a.DragDrop_Strain_x[self.new_coord['indice']]
        self.new_coord['x'] = x
        self.new_coord['y'] = y

        self.poly.xy[self._ind] = x, y
        self.line.set_data(zip(*self.poly.xy))

        self.canvas.restore_region(self.background)
        self.ax.draw_artist(self.poly)
        self.ax.draw_artist(self.line)
        self.canvas.blit(self.ax.bbox)

    def on_update_coordinate(self, event):
        if event.inaxes is None:
            self.statusbar.SetStatusText(u"", 1)
            self.statusbar.SetStatusText(u"", 2)
        else:
            a = P4Rm()
            if not a.AllDataDict['damaged_depth'] == 0:
                x, y = event.xdata, event.ydata
                xfloat = round(float(x), 2)
                yfloat = round(float(y), 2)
                self.statusbar.SetStatusText(u"x = " + str(xfloat), 1)
                self.statusbar.SetStatusText(u"y = " + str(yfloat), 2)

                xy = np.asarray(self.poly.xy)
                xyt = self.poly.get_transform().transform(xy)
                xt, yt = xyt[:, 0], xyt[:, 1]
                d = np.sqrt((xt-event.x)**2 + (yt-event.y)**2)
                indseq = np.nonzero(np.equal(d, np.amin(d)))[0]
                ind = indseq[0]

                if d[ind] >= self.epsilon:
                    self.canvas.SetCursor(Cursor(wx.CURSOR_ARROW))
                elif d[ind] <= self.epsilon:
                    self.canvas.SetCursor(Cursor(wx.CURSOR_HAND))
示例#46
0
class AnalyzeORBResult(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent=parent)

        splitter = wx.SplitterWindow(self)

        # XXX: we may need to place the canvas in its own Panel
        self.figure = Figure()
        self.canvas = FigureCanvas(splitter, wx.ID_ANY, self.figure)
        self.vehiclePointer = None
        self.imageTopic = None

        rightPanel = wx.Panel(splitter)
        cPanel = wx.BoxSizer(wx.VERTICAL)
        rightPanel.SetSizer(cPanel)

        self.orbResultChooser = FilePrompt(rightPanel, 'ORB-SLAM Result Bag',
                                           self.onClickOrbChoose)
        cPanel.Add(self.orbResultChooser, flag=wx.EXPAND)

        self.groundTruthChooser = FilePrompt(rightPanel, 'GroundTruth',
                                             self.onClickGtChoose)
        cPanel.Add(self.groundTruthChooser, flag=wx.EXPAND)

        timePosBox = wx.BoxSizer(wx.HORIZONTAL)
        timePosBox.Add(wx.StaticText(rightPanel, label='Time Position'),
                       flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL,
                       proportion=0)
        self.timeDisplay = wx.TextCtrl(rightPanel, style=wx.TE_READONLY)
        timePosBox.Add(self.timeDisplay,
                       flag=wx.EXPAND | wx.ALIGN_CENTER,
                       proportion=1)
        cPanel.Add(timePosBox, flag=wx.EXPAND)

        orbStatusBox = wx.BoxSizer(wx.HORIZONTAL)
        orbStatusBox.Add(wx.StaticText(rightPanel, label="ORB Status"),
                         flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL,
                         proportion=0)
        self.orbStatus = wx.StaticText(rightPanel, label="Init")
        orbStatusBox.Add(self.orbStatus,
                         flag=wx.ALIGN_CENTER | wx.EXPAND,
                         proportion=1)
        cPanel.Add(orbStatusBox, flag=wx.EXPAND)

        bagGroup = wx.StaticBoxSizer(
            wx.StaticBox(rightPanel, label='Image Source Bag'), wx.VERTICAL)
        askBag = FilePrompt(rightPanel, "Image Bag File", self.onBagChange)
        bagGroup.Add(askBag, flag=wx.EXPAND)
        self.imageTopicChooser = wx.ComboBox(rightPanel)
        bagGroup.Add(self.imageTopicChooser, flag=wx.EXPAND)
        self.imageTopicChooser.Bind(wx.EVT_COMBOBOX, self.onImageTopicChange)
        self.bagImageView = BagImagePreview(rightPanel)
        bagGroup.Add(self.bagImageView, flag=wx.EXPAND)
        cPanel.Add(bagGroup, flag=wx.EXPAND | wx.ALIGN_CENTER_HORIZONTAL)

        splitter.SplitVertically(self.canvas, rightPanel)
        splitter.SetMinimumPaneSize(30)

        mainLayout = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(mainLayout)
        mainLayout.Add(splitter, proportion=1, flag=wx.EXPAND | wx.ALIGN_TOP)

        self.timeChooser = wx.Slider(self)
        self.timeChooser.Bind(wx.EVT_SCROLL, self.onChangeTimePosition)
        mainLayout.Add(self.timeChooser, flag=wx.EXPAND | wx.ALIGN_BOTTOM)
        self.Fit()

    def onClickOrbChoose(self, bagPath):
        self.loadData()

    def onClickGtChoose(self, gtPath):
        self.loadData()

    def onChangeTimePosition(self, e):
        if self.currentORBTimestamp == None:
            return


#        print (self.timeChooser.GetValue())
        self.currentORBTimestamp = int(self.timeChooser.GetValue())
        self.redrawPosition()

    def onBagChange(self, bagPath):
        self.bagImageView.setBagPath(bagPath)
        self.imageTopicChooser.AppendItems(self.bagImageView.getAllTopics())

    def onImageTopicChange(self, e):
        self.imageTopic = (self.imageTopicChooser.GetValue())
        self.bagImageView.setTopic(self.imageTopic)
        self.redrawPosition()

    def loadData(self):
        if (self.orbResultChooser.GetValue() == ''
                or self.groundTruthChooser.GetValue() == ''):
            print("Select filenames first")
            return None
        print("Wait...")

        # Load ground truth and plot it
        self.ax = self.figure.add_subplot(111)
        self.ax.set_autoscale_on(True)
        self.ax.grid(True)
        self.groundTruth = PoseTable.loadFromBagFile(
            self.groundTruthChooser.GetValue(), 'world', 'ndt_frame')
        gtTbl = self.groundTruth.toArray()
        self.groundTruthPlot, = self.ax.plot(gtTbl[:, 0], gtTbl[:, 1])
        #        self.groundTruthPlot, = self.ax.plot([0,1,2], [4,5,6])

        self.orbResult = PoseTable.loadFromBagFile(
            self.orbResultChooser.GetValue(), '/ORB_SLAM/World',
            '/ORB_SLAM/ExtCamera')
        orbTbl = self.orbResult.toArray()
        self.orbResultPlot, = self.ax.plot(orbTbl[:, 0], orbTbl[:, 1])

        self.canvas.draw()
        self.background = self.canvas.copy_from_bbox(self.ax.bbox)
        #        self.helpText.Show(True)

        self.timeChooser.SetRange(self.orbResult[0].timestamp,
                                  self.orbResult.last().timestamp)
        self.currentORBTimestamp = self.orbResult[0].timestamp
        self.redrawPosition()

    @staticmethod
    def readMessage(bag, topic, timestamp):
        tm = rospy.Time.from_sec(timestamp)
        for topic, msg, time in bag.read_messages(topics=topic, start_time=tm):
            return msg

    def redrawPosition(self):
        if self.currentORBTimestamp == None:
            return
        dp = datetime.datetime.fromtimestamp(self.currentORBTimestamp)
        self.timeDisplay.SetValue(str(dp))

        orbPose = self.orbResult.findNearestInTime(self.currentORBTimestamp,
                                                   0.1)

        self.canvas.restore_region(self.background)
        if (orbPose != None):
            if (self.vehiclePointer == None):
                self.vehiclePointer = self.ax.scatter(orbPose.x,
                                                      orbPose.y,
                                                      s=100,
                                                      c=[1, 0, 0, 0.5],
                                                      linewidths=0)
            else:
                self.vehiclePointer.set_offsets([orbPose.x, orbPose.y])
            self.orbStatus.SetLabel("OK")
        else:
            self.orbStatus.SetLabel("Lost")
        self.canvas.draw()
        self.canvas.blit(self.ax.bbox)

        if self.imageTopic != None:
            self.bagImageView.showTime(self.currentORBTimestamp)
示例#47
0
class CartesianPanel(wx.Panel):
    def _init_ctrls(self, prnt):
        # generated method, don't edit
        wx.Panel.__init__(self,
                          id=wxID_LEFTPANEL,
                          name='CartesianPanel',
                          parent=prnt,
                          pos=wx.Point(8, 8),
                          size=wx.Size(200, 400),
                          style=wx.NO_BORDER | wx.TAB_TRAVERSAL)
        self.SetClientSize(wx.Size(200, 400))
        self.SetBackgroundColour(wx.Colour(0, 0, 255))
        self.Bind(wx.EVT_PAINT, self.OnCartesianPanelPaint)

    def __init__(self, parent, id, pos, size, style, name):
        self._init_ctrls(parent)
        ##Create a matplotlib figure/canvas in this panel
        ##the background colour will be the same as the panel
        ##the size will also be the same as the panel
        ##calculate size in inches
        pixels_width, pixels_height = self.GetSizeTuple()
        self.dpi = 96.0
        inches_width = pixels_width / self.dpi
        inches_height = pixels_height / self.dpi

        ##calculate colour in RGB 0 to 1
        colour = self.GetBackgroundColour()
        self.fig = Figure(figsize=(inches_width,inches_height), dpi = self.dpi\
            ,facecolor=(colour.Red()/255.0, colour.Green()/255.0, colour.Blue()/255.0)\
            ,edgecolor=(colour.Red()/255.0, colour.Green()/255.0, colour.Blue()/255.0))

        ##left : the left side of the subplots of the figure
        ##     |      right : the right side of the subplots of the figure
        ##     |      bottom : the bottom of the subplots of the figure
        ##     |      top : the top of the subplots of the figure
        ##     |      wspace : the amount of width reserved for blank space between subplots
        ##     |      hspace : the amount of height reserved for white space between subplots
        ##     |

        self.canvas = FigureCanvasWxAgg(self, -1, self.fig)

        ##now put everything in a sizer
        sizer = wx.BoxSizer(wx.VERTICAL)
        # This way of adding to sizer allows resizing
        sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
        self.SetSizer(sizer)
        self.Fit()

        ##now finally create the actual plot
        ##self.axes = self.fig.add_subplot(111)
        self.axes = self.fig.add_axes(
            (0.16, 0.08, 0.90, 0.85))  ##left,bottom,width,height
        self.plot = self.axes.plot([0, 0], [0, 0], 'b', animated=True)
        self.naohistoryplot = self.axes.plot([0, 0], [0, 0],
                                             'r',
                                             animated=True)
        self.naohistoryx = list()
        self.naohistoryy = list()
        self.naoplot = self.axes.plot([0, 0], [0, 0],
                                      'r',
                                      marker='o',
                                      markersize=4,
                                      animated=True)

        self.leftedgeplot = self.axes.plot([0, 0], [0, 0],
                                           'orange',
                                           marker='o',
                                           markersize=4,
                                           linewidth=0,
                                           animated=True)
        self.rightedgeplot = self.axes.plot([0, 0], [0, 0],
                                            'purple',
                                            marker='o',
                                            markersize=4,
                                            linewidth=0,
                                            animated=True)

        ##plot formatting
        self.axes.set_title('Laser Image', fontsize='10')
        #self.axes.set_xlabel('y (cm)', fontsize='10')
        #self.axes.set_ylabel('x (cm)', fontsize='10')
        ticks = numpy.arange(-450, 450 + 100, 100)
        labels = [str(tick) for tick in ticks]
        self.axes.set_yticks(ticks)
        self.axes.set_yticklabels(labels, fontsize=8)
        self.axes.set_ylim(ticks[0], ticks[-1])
        ticks = numpy.arange(0, 450 + 100, 100)
        labels = [str(tick) for tick in ticks]
        self.axes.set_xticks(ticks)
        self.axes.set_xticklabels(labels, fontsize=8)
        self.axes.set_xlim(ticks[0], ticks[-1])

        self.canvas.draw()
        self.canvas.gui_repaint()

        # save the clean slate background -- everything but the animated line
        # is drawn and saved in the pixel buffer background
        self.background = self.canvas.copy_from_bbox(self.axes.bbox)

    def setNaoFinder(self, finder):
        """ """
        self.NAOFinder = finder

    def updateData(self, data, naox, naoy):
        """updateData. Updates the data that this panel is displaying.
        """
        self.x = data[0]
        self.y = data[1]

        self.plot[0].set_data(self.x, self.y)
        self.naoplot[0].set_data([naox, naox], [naoy, naoy])
        self.naohistoryx.append(naox)
        self.naohistoryy.append(naoy)
        if len(self.naohistoryx) > 400:
            del self.naohistoryx[0]
            del self.naohistoryy[0]
        self.naohistoryplot[0].set_data(self.naohistoryx, self.naohistoryy)

        leftx = list()
        lefty = list()
        for leftedge in self.NAOFinder.LeftEdges:
            leftx.append(data[0][leftedge])
            lefty.append(data[1][leftedge])

        rightx = list()
        righty = list()
        for rightedge in self.NAOFinder.RightEdges:
            rightx.append(data[0][rightedge])
            righty.append(data[1][rightedge])

        self.leftedgeplot[0].set_data(leftx, lefty)
        self.rightedgeplot[0].set_data(rightx, righty)

        # restore the clean slate background
        self.canvas.restore_region(self.background)
        # just draw the animated artist
        self.axes.draw_artist(self.plot[0])
        self.axes.draw_artist(self.naoplot[0])
        self.axes.draw_artist(self.naohistoryplot[0])

        self.axes.draw_artist(self.leftedgeplot[0])
        self.axes.draw_artist(self.rightedgeplot[0])

        # just redraw the axes rectangle
        self.canvas.blit(self.axes.bbox)

    def OnCartesianPanelPaint(self, event):
        pass
示例#48
0
class MyFrame(wx.Frame):
    def __init__(self, parent, id):
        wx.Frame.__init__(self,parent, id, 'Biometrics Scanner',
                style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER,
                size=(800, 600))
        self.panel = wx.Panel(self, -1)

        self.fig = Figure((5, 4), 75)

        self.canvas = FigureCanvasWxAgg(self.panel, -1, self.fig)
        self.init_plot()

        self.start_stop_button = wx.Button(self.panel, -1, "Start");
        self.Bind(wx.EVT_BUTTON, self.start_stop_action, self.start_stop_button)

        self.mark_time_button = wx.Button(self.panel, -1, "Mark");
        self.Bind(wx.EVT_BUTTON, self.mark_time_action, self.mark_time_button)

        self.subject_name_label = wx.StaticText(self.panel, label="", style=wx.ALIGN_CENTER)

        topBar = wx.BoxSizer(wx.HORIZONTAL)
        topBar.Add(self.start_stop_button, 1, wx.EXPAND)
        topBar.Add(self.subject_name_label, 2, wx.CENTER)
        topBar.Add(self.mark_time_button, 1, wx.EXPAND)

        font = wx.Font(22, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, True)
        aggregates_bar = wx.BoxSizer(wx.VERTICAL)
        bpmPanel = wx.Panel(self.panel, -1)
        self.currentBPM = wx.StaticText(bpmPanel, label='##', style=wx.ALIGN_RIGHT, pos=(10, 10))
        self.currentBPM.SetFont(font)
        wx.StaticText(bpmPanel, label='BPM', style=wx.ALIGN_RIGHT, pos=(150, 10))
        aggregates_bar.Add(bpmPanel, 1, wx.EXPAND)

        edResponsePanel = wx.Panel(self.panel,-1)
        self.currentEDR = wx.StaticText(edResponsePanel, label='##', style=wx.ALIGN_RIGHT, pos=(10,10))
        self.currentEDR.SetFont(font)
        wx.StaticText(edResponsePanel, label='kOhms', style=wx.ALIGN_RIGHT, pos=(150,10))
        aggregates_bar.Add(edResponsePanel, 1, wx.EXPAND)

        mainBar = wx.BoxSizer(wx.HORIZONTAL)
        mainBar.Add(self.canvas, 5, wx.EXPAND)
        mainBar.Add(aggregates_bar, 2, wx.EXPAND)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(topBar, 0, wx.EXPAND)
        sizer.Add(mainBar, 5, wx.EXPAND)

        self.panel.SetSizer(sizer)
        self.panel.Fit()

        # Setting up the menu.
        filemenu = wx.Menu()

        # wx.ID_ABOUT and wx.ID_EXIT are standard IDs provided by wxWidgets.
        about_button = filemenu.Append(wx.ID_ABOUT, "&About"," Information about this program")
        self.Bind(wx.EVT_MENU, self.OnAbout, about_button)

        filemenu.AppendSeparator()
        exit_button = filemenu.Append(wx.ID_EXIT,"E&xit"," Terminate the program")
        self.Bind(wx.EVT_MENU, self.OnExit, exit_button)
        # Creating the menubar.
        menuBar = wx.MenuBar()
        menuBar.Append(filemenu,"&File") # Adding the "filemenu" to the MenuBar
        self.SetMenuBar(menuBar)  # Adding the MenuBar to the Frame content.

        self.Bind(EVT_REDRAW, self.onRedraw)
        self.Bind(EVT_RESTART, self.onRestart)

        self.mark_times = list()

        self.daqThread = None
        self.running = False

        self.beats_drawn = 0
        self.marks_drawn = 0


    def init_plot(self):
        self.t_window = 15
        self.t_undrawn = 2
        self.data_sets = ['ecg', 'bpm2', 'edr']
        self.data_limits = [(-512, 512), (50, 150), (80, 300)]
        # self.data_limits = [(-10, 10), (50, 55), (150, 200)]
        self.lines = list()
        self.data_labels = ['ECG', 'Pulse Rate (BPM)', 'EDR (kOhms)']
        self.show_beats = [True, False, False]
        self.show_marks = [True, True, True]
        self.axes = [self.fig.add_subplot(len(self.data_sets), 1, x) for x in range(1, len(self.data_sets) + 1)]

        self.reset_plot()

    def reset_plot(self):
        self.beats_drawn = 0
        self.marks_drawn = 0

        for ax, data_label, data_limit, show_beat, show_mark in zip(
                self.axes, self.data_labels, self.data_limits, self.show_beats, self.show_marks):
            ax.cla()
            ax.set_ylabel(data_label)
            data_set_line = ax.plot(0,0)[0]
            data_point_line = ax.plot(0,-600,'go')[0]
            beat_line = None
            mark_line = None
            if show_beat:
                beat_line = ax.plot(0,-600, 'ro')[0]
            if show_mark:
                mark_line = ax.plot(0,-600, 'ko')[0]
            ax.set_xlim(self.t_undrawn - self.t_window, self.t_undrawn)
            ax.set_ylim(*data_limit)
            self.lines.append((data_set_line, data_point_line, beat_line, mark_line))

        self.canvas.draw()
        self.backgrounds = [self.canvas.copy_from_bbox(ax.bbox) for ax in self.axes]
    
    def reset_data_limits(self, ax, background, limits):
	ax.set_ylim(*limits)
        self.canvas.draw()
        background = self.canvas.copy_from_bbox(ax.bbox)
            
    def onRedraw(self, event):
        # last_drawable = self.daqThread.last_drawable
        # first_drawable = self.daqThread.first_drawable
        self.daqThread.redraw_lock()
        self.currentBPM.SetLabel('%0.3f' % self.daqThread.get_last('bpm2'))
        if self.daqThread.pulse_regular:
            self.currentBPM.SetForegroundColour((0,255,0))
        else:
            self.currentBPM.SetForegroundColour((255,0,0))

        self.currentEDR.SetLabel('%0.3f' % self.daqThread.get_last('edr'))

        t_max = self.daqThread.get_last('time')
        drawable_time = [x - t_max for x in self.daqThread.get_drawable('time')]

        t_cutoff = self.t_undrawn - self.t_window + t_max
        beats_list_x = None
        beats_list_y = None
        try:
            beats_list_x, beats_list_y = zip(
                *[(x - t_max, 1) for x in self.daqThread.beats if x > t_cutoff])
        except ValueError:
            ''''''
            # print "beats_list unpopulated"
        marks_list_x = None
        marks_list_y = None
        try:
            marks_list_x, marks_list_y = zip(
                *[(x - t_max, 1) for x in self.daqThread.marks if x > t_cutoff])
        except ValueError:
            ''''''
        for ax, background, data_set_name, data_label, line_tuple, data_limit in zip(
                self.axes, self.backgrounds, self.data_sets, self.data_labels, self.lines, self.data_limits):
            self.canvas.restore_region(background)
            data_set_line, data_point_line, beat_line, mark_line = line_tuple
            data_set_line.set_xdata(drawable_time)
            data_set_line.set_ydata(self.daqThread.get_drawable(data_set_name))
            # new_data_limit = self.daqThread.get_y_limits(data_set_name)
            # if new_data_limit[0] < data_limit[0] or new_data_limit[1] > data_limit[1]:
            #     self.reset_data_limits(ax, background, new_data_limit)
            
            ax.draw_artist(data_set_line)
            data_point_line.set_ydata(self.daqThread.get_last(data_set_name))
            ax.draw_artist(data_point_line)
            if beat_line is not None and beats_list_x is not None:
                beat_line.set_xdata(beats_list_x);
                beat_line.set_ydata([y * float(data_limit[1] - (data_limit[1] - data_limit[0]) / 8.0) for y in beats_list_y]);
                ax.draw_artist(beat_line)
            if mark_line is not None and marks_list_x is not None:
                mark_line.set_xdata(marks_list_x)
                mark_line.set_ydata([y * float(data_limit[0] + (data_limit[1] - data_limit[0]) / 8.0) for y in marks_list_y]);
                ax.draw_artist(mark_line)
            self.canvas.blit(ax.bbox)
        self.daqThread.redraw_lock_release()


    def OnAbout(self, event):
        """"""

    def onRestart(self, event):
        if self.running:
            redrawThread = RedrawThread(self)
            redrawThread.start()

    def start_stop_action(self, event):
        if self.running:
            self.start_stop_button.SetLabel("Processing...")
            self.running = False
            self.daqThread.stop()
            while self.daqThread.is_alive():
                sleep(0.1)
            self.daqThread = None
            self.start_stop_button.SetLabel("Start")
        else:
            self.reset_plot()
            self.running = True
            self.daqThread = DAQThread()
            self.daqThread.t_drawable = self.t_window - self.t_undrawn
            self.daqThread.start()
            redrawThread = RedrawThread(self)
            redrawThread.start()
            self.start_stop_button.SetLabel("Stop")

    def OnExit(self, event):
        exit()

    def mark_time_action(self, event):
        if self.daqThread.is_alive():
            self.daqThread.add_mark()
class PlotFigure(wx.Frame):
    def __init__(self, portname, baudrate):###
        wx.Frame.__init__(self, None, wx.ID_ANY, title="Arduino Monitor", size=(800,600))

        self.fig = Figure((8,6), 100)
        self.canvas = FigureCanvas(self, wx.ID_ANY, self.fig)
        self.ax = self.fig.add_subplot(1,1,1)

        self.ax.set_ylim([-0.1, 1.15])
        self.ax.set_xlim([0,300])
        self.ax.set_autoscale_on(False)

        self.xleft = 0
        self.xright = 300
        self.ax.set_xticks([])
        self.ax.set_yticks([0.0,0.5,1.0])
        self.ax.grid(True)

        self.data = [None] * 300    
        
        self.l_data,=self.ax.plot(range(300), self.data, label='Arduino Output')
        #',' means iteration
        self.l_x1 = self.ax.text(0,-0.05,'') 
        self.l_x5 = self.ax.text(290,-0.05,'')

        self.ax.legend(loc='upper center', ncol=1)

        self.canvas.draw()
        self.bg = self.canvas.copy_from_bbox(self.ax.bbox)

        self.ser = serial.Serial(portname, baudrate)###open serial port and assign a baudrate
        time.sleep(5)#this command is very important since the arduino board needs a short while to settle. 
        #without this settling time, the programme would got stuck!
        self.ser.flushInput()
        self.ser.flushOutput()
        self.counter = 0.0

        wx.EVT_TIMER(self, TIMER_ID, self.onTimer)#binding

    def onTimer(self, evt):
        self.ser.write("?")#the py program might need to wait a bit till data arrives in buffer
        tmp = self.ser.read()#tmp is a string
        tmp = int(tmp)#tmp is an integer now
        self.canvas.restore_region(self.bg)
        self.data = self.data[1:] + [tmp]#keep self.data 300 elements long while forwarding the sequence
        
        self.xleft = self.xleft + 1
        self.xright = self.xright + 1
        #print self.xleft, self.xright

        self.l_data.set_ydata(self.data)
        self.counter = self.counter + 0.05
        tmp1 = str(int(self.counter + 0.5))
        tmp2 = str(int(self.counter + 0.5) - 15)# 15 = 300 pts / (1 sec / 50 msec)
        self.l_x1.set_text(tmp2)
        self.l_x5.set_text(tmp1)

        self.ax.draw_artist(self.l_data)
        
        self.ax.draw_artist(self.l_x1)##
        self.ax.draw_artist(self.l_x5)##

        self.canvas.blit(self.ax.bbox)
示例#50
0
文件: gui.py 项目: agos/BeatingModeSW
class MainFrame(wx.Frame):

    def __init__(self, parent=None, id=-1, title="Main Frame"):
        wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition,
            wx.Size(900, 700), style=wx.DEFAULT_FRAME_STYLE)

        self.create_menu()
        self.statusbar = self.CreateStatusBar()
        self.create_main_panel()
        self.Centre()
        # self.beatingimage = BeatingImage(path="dati/generated.dat", repetitions=15)
        # self.beatingdata = BeatingImageRow(data=self.beatingimage.data[24,:,:], pixel_frequency=100.0, shutter_frequency=5.856 / 2)
        self.beatingimage = BeatingImage(path="dati/samp6.dat")
        self.beatingdata = BeatingImageRow(data=self.beatingimage.data[1,:,:], pixel_frequency=100.0, shutter_frequency=5.865 / 2)
        self.drawingdata = self.beatingdata.data
        self.line_det_h, = self.axes_det1.plot(
            arange(self.beatingdata.image_width),
            zeros_like(arange(self.beatingdata.image_width)),
            animated=True)
        self.axes_det1.set_ylim(self.beatingdata.data.min(), self.beatingdata.data.max())
        self.line_det_v, = self.axes_det2.plot(
            arange(self.beatingdata.image_height),
            zeros_like(arange(self.beatingdata.image_height)),
            animated=True)
        self.axes_det2.set_ylim(self.beatingdata.data.min(), self.beatingdata.data.max())
        self.crosshair_lock = False
        self.draw_figure()

    def create_menu(self):
        self.menubar = wx.MenuBar()
        file_menu = wx.Menu()
        close_window_menu = wx.MenuItem(file_menu, 105,
            'Close &Window\tCtrl+W', 'Close the Window')
        file_menu.AppendItem(close_window_menu)
        self.Bind(wx.EVT_MENU, self.OnCloseMe, close_window_menu)
        self.menubar.Append(file_menu, '&File')
        self.SetMenuBar(self.menubar)

    def create_main_panel(self):
        """ Creates the main panel with all the controls on it:
             * mpl canvas
             * mpl navigation toolbar
             * Control panel for interaction
        """
        self.panel = wx.Panel(self)
        # Create the mpl Figure and FigCanvas objects.
        # 5x4 inches, 100 dots-per-inch
        self.dpi = 100
        self.fig = Figure((9.0, 7.0), dpi=self.dpi)
        self.canvas = FigCanvas(self.panel, -1, self.fig)
        self.onclick_cid = self.canvas.mpl_connect('button_press_event', self.on_mouseclick)
        self.detailfig = Figure((1.0, 7.0), dpi=self.dpi)
        self.detailcanvas = FigCanvas(self.panel, -1, self.detailfig)
        # Since we have only one plot, we can use add_axes
        # instead of add_subplot, but then the subplot
        # configuration tool in the navigation toolbar wouldn't
        # work.
        self.axes = self.fig.add_subplot(111)
        self.axes_det1 = self.detailfig.add_subplot(211)
        self.axes_det2 = self.detailfig.add_subplot(212)
        self.in_axes = False
        self.canvas.mpl_connect('axes_enter_event', self.enter_axes)
        self.canvas.mpl_connect('axes_leave_event', self.leave_axes)
        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_unbleach = wx.CheckBox(self.panel, -1,
            "Correct for bleaching",
            style=wx.ALIGN_RIGHT)
        self.Bind(wx.EVT_CHECKBOX, self.on_cb_unbleach, self.cb_unbleach)
        self.cb_ratiograph = wx.CheckBox(self.panel, -1,
            "Show enhancement ratio data")
        self.cb_ratiograph.Enable(False)
        self.Bind(wx.EVT_CHECKBOX, self.on_cb_ratiograph, self.cb_ratiograph)
        self.slider_label = wx.StaticText(self.panel, -1,
            "Crosshair opacity (%): ")
        self.slider_alpha = wx.Slider(self.panel, -1,
            value=30,
            minValue=1,
            maxValue=100,
            style=wx.SL_AUTOTICKS | wx.SL_LABELS)
        self.alpha = 0.3
        self.slider_alpha.SetTickFreq(5, 1)
        self.Bind(wx.EVT_COMMAND_SCROLL_THUMBTRACK, self.on_slider_alpha, self.slider_alpha)
        # Create the navigation toolbar, tied to the canvas
        self.toolbar = NavigationToolbar(self.canvas)
        #
        # Layout with box sizers
        #
        self.vbox = wx.BoxSizer(wx.VERTICAL)
        self.graphbox = wx.BoxSizer(wx.HORIZONTAL)
        flags = wx.ALIGN_LEFT | wx.ALL | wx.ALIGN_CENTER_VERTICAL
        self.graphbox.Add(self.canvas, 2, flag=flags| wx.GROW)
        self.graphbox.Add(self.detailcanvas, 1, flag=flags | wx.GROW)
        self.vbox.Add(self.graphbox, 1, wx.LEFT | wx.TOP | wx.GROW)
        self.vbox.Add(self.toolbar, 0, wx.EXPAND)
        self.vbox.AddSpacer(10)
        self.hbox = wx.BoxSizer(wx.HORIZONTAL)
        flags = wx.ALIGN_LEFT | wx.ALL | wx.ALIGN_CENTER_VERTICAL
        self.hbox.Add(self.cb_unbleach, 0, border=3, flag=flags)
        self.hbox.Add(self.cb_ratiograph, 0, border=3, flag=flags)
        self.hbox.Add(self.cb_grid, 0, border=3, flag=flags)
        self.hbox.AddSpacer(30)
        self.hbox.Add(self.slider_label, 0, flag=flags)
        self.hbox.Add(self.slider_alpha, 0, border=3, flag=flags)
        self.vbox.Add(self.hbox, 0, flag = wx.ALIGN_CENTER | wx.TOP)
        self.panel.SetSizer(self.vbox)
        self.vbox.Fit(self)
        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.callback, self.timer)
        self.prevx, self.prevy = -1, -1

    def draw_figure(self):
        """ Redraws the figure
        """
        self.axes.clear()
        if self.cb_grid.IsChecked():
            self.axes.grid(b=True, color="#ffffff", alpha=0.8)
        if self.cb_unbleach.IsChecked():
            self.drawingdata = self.beatingdata.unbleached_data
        else:
            self.drawingdata = self.beatingdata.data
        self.beating_image = self.axes.imshow(self.drawingdata, cmap=my_color_map)
        self.beating_image.set_interpolation('nearest')
        self.canvas.draw()
        self.detailcanvas.draw()
        if not self.cb_ratiograph.IsChecked():
            self.background_h = self.detailcanvas.copy_from_bbox(self.axes_det1.bbox)
            self.background_v = self.detailcanvas.copy_from_bbox(self.axes_det2.bbox)


    def on_cb_grid(self, event):
        self.draw_figure()

    def on_cb_unbleach(self, event):
        if self.cb_unbleach.IsChecked():
            self.cb_ratiograph.Enable(True)
        else:
            self.cb_ratiograph.Enable(False)
        self.draw_figure()

    def on_cb_ratiograph(self,event):
        if self.cb_ratiograph.IsChecked():
            self.axes_det1.clear()
            width = self.drawingdata.shape[1]
            self.er_graph, = self.axes_det1.plot(
                arange(width),
                self.beatingdata.enhancement_ratios)
            self.axes_det2.clear()
            self.min_graph, = self.axes_det2.plot(
                arange(width),
                self.beatingdata.reconstructed_off)
            self.max_graph, = self.axes_det2.plot(
                arange(width),
                self.beatingdata.reconstructed_on)
            self.detailcanvas.draw()
            self.axes_det1.autoscale()
            self.axes_det2.autoscale()
        else:
            # Riattivare il vecchio grafico!
            self.axes_det1.cla()
            self.axes_det2.cla()
            self.line_det_h, = self.axes_det1.plot(
                arange(self.beatingdata.image_width),
                zeros_like(arange(self.beatingdata.image_width)),
                animated=True)
            self.axes_det1.set_ylim(self.beatingdata.data.min(), self.beatingdata.data.max())
            self.line_det_v, = self.axes_det2.plot(
                arange(self.beatingdata.image_height),
                zeros_like(arange(self.beatingdata.image_height)),
                animated=True)
            self.axes_det2.set_ylim(self.beatingdata.data.min(), self.beatingdata.data.max())
            self.detailcanvas.draw()
            self.background_h = self.detailcanvas.copy_from_bbox(self.axes_det1.bbox)
            self.background_v = self.detailcanvas.copy_from_bbox(self.axes_det2.bbox)

    def OnCloseMe(self, event):
        self.Close(True)

    def on_mouseover(self, event):
        if event.inaxes == self.axes:
            x, y = int(floor(event.xdata)), int(floor(event.ydata))
            self.x, self.y = x, y

    def on_mouseclick(self, event):
        if event.inaxes == self.axes:
            if not self.crosshair_lock:
                self.crosshair_lock = True
                self.deactivate_mouseover()
                x, y = int(floor(event.xdata)), int(floor(event.ydata))
                self.x, self.y = x, y
            else:
                self.crosshair_lock = False
                x, y = int(floor(event.xdata)), int(floor(event.ydata))
                self.x, self.y = x, y
                self.activate_mouseover()

    def activate_mouseover(self):
        self.cid = self.canvas.mpl_connect('motion_notify_event',
            self.on_mouseover)
        self.timer.Start(80)

    def deactivate_mouseover(self):
        self.canvas.mpl_disconnect(self.cid)
        self.timer.Stop()

    def enter_axes(self, event):
        self.in_axes = True
        if not self.crosshair_lock:
            self.activate_mouseover()

    def leave_axes(self, event):
        self.in_axes = False
        if not self.crosshair_lock:
            self.deactivate_mouseover()
            self.statusbar.SetStatusText(" ")
            self.beating_image.set_array(self.drawingdata)
            self.canvas.draw()
            if not self.cb_ratiograph.IsChecked():
                self.axes_det1.clear()
                self.axes_det2.clear()
                self.detailcanvas.draw()

    def callback(self, event):
        if self.in_axes and (self.x != self.prevx or self.y != self.prevy):
            x, y = self.x, self.y
            value = self.drawingdata[y, x]
            msg = "Coordinate: {0}, {1} Valore: {2}".format(x, y, value)
            self.statusbar.SetStatusText(msg)
            highlight_data = copy(self.drawingdata)
            highlight_data[:, x] = highlight_data[:, x] * (1.0 - self.alpha) + highlight_data.max() * self.alpha
            highlight_data[y, :] = highlight_data[y, :] * (1.0 - self.alpha) + highlight_data.max() * self.alpha
            highlight_data[y, x] = value
            self.beating_image.set_array(highlight_data)
            self.canvas.draw()
            # Aggiorno i dettagli
            if not self.cb_ratiograph.IsChecked():
                self.detailcanvas.restore_region(self.background_h)
                self.detailcanvas.restore_region(self.background_v)
                self.line_det_h.set_ydata(self.drawingdata[y, :])
                self.line_det_v.set_ydata(self.drawingdata[:, x])
                self.axes_det1.draw_artist(self.line_det_h)
                self.axes_det2.draw_artist(self.line_det_v)
                self.detailcanvas.blit(self.axes_det1.bbox)
                self.detailcanvas.blit(self.axes_det2.bbox)
                self.prevx, self.prevy = x, y

    def on_slider_alpha(self, event):
        self.alpha = self.slider_alpha.GetValue() / 100.0
示例#51
0
class PlotFrame(wx.Frame):
    """
        PlotFrame is a custom wxPython frame to hold the panel with a
        Figure and WxAgg backend canvas for matplotlib plots or other
        figures.  In this frame:

        self is an instance of a wxFrame;
        axes is an instance of MPL Axes;
        fig is an instance of MPL Figure;
        panel is an instance of wxPanel, used for the main panel, to hold
        canvas, an instance of MPL FigureCanvasWxAgg.
    """

    # Main function to set everything up when the frame is created
    def __init__(self, title, pos, size):
        """
           This will be executed when an instance of PlotFrame is created.
           It is the place to define any globals as "self.<name>".
        """
        wx.Frame.__init__(self, None, wx.ID_ANY, title, pos, size)

        if len(sys.argv) < 2:
            self.filename = ""
        else:
            self.filename = sys.argv[1]

        # set some Boolean flags
        self.STOP = False
        self.data_loaded = False
        self.reverse_play = False

        self.step = 1

        #    Make the main Matplotlib panel for plots
        self.create_main_panel()  # creates canvas and contents

        # Then add wxPython widgets below the MPL canvas
        # Layout with box sizers

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.EXPAND)
        self.sizer.AddSpacer(10)
        self.sizer.Add(self.toolbar, 0, wx.EXPAND)
        self.sizer.AddSpacer(10)

        #    Make the control panel with a row of buttons
        self.create_button_bar()
        self.sizer.Add(self.button_bar_sizer, 0, flag=wx.ALIGN_CENTER | wx.TOP)

        #    Make a Status Bar
        self.statusbar = self.CreateStatusBar()
        self.sizer.Add(self.statusbar, 0, wx.EXPAND)

        self.SetStatusText("Frame created ...")

        # -------------------------------------------------------
        #	       set up the Menu Bar
        # -------------------------------------------------------
        menuBar = wx.MenuBar()

        menuFile = wx.Menu()  # File menu
        menuFile.Append(1, "&Open", "Filename(s) or wildcard list to plot")
        menuFile.Append(3, "Save", "Save plot as a PNG image")
        menuFile.AppendSeparator()
        menuFile.Append(10, "E&xit")
        menuBar.Append(menuFile, "&File")

        menuHelp = wx.Menu()  # Help menu
        menuHelp.Append(11, "&About Netview")
        menuHelp.Append(12, "&Usage and Help")
        menuHelp.Append(13, "Program &Info")

        menuBar.Append(menuHelp, "&Help")
        self.SetMenuBar(menuBar)

        self.panel.SetSizer(self.sizer)
        self.sizer.Fit(self)

        # -------------------------------------------------------
        #      Bind the menu items to functions
        # -------------------------------------------------------

        self.Bind(wx.EVT_MENU, self.OnOpen, id=1)
        self.Bind(wx.EVT_MENU, self.OnSave, id=3)
        self.Bind(wx.EVT_MENU, self.OnQuit, id=10)
        self.Bind(wx.EVT_MENU, self.OnAbout, id=11)
        self.Bind(wx.EVT_MENU, self.OnUsage, id=12)
        self.Bind(wx.EVT_MENU, self.OnInfo, id=13)

        # methods defined below to get and plot the data
        # Normally do the plot on request, and not here
        # self.get_data_params()
        # self.init_plot()
        # self.get_xyt_data()
        # plot_data()

# ---------- end of __init__ ----------------------------

# -------------------------------------------------------
#   Function to make the main Matplotlib panel for plots
# -------------------------------------------------------

    def create_main_panel(self):
        """ create_main_panel creates the main mpl panel with instances of:
             * mpl Canvas 
             * mpl Figure 
             * mpl Figure
             * mpl Axes with subplot
             * mpl Widget class Sliders and Button
             * mpl navigation toolbar
           self.axes is the instance of MPL Axes, and is where it all happens
        """

        self.panel = wx.Panel(self)

        # Create the mpl Figure and FigCanvas objects.
        # 3.5 x 5 inches, 100 dots-per-inch
        #
        self.dpi = 100
        self.fig = Figure((3.5, 5.0), dpi=self.dpi)
        self.canvas = FigCanvas(self.panel, wx.ID_ANY, self.fig)

        # Since we have only one plot, we could use add_axes
        # instead of add_subplot, but then the subplot
        # configuration tool in the navigation toolbar wouldn't work.

        self.axes = self.fig.add_subplot(111)
        # (111) == (1,1,1) --> row 1, col 1, Figure 1)
        # self.axes.set_title("View from: "+self.filename)

        # Now create some sliders below the plot after making room
        self.fig.subplots_adjust(left=0.1, bottom=0.20)

        self.axtmin = self.fig.add_axes([0.2, 0.10, 0.5, 0.03])
        self.axtmax = self.fig.add_axes([0.2, 0.05, 0.5, 0.03])

        self.stmin = Slider(self.axtmin, 't_min:', 0.0, 1.0, valinit=0.0)
        self.stmax = Slider(self.axtmax, 't_max:', 0.0, 1.0, valinit=1.0)
        self.stmin.on_changed(self.update_trange)
        self.stmax.on_changed(self.update_trange)

        self.axbutton = self.fig.add_axes([0.8, 0.07, 0.1, 0.07])
        self.reset_button = Button(self.axbutton, 'Reset')
        self.reset_button.color = 'skyblue'
        self.reset_button.hovercolor = 'lightblue'
        self.reset_button.on_clicked(self.reset_trange)

        # Create the navigation toolbar, tied to the canvas

        self.toolbar = NavigationToolbar(self.canvas)

    def update_trange(self, event):
        self.t_min = self.stmin.val
        self.t_max = self.stmax.val
        # print(self.t_min, self.t_max)

    def reset_trange(self, event):
        self.stmin.reset()
        self.stmax.reset()

    def create_button_bar(self):
        """
	create_button_bar makes a control panel bar with buttons and
	toggles for

	New Data - Play - STOP - Single Step - Forward/Back - Normal/Fast

	It does not create a Panel container, but simply creates Button
	objects with bindings, and adds  them to a horizontal BoxSizer
	self.button_bar_sizer.	This is added to the PlotFrame vertical
	BoxSizer, after the MPL canvas, during initialization of the frame.

	"""
        rewind_button = wx.Button(self.panel, -1, "New Data")
        self.Bind(wx.EVT_BUTTON, self.OnRewind, rewind_button)

        replot_button = wx.Button(self.panel, -1, "Play")
        self.Bind(wx.EVT_BUTTON, self.OnReplot, replot_button)

        sstep_button = wx.Button(self.panel, -1, "Single Step")
        self.Bind(wx.EVT_BUTTON, self.OnSstep, sstep_button)

        stop_button = wx.Button(self.panel, -1, "STOP")
        self.Bind(wx.EVT_BUTTON, self.OnStop, stop_button)

        # The toggle buttons need to be globally accessible

        self.forward_toggle = wx.ToggleButton(self.panel, -1, "Forward")
        self.forward_toggle.SetValue(True)
        self.forward_toggle.SetLabel("Forward")
        self.Bind(wx.EVT_TOGGLEBUTTON, self.OnForward, self.forward_toggle)

        self.fast_toggle = wx.ToggleButton(self.panel, -1, " Normal ")
        self.fast_toggle.SetValue(True)
        self.fast_toggle.SetLabel(" Normal ")
        self.Bind(wx.EVT_TOGGLEBUTTON, self.OnFast, self.fast_toggle)

        # Set button colors to some simple colors that are likely
        # to be independent on X11 color definitions.  Some nice
        # bit maps (from a media player skin?) should be used
        # or the buttons and toggle state colors in OnFast() below

        rewind_button.SetBackgroundColour('skyblue')
        replot_button.SetBackgroundColour('skyblue')
        sstep_button.SetBackgroundColour('skyblue')
        stop_button.SetBackgroundColour('skyblue')
        self.forward_toggle.SetForegroundColour('black')
        self.forward_toggle.SetBackgroundColour('yellow')
        self.fast_toggle.SetForegroundColour('black')
        self.fast_toggle.SetBackgroundColour('yellow')
        self.button_bar_sizer = wx.BoxSizer(wx.HORIZONTAL)
        flags = wx.ALIGN_CENTER | wx.ALL
        self.button_bar_sizer.Add(rewind_button, 0, border=3, flag=flags)
        self.button_bar_sizer.Add(replot_button, 0, border=3, flag=flags)
        self.button_bar_sizer.Add(sstep_button, 0, border=3, flag=flags)
        self.button_bar_sizer.Add(stop_button, 0, border=3, flag=flags)
        self.button_bar_sizer.Add(self.forward_toggle, 0, border=3, flag=flags)
        self.button_bar_sizer.Add(self.fast_toggle, 0, border=3, flag=flags)

    # -------------------------------------------------------
    #	Functions to generate or read (x,y) data and plot it
    # -------------------------------------------------------

    def get_data_params(self):
        #  These parameters  would normally be provided in a file header,
        # past as arguments in a function, or from other file information
        #  Next version will bring up a dialog for dt NX NY if no file header

        # Here check to see if a filename should be entered from File/Open
        # self.filename = 'Ex_net_Vm_0001.txt'
        if len(self.filename) == 0:
            # fake a button press of File/Open
            self.OnOpen(wx.EVT_BUTTON)

        # should check here if file exists as specified [path]/filename

        # assume it is a bzip2 compressed file
        try:
            fp = bz2.BZ2File(self.filename)
            line = fp.readline()
        except IOError:
            # then assume plain text
            fp = open(self.filename)
            line = fp.readline()

        fp.close()

        # check if first line is a header line starting with '#'
        header = line.split()
        if header[0][0] == "#":
            self.Ntimes = int(header[1])
            self.t_min = float(header[2])
            self.dt = float(header[3])
            self.NX = int(header[4])
            self.NY = int(header[5])
        else:
            pdentry = self.ParamEntryDialog()
            if pdentry.ShowModal() == wx.ID_OK:
                self.Ntimes = int(pdentry.Ntimes_dialog.entry.GetValue())
                self.t_min = float(pdentry.tmin_dialog.entry.GetValue())
                self.dt = float(pdentry.dt_dialog.entry.GetValue())
                self.NX = int(pdentry.NX_dialog.entry.GetValue())
                self.NY = int(pdentry.NY_dialog.entry.GetValue())
                print 'Ntimes = ', self.Ntimes, ' t_min = ', self.t_min
                print 'NX = ', self.NX, ' NY = ', self.NY
            pdentry.Destroy()
        self.t_max = (self.Ntimes - 1) * self.dt
        # reset slider max and min
        self.stmin.valmax = self.t_max
        self.stmin.valinit = self.t_min
        self.stmax.valmax = self.t_max
        self.stmax.valinit = self.t_max
        self.stmax.set_val(self.t_max)
        self.stmin.reset()
        self.stmax.reset()
        fp.close()

    def init_plot(self):
        ''' 
        init_plot creates the initial plot display. A normal MPL plot
	would be created here with a command "self.axes.plot(x, y)" in
	order to create a plot of points in the x and y arrays on the
	Axes subplot.  Here, we create an AxesImage instance with
	imshow(), instead.  The initial image is a blank one of the
	proper dimensions, filled with zeroes.

        '''
        self.t_max = (self.Ntimes - 1) * self.dt
        self.axes.set_title("View of " + self.filename)
        # Note that NumPy array (row, col) = image (y, x)
        data0 = np.zeros((self.NY, self.NX))

        # Define a 'cold' to 'hot' color scale based in GENESIS 2 'hot'
        hotcolors = [
            '#000032', '#00003c', '#000046', '#000050', '#00005a', '#000064',
            '#00006e', '#000078', '#000082', '#00008c', '#000096', '#0000a0',
            '#0000aa', '#0000b4', '#0000be', '#0000c8', '#0000d2', '#0000dc',
            '#0000e6', '#0000f0', '#0000fa', '#0000ff', '#000af6', '#0014ec',
            '#001ee2', '#0028d8', '#0032ce', '#003cc4', '#0046ba', '#0050b0',
            '#005aa6', '#00649c', '#006e92', '#007888', '#00827e', '#008c74',
            '#00966a', '#00a060', '#00aa56', '#00b44c', '#00be42', '#00c838',
            '#00d22e', '#00dc24', '#00e61a', '#00f010', '#00fa06', '#00ff00',
            '#0af600', '#14ec00', '#1ee200', '#28d800', '#32ce00', '#3cc400',
            '#46ba00', '#50b000', '#5aa600', '#649c00', '#6e9200', '#788800',
            '#827e00', '#8c7400', '#966a00', '#a06000', '#aa5600', '#b44c00',
            '#be4200', '#c83800', '#d22e00', '#dc2400', '#e61a00', '#f01000',
            '#fa0600', '#ff0000', '#ff0a00', '#ff1400', '#ff1e00', '#ff2800',
            '#ff3200', '#ff3c00', '#ff4600', '#ff5000', '#ff5a00', '#ff6400',
            '#ff6e00', '#ff7800', '#ff8200', '#ff8c00', '#ff9600', '#ffa000',
            '#ffaa00', '#ffb400', '#ffbe00', '#ffc800', '#ffd200', '#ffdc00',
            '#ffe600', '#fff000', '#fffa00', '#ffff00', '#ffff0a', '#ffff14',
            '#ffff1e', '#ffff28', '#ffff32', '#ffff3c', '#ffff46', '#ffff50',
            '#ffff5a', '#ffff64', '#ffff6e', '#ffff78', '#ffff82', '#ffff8c',
            '#ffff96', '#ffffa0', '#ffffaa', '#ffffb4', '#ffffbe', '#ffffc8',
            '#ffffd2', '#ffffdc', '#ffffe6', '#fffff0'
        ]

        cmap = matplotlib.colors.ListedColormap(hotcolors)

        self.im = self.axes.imshow(data0, cmap=cmap, origin='lower')

        # http://matplotlib.sourceforge.net/examples/pylab_examples/show_colormaps.html
        # shows examples to use as a 'cold' to 'hot' mapping of value to color
        # cm.jet, cm.gnuplot and cm.afmhot are good choices, but are unlike G2 'hot'

        self.im.cmap = cmap

        # Not sure how to properly add a colorbar
        # self.cb = self.fig.colorbar(self.im, orientation='vertical')

        # refresh the canvas
        self.canvas.draw()

    def get_xyt_data(self):
        # Create scaled (0-1) luminance(x,y) array from ascii G-2 disk_out file
        # get the data to plot from the specified filename
        # Note that NumPy loadtxt transparently deals with bz2 compression
        self.SetStatusText('Data loading - please wait ....')
        rawdata = np.loadtxt(self.filename)
        # Note the difference between NumPy [row, col] order and network
        # x-y grid (x, y) = (col, row). We want a NumPy NY x NX, not
        # NX x NY, array to be used by the AxesImage object.

        xydata = np.resize(rawdata, (self.Ntimes, self.NY, self.NX))
        # imshow expects the data to be scaled to range 0-1.
        Vmin = xydata.min()
        Vmax = xydata.max()
        self.ldata = (xydata - Vmin) / (Vmax - Vmin)
        self.data_loaded = True
        self.SetStatusText('Data has been loaded - click Play')

    def plot_data(self):
        ''' plot_data() shows successive frames of the data that was loaded
            into the ldata array.  Creating a new self.im AxesImage instance
            for each frame is extremely slow, so the set_data method of
            AxesImage is used to load new data into the existing self.im for
            each frame.  Normally 'self.canvas.draw()' would be used to
            display a frame, but redrawing the entire canvas, redraws the
            axes, labels, sliders, buttons, or anything else on the canvas.
            This uses a method taken from an example in Ch 7, p. 192
            Matplotlib for Python developers, with draw_artist() and blit()
            redraw only the part that was changed.

        '''
        if self.data_loaded == False:
            # bring up a warning dialog
            msg = """
            Data for plotting has not been loaded!
            Please enter the file to plot with File/Open, unless
            it was already specified, and then click on 'New Data'
            to load the data to play back, before clicking 'Play'.
            """
            wx.MessageBox(msg, "Plot Warning", wx.OK | wx.ICON_ERROR, self)
            return

        # set color limits
        self.im.set_clim(0.0, 1.0)
        self.im.set_interpolation('nearest')
        # 'None' is is slightly faster, but not implemented for MPL ver < 1.1
        # self.im.set_interpolation('None')

        # do an initial draw, then save the empty figure axes
        self.canvas.draw()

        # self.bg = self.canvas.copy_from_bbox(self.axes.bbox)
        # However the save and restore is only  needed if I change
        # axes legends, etc.  The draw_artist(artist), and blit
        # are much faster than canvas.draw() and are sufficient.

        print 'system time (seconds) = ', time.time()

        # round frame_min down and frame_max up for the time window
        frame_min = int(self.t_min / self.dt)
        frame_max = min(int(self.t_max / self.dt) + 1, self.Ntimes)
        frame_step = self.step

        # Displaying simulation time to the status bar is much faster
        # than updating a slider progress bar, but location isn't optimum.
        # The check for the STOP button doesn't work because the button
        # click is not registered until this function exits.

        # check to see if self.reverse_play == True
        # then interchange frame_min, frame_max, and use negative step
        if self.reverse_play == True:
            frame_min = min(int(self.t_max / self.dt) + 1, self.Ntimes) - 1
            frame_max = int(self.t_min / self.dt) - 1
            frame_step = -self.step
        for frame_num in range(frame_min, frame_max, frame_step):
            self.SetStatusText('time: ' + str(frame_num * self.dt))
            if self.STOP == True:
                self.t_min = frame_num * self.dt
                # set t_min slider ?
                self.STOP = False
                break
            self.im.set_data(self.ldata[frame_num])
            self.axes.draw_artist(self.im)
            self.canvas.blit(self.axes.bbox)

        print 'system time (seconds) = ', time.time()

    #  ------------------------------------------------------------------
    #	Define the classes and functions for getting parameter values
    #  --------------------------------------------------------------

    class ParamEntryDialog(wx.Dialog):
        def __init__(self):
            wx.Dialog.__init__(self, None, wx.ID_ANY)
            self.SetSize((250, 200))
            self.SetTitle('Enter Data File Parameters')
            vbox = wx.BoxSizer(wx.VERTICAL)
            self.Ntimes_dialog = XDialog(self)
            self.Ntimes_dialog.entry_label.SetLabel('Number of entries')
            self.Ntimes_dialog.entry.ChangeValue(str(2501))
            self.tmin_dialog = XDialog(self)
            self.tmin_dialog.entry_label.SetLabel('Start time (sec)')
            self.tmin_dialog.entry.ChangeValue(str(0.0))

            self.dt_dialog = XDialog(self)
            self.dt_dialog.entry_label.SetLabel('Output time step (sec)')
            self.dt_dialog.entry.ChangeValue(str(0.0002))

            self.NX_dialog = XDialog(self)
            self.NX_dialog.entry_label.SetLabel('Number of cells on x-axis')
            self.NX_dialog.entry.ChangeValue(str(32))
            self.NY_dialog = XDialog(self)
            self.NY_dialog.entry_label.SetLabel('Number of cells on y-axis')
            self.NY_dialog.entry.ChangeValue(str(32))

            vbox.Add(self.Ntimes_dialog, 0, wx.EXPAND | wx.ALL, border=5)
            vbox.Add(self.tmin_dialog, 0, wx.EXPAND | wx.ALL, border=5)
            vbox.Add(self.dt_dialog, 0, wx.EXPAND | wx.ALL, border=5)
            vbox.Add(self.NX_dialog, 0, wx.EXPAND | wx.ALL, border=5)
            vbox.Add(self.NY_dialog, 0, wx.EXPAND | wx.ALL, border=5)

            okButton = wx.Button(self, wx.ID_OK, 'Ok')
            # vbox.Add(okButton,flag=wx.ALIGN_CENTER|wx.TOP|wx.BOTTOM, border=10)
            vbox.Add(okButton, flag=wx.ALIGN_CENTER, border=10)

            self.SetSizer(vbox)
            self.SetSizerAndFit(vbox)

    #  ------------------------------------------------------------------
    #	Define the functions executed on menu choices
    #  ---------------------------------------------------------------

    def OnQuit(self, event):
        self.Close()

    def OnSave(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 OnAbout(self, event):
        msg = """

                      G-3 Netview ver. 1.7

Netview is a stand-alone Python application for viewing
the output of GENESIS 2 and 3 network simulations.
It is intended to replace GENESIS 2 SLI scripts that use the
XODUS 'xview' widget.

The design and operation is based on the G3Plot application
for creating 2D plots of y(t) or y(x) from data files.
Unlike G3Plot, the image created with Netview is an animated
representation of a rectangular network with colored squares
used to indicate the value of some variable at that position
and time.  Typically, this would be the membrane potenial of
a cell soma, or a synaptic current in a dendrite segment.

Help/Usage gives HTML help for using Netview.
This is the main Help page.

Help/Program Info provides some information about the
objects and functions, and the wxPython and matplotlib
classes used here.

Dave Beeman, August 2012
	"""
        dlg = wx.MessageDialog(self, msg, "About G-3 Netview",
                               wx.OK | wx.ICON_QUESTION)
        dlg.ShowModal()
        dlg.Destroy()

    def OnOpen(self, event):
        dlg = wx.TextEntryDialog(self,
                                 "File with x,y data to plot",
                                 "File Open",
                                 self.filename,
                                 style=wx.OK | wx.CANCEL)
        if dlg.ShowModal() == wx.ID_OK:
            self.filename = dlg.GetValue()
            # A new filename has been entered, but the data has not been read
            self.data_loaded = False
            # print "You entered: %s" % self.filename
        dlg.Destroy()

    #  This starts with the long string of HTML to display
    class UsageFrame(wx.Frame):
        text = """
<HTML>
<HEAD></HEAD>
<BODY BGCOLOR="#D6E7F7">

<CENTER><H1>Using G-3 Netview</H1></CENTER>

<H2>Introduction and Quick Start</H2>

<p>Netview is a stand-alone Python application for viewing the output of
GENESIS 2 and 3 network simulations.  It is intended to replace GENESIS 2
SLI scripts that use the XODUS 'xview' widget.</p>

<p>The design and operation is based on the G3Plot application for creating 2D
plots of y(t) or y(x) from data files.  As with G3Plot, the main class
PlotFrame uses a basic wxPython frame to embed a matplotlib figure for
plotting.  It defines some basic menu items and a control panel of buttons
and toggles, each with bindings to a function to execute on a mouse click.</p>

<p>Unlike G3Plot, the image created with Netview is an animated
representation of a rectangular network with colored squares
used to indicate the value of some variable at that position
and time.  Typically, this would be the membrane potenial of
a cell soma, or a synaptic current in a dendrite segment.</p>

<h2>Usage</h2>

<p>The Menu Bar has <em>File/Open</em>, <em>File/Save</em>, and
<em>File/Exit</em> choices.  The Help Menu choices <em>About</em> and
<em>Usage</em> give further information.  The <em>Program Info</em>
selection shows code documentation that is contained in some of the main
function <em>docstrings</em>.</p>

<p>After starting the <em>netview</em> program, enter a data file name
in the dialog for File/Open, unless the filename was given as a
command line argument.  Then click on <strong>New Data</strong> to load the new
data and initialize the plot.  When the plot is cleared to black,
press <strong>Play</strong>.</p>

<p>The file types recognized are plain text or text files compressed with
bzip2.  The expected data format is one line for each output time step,
with each line having the membrane potential value of each cell in the net.
No time value should be given on the line.  In order to properly display
the data, netview needs some additional information about the network and
the data.  This can optionally be contained in a header line that precedes
the data.  If a header is not detected, a dialog will appear asking for the
needed parameters.</p>

<p>It is assumed that the cells are arranged on a NX x NY grid, numbered
from 0 (bottom left corner) to NX*NY - 1 (upper right corner).
In order to provide this information to netview, the data file should
begin with a header line of the form:</p>

<pre>
    #optional_RUNID_string Ntimes start_time dt NX NY SEP_X SEP_Y x0 y0 z0
</pre>

<p>The line must start with &quot;#&quot; and can optionally be followed immediately by any
string.  Typically this is some identification string generated by the
simulation run.  The following parameters, separated by blanks or any
whitespace, are:</p>

<ul>
<li>Ntimes - the number of lines in the file, exclusive of the header</li>
<li>start_time - the simulation time for the first data line (default 0.0)</li>
<li>dt - the time step used for output</li>
<li>NX, NY - the integer dimensions of the network</li>
<li>SEP_X, SEP_Y - the x,y distances between cells (optional)</li>
<li>x0, y0, z0 - the location of the compartment (data source) relative to the
cell origin</li>
</ul>

<p>The RUNID string and the last five parameters are not read or used
by netview.  These are available for other data analysis tools that
need a RUNID and the location of each source.</p>

<p>The slider bars can be used to set a time window for display, and the
<strong>Reset</strong> button can set t_min and t_max back to the defaults.
Use the <strong>Forward/Back</strong> toggle to reverse direction of
<strong>Play</strong>, and the <strong>Normal/Fast</strong> toggle to show
every tenth frame.</p> <p>The <strong>Single Step</strong> button can be
used to advance a single step at a time (or 10, if in 'Fast' mode).</p>

<p>The <strong>STOP</strong> button is currently not implemented</p>
<p>To plot different data, enter a new filename with <strong>File/Open</strong> and
repeat with <strong>New Data</strong> and <strong>Play</strong>.</p>

<HR>
</BODY>
</HTML>
        """

        def __init__(self, parent):
            wx.Frame.__init__(self,
                              parent,
                              -1,
                              "Usage and Help",
                              size=(640, 600),
                              pos=(400, 100))
            html = wx.html.HtmlWindow(self)
            html.SetPage(self.text)
            panel = wx.Panel(self, -1)
            button = wx.Button(panel, wx.ID_OK, "Close")
            self.Bind(wx.EVT_BUTTON, self.OnCloseMe, button)
            sizer = wx.BoxSizer(wx.VERTICAL)
            sizer.Add(html, 1, wx.EXPAND | wx.ALL, 5)
            sizer.Add(panel, 0, wx.ALIGN_CENTER | wx.ALL, 5)
            self.SetSizer(sizer)
            self.Layout()

        def OnCloseMe(self, event):
            self.Close(True)

        # ----------- end of class UsageFrame ---------------

    def OnUsage(self, event):
        usagewin = self.UsageFrame(self)
        usagewin.Show(True)

    def OnInfo(self, event):
        msg = "Program information for PlotFrame obtained from docstrings:"
        msg += "\n" + self.__doc__ + "\n" + self.create_main_panel.__doc__
        msg += self.create_button_bar.__doc__
        msg += self.init_plot.__doc__
        msg += self.plot_data.__doc__
        dlg = wx.lib.dialogs.ScrolledMessageDialog(self, msg,
                                                   "PlotFrame Documentation")
        dlg.ShowModal()

    #  ---------------------------------------------------------------
    #	Define the functions executed on control button click
    #  ---------------------------------------------------------------

    def OnRewind(self, event):
        self.get_data_params()
        self.init_plot()
        self.get_xyt_data()

    def OnReplot(self, event):
        self.plot_data()
        self.canvas.draw()

    def OnSstep(self, event):
        if self.data_loaded == False:
            # bring up a warning dialog
            msg = """
            Data for plotting has not been loaded!
            Please enter the file to plot with File/Open, unless
            it was already specified, and then click on 'New Data'
            to load the data to play back, before clicking 'Play'.
            """
            wx.MessageBox(msg, "Plot Warning", wx.OK | wx.ICON_ERROR, self)
            return

        self.t_max = min(self.t_max + self.dt, (self.Ntimes - 1) * self.dt)
        self.stmax.set_val(self.t_max)
        frame_num = int(self.t_max / self.dt)
        self.SetStatusText('time: ' + str(frame_num * self.dt))
        self.im.set_data(self.ldata[frame_num])
        self.axes.draw_artist(self.im)
        self.canvas.blit(self.axes.bbox)

    def OnStop(self, event):
        self.STOP = 'True'

    def OnForward(self, event):
        state = self.forward_toggle.GetValue()
        if state:
            self.reverse_play = False
            self.forward_toggle.SetLabel("Forward ")
            self.forward_toggle.SetForegroundColour('black')
            self.forward_toggle.SetBackgroundColour('yellow')
        else:
            self.reverse_play = True
            self.forward_toggle.SetLabel("  Back  ")
            self.forward_toggle.SetForegroundColour('red')
            self.forward_toggle.SetBackgroundColour('green')

    def OnFast(self, event):
        state = self.fast_toggle.GetValue()
        if state:
            # print state
            self.fast_toggle.SetLabel(" Normal ")
            self.fast_toggle.SetForegroundColour('black')
            self.fast_toggle.SetBackgroundColour('yellow')
            self.step = 1
        else:
            # print state
            self.fast_toggle.SetLabel("  Fast  ")
            self.fast_toggle.SetForegroundColour('red')
            self.fast_toggle.SetBackgroundColour('green')
            self.step = 10
示例#52
0
class VelocityPanel(wx.Panel):
    def _init_ctrls(self, prnt):
        # generated method, don't edit
        wx.Panel.__init__(self,
                          id=wxID_RIGHTPANEL,
                          name='VelocityPanel',
                          parent=prnt,
                          pos=wx.Point(8, 416),
                          size=wx.Size(1000, 250),
                          style=wx.TAB_TRAVERSAL)
        self.SetClientSize(wx.Size(1000, 250))
        self.SetBackgroundColour(wx.Colour(0, 0, 255))
        self.Bind(wx.EVT_PAINT, self.OnPolarPanelPaint)

    def __init__(self, parent, id, pos, size, style, name):
        self._init_ctrls(parent)

        self.Times = list()
        self.VelocitiesX = list()
        self.VelocitiesY = list()
        self.Velocities = list()

        self._initFigure()

        ##now finally create the actual plot
        self.x_axes = self.fig.add_subplot(131)  ## the x velocity
        self.y_axes = self.fig.add_subplot(132)  ## the y velocity
        self.m_axes = self.fig.add_subplot(
            133)  ## the magnitude of the velocity
        #self.axes = self.fig.add_axes((0.1,0.1,0.85,0.8))        ##left,bottom,width,height

        self.x_plot = self.x_axes.plot([0, 1], [0, 1], 'b', animated=True)
        self.y_plot = self.y_axes.plot([0, 1], [0, 1], 'b', animated=True)
        self.m_plot = self.m_axes.plot([0, 1], [0, 1], 'r', animated=True)

        self.x_axes.set_title('X', fontsize='10')
        self.y_axes.set_title('Y', fontsize='10')
        self.m_axes.set_title('M', fontsize='10')
        self.x_axes.set_ylabel('Velocity (cm/s)', fontsize='10')
        #self.axes.set_ylabel('x (cm)', fontsize='10')

        ##plot formatting
        self._formatAxes(self.x_axes)
        self._formatAxes(self.y_axes)
        self._formatAxes(self.m_axes)
        #self.axes.set_title('Velocity', fontsize='10')

        self.canvas.draw()
        self.canvas.gui_repaint()

        # save the clean slate background -- everything but the animated line
        # is drawn and saved in the pixel buffer background
        self.background = self.canvas.copy_from_bbox(self.fig.bbox)

    def _initFigure(self):
        ##Create a matplotlib figure/canvas in this panel
        ##the background colour will be the same as the panel
        ##the size will also be the same as the panel
        ##calculate size in inches
        pixels_width, pixels_height = self.GetSizeTuple()
        self.dpi = 96.0
        inches_width = pixels_width / self.dpi
        inches_height = pixels_height / self.dpi

        ##calculate colour in RGB 0 to 1
        colour = self.GetBackgroundColour()
        self.fig = Figure(figsize=(inches_width,inches_height), dpi = self.dpi\
            ,facecolor=(colour.Red()/255.0, colour.Green()/255.0, colour.Blue()/255.0)\
            ,edgecolor=(colour.Red()/255.0, colour.Green()/255.0, colour.Blue()/255.0))

        self.canvas = FigureCanvasWxAgg(self, -1, self.fig)

        self.fig.subplots_adjust(left=0.05, right=0.95, wspace=0.08)

        ##now put everything in a sizer
        sizer = wx.BoxSizer(wx.VERTICAL)
        # This way of adding to sizer allows resizing
        sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
        self.SetSizer(sizer)
        self.Fit()

    def _formatAxes(self, axes):
        """ """
        ticks = numpy.arange(-25, 25 + 5, 5)
        labels = [str(tick) for tick in ticks]  # velocity
        axes.set_yticks(ticks)
        axes.set_yticklabels(labels, fontsize=8)
        ticks = numpy.arange(0, 10 + 1.0, 1.0)  # time
        labels = [str(tick) for tick in ticks]
        axes.set_xticks(ticks)
        axes.set_xticklabels(labels, fontsize=8)

        #if axes == self.m_axes:
        #    self.axes.set_xlabel('time (s)', fontsize='10')
        #self.axes.set_ylabel(' (mm)', fontsize='10')

    def updateData(self, velx, vely, vel):
        """updateData. Updates the data that this panel is displaying.
        """
        self.VelocitiesX.append(velx)
        self.VelocitiesY.append(vely)
        self.Velocities.append(vel)
        timenow = time.time()
        self.Times.append(timenow)
        if timenow - self.Times[0] > 10:
            del self.Times[0]
            del self.VelocitiesX[0]
            del self.VelocitiesY[0]
            del self.Velocities[0]

        self.x_plot[0].set_data(
            numpy.array(self.Times) - self.Times[0], self.VelocitiesX)
        self.y_plot[0].set_data(
            numpy.array(self.Times) - self.Times[0], self.VelocitiesY)
        self.m_plot[0].set_data(
            numpy.array(self.Times) - self.Times[0], self.Velocities)

        # restore the clean slate background
        self.canvas.restore_region(self.background)
        # just draw the animated artist
        self.fig.draw_artist(self.x_plot[0])
        self.fig.draw_artist(self.y_plot[0])
        self.fig.draw_artist(self.m_plot[0])
        # just redraw the axes rectangle
        self.canvas.blit(self.fig.bbox)

    def OnPolarPanelPaint(self, event):
        pass
示例#53
0
class MonitorFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self,
                          parent=None,
                          id=-1,
                          title=__app_name__,
                          pos=(10, 10),
                          size=(1200, 620))
        self.LoadParam()
        self.BuildUI()
        self.InitUiParam()
        self.proc_name_value.SetFocus()
        self.t = wx.Timer(self, TIMER_ID)

    def LoadParam(self):
        self.settings = param.load_param('config.json')
        if 'xmin' not in self.settings:
            self.settings['xmin'] = 0
        if 'xmax' not in self.settings:
            self.settings['xmax'] = self.settings['points']

    def BuildUI(self):
        # ------- config box ------------
        # process name
        self.proc_name_label = wx.StaticText(parent=self,
                                             label='Process Name: ',
                                             style=wx.ALIGN_CENTER)
        self.proc_name_value = wx.TextCtrl(parent=self,
                                           value='',
                                           style=wx.TE_PROCESS_ENTER)
        self.proc_name_box = wx.BoxSizer(wx.HORIZONTAL)
        self.proc_name_box.Add(self.proc_name_label, 1, wx.ALIGN_CENTER, 5, 0)
        self.proc_name_box.Add(self.proc_name_value, 2, wx.ALIGN_CENTER, 5, 0)
        # input response
        self.proc_msg = wx.StaticText(parent=self,
                                      label='',
                                      size=(800, 30),
                                      style=wx.ALIGN_LEFT
                                      | wx.ST_NO_AUTORESIZE)
        # add to config box
        self.configBox = wx.BoxSizer(wx.VERTICAL)
        self.configBox.Add(self.proc_name_box, 1,
                           wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 5, 0)
        self.configBox.Add(self.proc_msg, 1,
                           wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 5, 0)

        # ------- control box ------------
        self.startBtn = wx.Button(parent=self, label="Start", size=(60, 60))
        self.stopBtn = wx.Button(parent=self, label="Stop")
        self.showBtn = wx.Button(parent=self, label="Show")
        self.controlBox = wx.BoxSizer(wx.HORIZONTAL)
        self.controlBox.Add(self.startBtn, 1,
                            wx.ALL | wx.EXPAND | wx.ALIGN_CENTER_VERTICAL, 5,
                            0)
        self.controlBox.Add(self.showBtn, 1,
                            wx.ALL | wx.EXPAND | wx.ALIGN_CENTER_VERTICAL, 5,
                            0)
        self.controlBox.Add(self.stopBtn, 1,
                            wx.ALL | wx.EXPAND | wx.ALIGN_CENTER_VERTICAL, 5,
                            0)

        self.startBtn.Enable()
        self.stopBtn.Disable()

        # ------- tool box(config, control) -------
        self.toolbox = wx.BoxSizer(wx.HORIZONTAL)
        self.toolbox.AddSpacer(20)
        self.toolbox.Add(self.configBox, 5, wx.ALL | wx.ALIGN_CENTER, 5, 0)
        self.toolbox.Add(self.controlBox, 2, wx.ALL | wx.ALIGN_CENTER, 5, 0)
        # ------- track log box -------------------
        self.track_log = wx.TextCtrl(parent=self,
                                     style=wx.TE_AUTO_SCROLL | wx.TE_MULTILINE)
        self.track_log.SetEditable(False)
        self.fig = self.InitPlotUI()
        self.canvas = FigureCanvas(self, wx.ID_ANY, self.fig)
        self.canvas.draw()
        self.bg = self.canvas.copy_from_bbox(self.ax.bbox)
        self.dispbox = wx.BoxSizer(wx.HORIZONTAL)
        self.dispbox.Add(self.track_log, 1, wx.ALL | wx.EXPAND, 5, 5)
        self.dispbox.Add(self.canvas, 0, wx.ALL | wx.EXPAND, 5, 5)
        # ------- main box(tool, tracklog) --------
        self.mainbox = wx.BoxSizer(wx.VERTICAL)
        self.mainbox.Add(self.toolbox, 1, wx.NORMAL, 0, 0)
        self.mainbox.Add(self.dispbox, 0, wx.EXPAND, 5, 5)

        self.SetSizer(self.mainbox)
        self.CenterOnScreen()

        self.startBtn.Bind(wx.EVT_BUTTON, self.OnStartTrack)
        self.stopBtn.Bind(wx.EVT_BUTTON, self.OnStopTrack)
        self.proc_name_value.Bind(wx.EVT_TEXT, self.OnProcInputChanged)
        self.proc_name_value.Bind(wx.EVT_TEXT_ENTER, self.OnStartTrack)
        self.Bind(wx.EVT_ACTIVATE, self.OnWindowActivate)
        wx.EVT_TIMER(self, TIMER_ID, self.onTimer)

    def InitUiParam(self):
        self.proc_name_value.SetValue(self.settings['process_name'])
        self.proc_tracking = None
        self.is_track_running = False

    def OnStartTrack(self, event):
        if self.is_track_running:
            return

        proc_name = self.proc_name_value.GetValue().strip()

        if 0 == len(proc_name):
            msg = 'Please input a process name!'
            dlg = wx.MessageDialog(None, msg, "%s Error" % __app_name__,
                                   wx.ICON_ERROR)
            dlg.ShowModal()
            return None

        if self.proc_tracking is None:
            self.MatchProcName(proc_name)
            if self.proc_tracking is None:
                msg = 'No such process!\nGo on to track %s?' % proc_name
                dlg = wx.MessageDialog(None, msg, "%s Error" % __app_name__,
                                       wx.YES_NO | wx.ICON_QUESTION)
                if dlg.ShowModal() != wx.ID_YES:
                    return None

        # transfer button status
        self.startBtn.Disable()
        self.showBtn.Disable()
        self.stopBtn.Enable()
        self.proc_name_value.Disable()
        # clear log
        self.track_log.SetValue('')
        wx.CallAfter(self.StartTrack, self.proc_tracking,
                     self.proc_name_value.GetValue())

    def update_log(self, disp_data):
        global _log_cache
        _log_cache.append(disp_data)
        if len(_log_cache) >= (1000.0 / self.settings['interval']):
            wx.CallAfter(self.track_log.AppendText,
                         '%s | %.4f MB\n' % (timestamp(), avg(_log_cache)))
            _log_cache = []

    def StartTrack(self, proc, proc_name):
        self.is_track_running = True
        self.t.Start(self.settings['interval'])

    def OnStopTrack(self, event):
        self.startBtn.Enable()
        self.showBtn.Enable()
        self.stopBtn.Disable()
        self.proc_name_value.Enable()
        # stop thread
        self.t.Stop()
        self.is_track_running = False

    def OnWindowActivate(self, event):
        if not self.is_track_running:
            self.MatchProcName(self.proc_name_value.GetValue().strip())

    def OnProcInputChanged(self, event):
        self.MatchProcName(self.proc_name_value.GetValue().strip())

    def MatchProcName(self, pname):
        self.proc_tracking = None
        if 0 == len(pname):
            self.proc_msg.SetLabel('Please input a process name')
            return None
        procs = monitor.get_procs(pname)
        if 0 == len(procs):
            self.proc_msg.SetLabel('Process not exists or AccessDenied')
            return None
        self.proc_tracking = procs[0]
        if len(procs) > 1:
            self.proc_msg.SetLabel('Warning! Multi Processes Match. use %s' %
                                   format_proc(self.proc_tracking))
        else:
            self.proc_msg.SetLabel(format_proc(self.proc_tracking))
        return self.proc_tracking

    def InitPlotUI(self):
        plot_points = self.settings['points']
        fig = Figure(figsize=(9, 5), dpi=100)
        self.ax = fig.add_subplot(111)

        self.ax.set_ylim([self.settings['ymin'], self.settings['ymax']])
        self.ax.set_xlim([self.settings['xmin'], self.settings['xmax']])
        self.ax.set_autoscale_on(False)

        self.ax.set_xticks([])
        self.ax.set_yticks(
            range(self.settings['ymin'], self.settings['ymax'] + 1,
                  self.settings['ystep']))

        self.ax.grid(True)

        self.mem_rss_data = [None] * plot_points
        self.l_mem_rss, = self.ax.plot(range(plot_points),
                                       self.mem_rss_data,
                                       label='Memory(RSS) %')

        # add the legend
        self.ax.legend(loc='upper center',
                       ncol=4,
                       prop=font_manager.FontProperties(size=10))
        return fig

    def onTimer(self, evt):
        """callback function for timer events"""
        # restore the clean background, saved at the beginning
        self.canvas.restore_region(self.bg)
        # get new perf data
        if self.proc_tracking is None:
            proc_name = self.proc_name_value.GetValue().strip()
            self.proc_tracking = monitor.find_proc(proc_name)
        rss_mem = getSizeInMb(monitor.get_rss_mem(self.proc_tracking))
        # update log
        wx.CallAfter(self.update_log, rss_mem)
        # plot
        self.mem_rss_data = self.mem_rss_data[1:] + [rss_mem]
        self.l_mem_rss.set_ydata(self.mem_rss_data)
        self.ax.draw_artist(self.l_mem_rss)
        self.canvas.blit(self.ax.bbox)
class VelocityPanel(wx.Panel):
    def _init_ctrls(self, prnt):
        # generated method, don't edit
        wx.Panel.__init__(self, id=wxID_RIGHTPANEL, name='VelocityPanel',
              parent=prnt, pos=wx.Point(8, 416), size=wx.Size(1000, 250),
              style=wx.TAB_TRAVERSAL)
        self.SetClientSize(wx.Size(1000, 250))
        self.SetBackgroundColour(wx.Colour(0, 0, 255))
        self.Bind(wx.EVT_PAINT, self.OnPolarPanelPaint)

    def __init__(self, parent, id, pos, size, style, name):
        self._init_ctrls(parent)
        
        self.Times = list()
        self.VelocitiesX = list()
        self.VelocitiesY = list()
        self.Velocities = list()
        
        self._initFigure()
        
        ##now finally create the actual plot
        self.x_axes = self.fig.add_subplot(131)                 ## the x velocity
        self.y_axes = self.fig.add_subplot(132)                 ## the y velocity
        self.m_axes = self.fig.add_subplot(133)                 ## the magnitude of the velocity
        #self.axes = self.fig.add_axes((0.1,0.1,0.85,0.8))        ##left,bottom,width,height
        
        self.x_plot = self.x_axes.plot([0,1],[0,1],'b', animated=True)
        self.y_plot = self.y_axes.plot([0,1],[0,1],'b', animated=True)
        self.m_plot = self.m_axes.plot([0,1],[0,1],'r', animated=True)
        
        self.x_axes.set_title('X', fontsize='10')
        self.y_axes.set_title('Y', fontsize='10')
        self.m_axes.set_title('M', fontsize='10')
        self.x_axes.set_ylabel('Velocity (cm/s)', fontsize='10')
        #self.axes.set_ylabel('x (cm)', fontsize='10')

        ##plot formatting
        self._formatAxes(self.x_axes)
        self._formatAxes(self.y_axes)
        self._formatAxes(self.m_axes)
        #self.axes.set_title('Velocity', fontsize='10')
        
        self.canvas.draw()
        self.canvas.gui_repaint()
        
        # save the clean slate background -- everything but the animated line
        # is drawn and saved in the pixel buffer background
        self.background = self.canvas.copy_from_bbox(self.fig.bbox)
        
    def _initFigure(self):
        ##Create a matplotlib figure/canvas in this panel
        ##the background colour will be the same as the panel
        ##the size will also be the same as the panel
        ##calculate size in inches
        pixels_width,pixels_height = self.GetSizeTuple()
        self.dpi = 96.0
        inches_width = pixels_width/self.dpi
        inches_height = pixels_height/self.dpi
        
        ##calculate colour in RGB 0 to 1
        colour = self.GetBackgroundColour()
        self.fig = Figure(figsize=(inches_width,inches_height), dpi = self.dpi\
            ,facecolor=(colour.Red()/255.0, colour.Green()/255.0, colour.Blue()/255.0)\
            ,edgecolor=(colour.Red()/255.0, colour.Green()/255.0, colour.Blue()/255.0))    

        self.canvas = FigureCanvasWxAgg(self, -1, self.fig)

        self.fig.subplots_adjust(left=0.05,right=0.95,wspace=0.08)

        ##now put everything in a sizer
        sizer = wx.BoxSizer(wx.VERTICAL)
        # This way of adding to sizer allows resizing
        sizer.Add(self.canvas, 1, wx.LEFT|wx.TOP|wx.GROW)
        self.SetSizer(sizer)
        self.Fit()
        
    def _formatAxes(self, axes):
        """ """
        ticks = numpy.arange(-25, 25+5, 5)
        labels = [str(tick) for tick in ticks]              # velocity
        axes.set_yticks(ticks)
        axes.set_yticklabels(labels, fontsize=8)
        ticks = numpy.arange(0, 10+1.0, 1.0)                # time
        labels = [str(tick) for tick in ticks]              
        axes.set_xticks(ticks)
        axes.set_xticklabels(labels,fontsize=8)
        
        #if axes == self.m_axes:
        #    self.axes.set_xlabel('time (s)', fontsize='10')
        #self.axes.set_ylabel(' (mm)', fontsize='10')
        
        
    
    def updateData(self, velx, vely, vel):
        """updateData. Updates the data that this panel is displaying.
        """
        self.VelocitiesX.append(velx)
        self.VelocitiesY.append(vely)
        self.Velocities.append(vel)
        timenow = time.time()
        self.Times.append(timenow)
        if timenow - self.Times[0] > 10:
            del self.Times[0]
            del self.VelocitiesX[0]
            del self.VelocitiesY[0]
            del self.Velocities[0]
        
        self.x_plot[0].set_data(numpy.array(self.Times) - self.Times[0], self.VelocitiesX)
        self.y_plot[0].set_data(numpy.array(self.Times) - self.Times[0], self.VelocitiesY)
        self.m_plot[0].set_data(numpy.array(self.Times) - self.Times[0], self.Velocities)
        
        # restore the clean slate background
        self.canvas.restore_region(self.background)
        # just draw the animated artist
        self.fig.draw_artist(self.x_plot[0])
        self.fig.draw_artist(self.y_plot[0])
        self.fig.draw_artist(self.m_plot[0])
        # just redraw the axes rectangle
        self.canvas.blit(self.fig.bbox)

    def OnPolarPanelPaint(self, event):
        pass
示例#55
0
class LeftGraphBottom(wx.Panel):
    def __init__(self, parent, statusbar):
        wx.Panel.__init__(self, parent)
        self.statusbar = statusbar
        """
        An polygon editor.
        Key-bindings
          't' toggle vertex markers on and off.  When vertex markers are on,
              you can move them, delete them
          'd' delete the vertex under point
          'i' insert a vertex at point.  You must be within epsilon of the
              line connecting two existing vertices
        """
        self.fig = Figure((4.0, 3.0))
        self.canvas = FigCanvas(self, -1, self.fig)
        self.ax = self.fig.add_subplot(111)
        """ subplots_adjust(bottom=0.14): permet d'ajuster la taille du canevas
        en prenant en compte la legende
        sinon la legende est rognee"""
        self.fig.subplots_adjust(bottom=0.20)
        self.ax.set_ylabel("DW", fontdict=font)
        self.ax.set_xlabel("Depth ($\AA$)", fontdict=font)
        self.toolbar = NavigationToolbar(self.canvas)
        self.toolbar.Hide()
        self.fig.patch.set_facecolor(colorBackgroundGraph)

        self._ind = None  # the active vert
        self.poly = []
        self.line = []
        self.showverts = True
        self.epsilon = 5  # max pixel distance to count as a vertex hit
        self.new_coord = {'indice': 0, 'x': 0, 'y': 0}
        self.modelpv = False

        xs = [-1]
        ys = [-1]
        poly = Polygon(list(zip(xs, ys)),
                       ls='solid',
                       fill=False,
                       closed=False,
                       animated=True)
        self.ax.set_xlim([0, 1])
        self.ax.set_ylim([0, 1])
        self.c_dw = ""
        self.l_dw = ""

        self.canvas.mpl_connect('draw_event', self.draw_callback)
        self.canvas.mpl_connect('button_press_event',
                                self.button_press_callback)
        self.canvas.mpl_connect('button_release_event',
                                self.button_release_callback)
        self.canvas.mpl_connect('motion_notify_event',
                                self.motion_notify_callback)
        self.canvas.mpl_connect('scroll_event', self.scroll_callback)
        self.canvas.mpl_connect('motion_notify_event',
                                self.on_update_coordinate)

        mastersizer = wx.BoxSizer(wx.VERTICAL)
        mastersizer.Add(self.canvas, 1, wx.ALL | wx.EXPAND)
        mastersizer.Add(self.toolbar, 0, wx.ALL)

        pub.subscribe(self.draw_c, pubsub_draw_graph)
        pub.subscribe(self.OnDrawGraph, pubsub_Draw_DW)
        pub.subscribe(self.scale_manual, pubsub_Update_Scale_DW)
        pub.subscribe(self.on_color, pubsub_Graph_change_color_style)

        self.on_color()
        self.draw_c(poly, xs, ys)

        self.SetSizer(mastersizer)
        self.Fit()

    def on_color(self):
        a = P4Rm()
        self.c_dw = a.DefaultDict['c_dw']
        self.l_dw = a.DefaultDict['l_dw']
        self.c_bkg = a.DefaultDict['c_graph_background']

    def OnDrawGraph(self, b=None):
        a = P4Rm()
        self.modelpv = a.modelPv
        self.ax.clear()
        if a.AllDataDict['damaged_depth'] == 0:
            self.ax.text(0.5,
                         0.5,
                         "No Damage",
                         size=30,
                         rotation=0.,
                         ha="center",
                         va="center",
                         bbox=dict(
                             boxstyle="round",
                             ec='red',
                             fc=self.c_dw,
                         ))
            x_dwp = [-1]
            y_dwp = [-1]
            xs = [-1]
            ys = [-1]
            self.ax.set_xticklabels([])
            self.ax.set_yticklabels([])
            self.ax.set_xlim([0, 1])
            self.ax.set_ylim([0, 1])
        else:
            if b != 2:
                x_dwp = a.ParamDict['x_dwp']
                y_dwp = a.ParamDict['DW_shifted']
                xs = deepcopy(a.ParamDict['depth'])
                ys = deepcopy(a.ParamDict['DW_i'])
                P4Rm.DragDrop_DW_x = x_dwp
                P4Rm.DragDrop_DW_y = y_dwp
                ymin = min(ys) - min(ys) * 10 / 100
                ymax = max(ys) + max(ys) * 10 / 100
                self.ax.set_ylim([ymin, ymax])
                if a.ParamDict['x_dwp'] != "":
                    self.ax.set_xlim(
                        [a.ParamDict['depth'][-1], a.ParamDict['depth'][0]])
            elif b == 2:
                x_dwp = [-1]
                y_dwp = [-1]
                xs = [-1]
                ys = [-1]
                self.ax.set_xlim([0, 1])
                self.ax.set_ylim([0, 1])
        poly = Polygon(list(zip(x_dwp, y_dwp)),
                       lw=0,
                       ls='solid',
                       color=self.c_dw,
                       fill=False,
                       closed=False,
                       animated=True)
        if self.modelpv is True:
            P4Rm.ParamDict['dwp_pv_backup'] = a.ParamDict['dwp']
        self.draw_c(poly, xs, ys)

    def draw_c(self, data, x, y):
        self.ax.plot(x, y, color=self.c_dw, lw=2., ls='solid')
        self.ax.set_ylabel("DW", fontdict=font)
        self.ax.set_xlabel("Depth ($\AA$)", fontdict=font)
        if LooseVersion(matplotlib_vers) < LooseVersion("2.0.0"):
            self.ax.set_axis_bgcolor(self.c_bkg)
        else:
            self.ax.set_facecolor(self.c_bkg)
        self.poly = data
        xs, ys = zip(*self.poly.xy)
        self.line = Line2D(xs,
                           ys,
                           lw=0,
                           ls='solid',
                           color=self.c_dw,
                           marker='.',
                           ms=32,
                           markerfacecolor=self.c_dw,
                           markeredgecolor='k',
                           mew=1.0)
        self.ax.add_line(self.line)
        self.ax.add_patch(self.poly)
        self.canvas.SetCursor(Cursor(wx.CURSOR_HAND))
        self.canvas.draw()

    def draw_callback(self, event):
        self.background = self.canvas.copy_from_bbox(self.ax.bbox)
        self.ax.draw_artist(self.poly)
        self.ax.draw_artist(self.line)
        self.canvas.blit(self.ax.bbox)

    def get_ind_under_point(self, event):
        'get the index of the vertex under point if within epsilon tolerance'

        # display coords
        xy = np.asarray(self.poly.xy)
        xyt = self.poly.get_transform().transform(xy)
        xt, yt = xyt[:, 0], xyt[:, 1]
        d = np.sqrt((xt - event.x)**2 + (yt - event.y)**2)
        indseq = np.nonzero(np.equal(d, np.amin(d)))[0]
        ind = indseq[0]

        if d[ind] >= self.epsilon:
            ind = None
        return ind

    def button_press_callback(self, event):
        'whenever a mouse button is pressed'
        a = P4Rm()
        val = a.xrd_graph_loaded
        if self.canvas.HasCapture():
            self.canvas.ReleaseMouse()
            if not self.showverts:
                return
            if event.inaxes is None:
                return
            if event.button != 1:
                return
            if val == 1:
                self._ind = self.get_ind_under_point(event)
                self.new_coord['indice'] = self._ind

    def button_release_callback(self, event):
        'whenever a mouse button is released'
        a = P4Rm()
        val = a.xrd_graph_loaded
        if self.canvas.HasCapture():
            self.canvas.ReleaseMouse()
        else:
            if not self.showverts:
                return
            if event.button != 1:
                return
            if self.new_coord['indice'] is not None and val == 1:
                a = P4Rm()
                temp_1 = self.new_coord['y']
                temp_2 = self.new_coord['x']
                P4Rm.DragDrop_DW_y[self.new_coord['indice']] = temp_1
                P4Rm.DragDrop_DW_x[self.new_coord['indice']] = temp_2
                if a.AllDataDict['model'] == 0:
                    temp = self.new_coord['y']
                    P4Rm.DragDrop_DW_y[self.new_coord['indice']] = temp
                    temp = [
                        dw * scale for dw, scale in zip(
                            a.DragDrop_DW_y, a.ParamDict['scale_dw'])
                    ]
                    temp = [float(format(value, '.8f')) for value in temp]
                    temp2 = np.concatenate([temp, [a.ParamDict['dw_out']]])
                    P4Rm.ParamDict['dwp'] = deepcopy(temp2)
                    P4Rm.ParamDictbackup['dwp'] = deepcopy(temp2)
                elif a.AllDataDict['model'] == 1:
                    temp = self.new_coord['y']
                    P4Rm.DragDrop_DW_y[self.new_coord['indice']] = temp
                    temp = [
                        dw * scale for dw, scale in zip(
                            a.DragDrop_DW_y, a.ParamDict['scale_dw'])
                    ]
                    temp = [float(format(value, '.8f')) for value in temp]
                    temp2 = np.concatenate([[a.ParamDict['dw_out'][0]], temp,
                                            [a.ParamDict['dw_out'][1]]])
                    P4Rm.ParamDict['dwp'] = deepcopy(temp2)
                    P4Rm.ParamDictbackup['dwp'] = deepcopy(temp2)
                elif a.AllDataDict['model'] == 2:
                    t_temp = a.ParamDict['depth'] + a.ParamDict['z']
                    t = t_temp[0]
                    dwp_temp = range(7)
                    dwp_temp[0] = a.DragDrop_DW_y[0]
                    dwp_temp[1] = 1 - a.DragDrop_DW_x[0] / t
                    dwp_temp[2] = 2 * (-1 + a.ParamDict['dwp'][1] +
                                       a.DragDrop_DW_x[1] / t)
                    dwp_temp[3] = 2 * (1 - a.ParamDict['dwp'][1] -
                                       1 * a.DragDrop_DW_x[2] / t)
                    dwp_temp[4] = a.ParamDict['dwp'][4]
                    dwp_temp[5] = a.ParamDict['dwp'][5]
                    dwp_temp[6] = a.DragDrop_DW_y[3]
                    P4Rm.ParamDict['dwp'] = deepcopy(dwp_temp)
                    P4Rm.ParamDictbackup['dwp'] = deepcopy(dwp_temp)
                    P4Rm.ParamDict['dwp_pv'] = deepcopy(dwp_temp)
                pub.sendMessage(pubsub_Update_Fit_Live)
            self._ind = None

    def scroll_callback(self, event):
        if not event.inaxes:
            return
        a = P4Rm()
        if event.key == 'u' and event.button == 'up':
            temp = a.ParamDict['DW_multiplication'] + 0.01
            P4Rm.ParamDict['DW_multiplication'] = temp
        elif event.key == 'u' and event.button == 'down':
            temp = a.ParamDict['DW_multiplication'] - 0.01
            P4Rm.ParamDict['DW_multiplication'] = temp
        P4Rm.ParamDict['dwp'] = multiply(a.ParamDictbackup['dwp'],
                                         a.ParamDict['DW_multiplication'])
        pub.sendMessage(pubsub_Re_Read_field_paramters_panel, event=event)

    def scale_manual(self, event, val=None):
        a = P4Rm()
        if val is not None:
            P4Rm.ParamDict['DW_multiplication'] = val
        P4Rm.ParamDict['dwp'] = multiply(a.ParamDict['dwp'],
                                         a.ParamDict['DW_multiplication'])
        pub.sendMessage(pubsub_Re_Read_field_paramters_panel, event=event)

    def motion_notify_callback(self, event):
        'on mouse movement'
        a = P4Rm()
        if a.AllDataDict['damaged_depth'] == 0:
            return
        if not self.showverts:
            return
        if self._ind is None:
            return
        if event.inaxes is None:
            return
        if event.button != 1:
            return

        if self.modelpv is True:
            if self._ind == 0:
                y = event.ydata
                x = event.xdata
            elif self._ind == 1 or self._ind == 2:
                y = a.DragDrop_DW_y[self.new_coord['indice']]
                x = event.xdata
            else:
                x = a.DragDrop_DW_x[self.new_coord['indice']]
                y = event.ydata
        else:
            y = event.ydata
            x = a.DragDrop_DW_x[self.new_coord['indice']]

        self.new_coord['x'] = x
        self.new_coord['y'] = y
        self.poly.xy[self._ind] = x, y
        self.line.set_data(zip(*self.poly.xy))

        self.canvas.restore_region(self.background)
        self.ax.draw_artist(self.poly)
        self.ax.draw_artist(self.line)
        self.canvas.blit(self.ax.bbox)

    def on_update_coordinate(self, event):
        if event.inaxes is None:
            self.statusbar.SetStatusText(u"", 1)
            self.statusbar.SetStatusText(u"", 2)
        else:
            a = P4Rm()
            if not a.AllDataDict['damaged_depth'] == 0:
                x, y = event.xdata, event.ydata
                xfloat = round(float(x), 2)
                yfloat = round(float(y), 2)
                self.statusbar.SetStatusText(u"x = " + str(xfloat), 1)
                self.statusbar.SetStatusText(u"y = " + str(yfloat), 2)
                xy = np.asarray(self.poly.xy)
                xyt = self.poly.get_transform().transform(xy)
                xt, yt = xyt[:, 0], xyt[:, 1]
                d = np.sqrt((xt - event.x)**2 + (yt - event.y)**2)
                indseq = np.nonzero(np.equal(d, np.amin(d)))[0]
                ind = indseq[0]

                if d[ind] >= self.epsilon:
                    self.canvas.SetCursor(Cursor(wx.CURSOR_ARROW))
                elif d[ind] <= self.epsilon:
                    self.canvas.SetCursor(Cursor(wx.CURSOR_HAND))
示例#56
0
class MyPlot(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, -1)

        self.fig = None
        self.canvas = None
        self.ax = None
        self.background = None
        self.lines = []
        self._doRePlot = True

        self.foo = 1
        self.t = time.time()
        self.blit_time = 0
        self.y = numpy.cos(numpy.arange(0.0, 1.0, 0.1))

        self.ylim = None
        self.autolim = None
        self.span = 500
        self.begin = 0
        self.channels = []

        self._SetSize()

        self.Bind(wx.EVT_IDLE, self._onIdle)
        self.Bind(wx.EVT_SIZE, self._onSize)
        self._resizeFlag = True

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.canvas, 1, wx.GROW)
        self.SetSizer(sizer)
        self.canvas.Show()

    def addChannel(self, channel):
        self.channels.append(channel)

    def setTimespan(self, span):
        self.span = span

    def setYlim(self, ymin, ymax):
        self.ylim = [ymin, ymax]

    def _resizeCreateContent(self):
        '''Resize graph according to user input and initialize plots'''

        self.lines = []
        for c in self.channels:
            data = c.getNext()
            line, = self.ax.plot(data[0], data[1], animated=True)
            self.lines.append(line)
        gca = self.fig.gca()
        #TODO: add an auto mode here
        if self.ylim:
            gca.set_ylim(self.ylim)
        else:
            if self.autolim:
                diff = self.autolim[1] - self.autolim[0]
                gca.set_ylim([
                    self.autolim[0] - 0.1 * diff, self.autolim[1] + 0.1 * diff
                ])
            else:
                gca.set_ylim([-1, 1])
        gca.set_xlim([self.begin, (self.begin + self.span)])
        self.ax.grid()
        #self.fig.clear()

        self.canvas.draw()
        self.background = None
        print 'content'
        self._doRePlot = False

    def _createGraphics(self):
        """Reallocate new figure and take care of panel resizing issues"""
        self.fig = Figure()
        self.canvas = FigureCanvas(self, -1, self.fig)
        self.ax = self.fig.add_subplot(111)

        self.ax._cachedRenderer = self.canvas.get_renderer()

    def _onSize(self, evt):
        self._resizeFlag = True

    def _onIdle(self, event):
        event.RequestMore(True)
        if self._resizeFlag:
            self._resizeFlag = False
            self._SetSize()
        self.draw_plot()
        #if self.foo > 2000:
        #u=time.time()
        #print self.foo/(u-self.t), self.blit_time/(u-self.t)
        #exit(0)

    def _SetSize(self, pixels=None):
        if not pixels:
            pixels = self.GetClientSize()
        self._createGraphics()
        self.canvas.SetSize(pixels)

        self.fig.set_size_inches(pixels[0] / self.fig.get_dpi(),
                                 pixels[1] / self.fig.get_dpi(),
                                 forward=True)
        self._doRePlot = True

    def draw_plot(self):
        if self._doRePlot:
            self._resizeCreateContent()
        if self.background is None:
            self.background = self.canvas.copy_from_bbox(self.ax.bbox)
        self.foo += 1
        #self.y = numpy.cos(numpy.arange(0.0,1.0,0.1)+self.foo*0.1)
        # Optimization on the blitting: we compute the box where the changes happen
        changes_box = None

        for i in range(len(self.lines)):
            data = self.channels[i].getNext()

            if len(data[1]) > 0:
                if self.autolim:
                    print self.autolim[0], data[1], self.autolim[1]
                    self.autolim = [ min(self.autolim[0], min(data[1])), \
                        max(self.autolim[1], max(data[1])) ]
                else:
                    self.autolim = [min(data[1]), min(data[1])]

                if changes_box is None:
                    changes_box = Bbox.unit()
                print '>>>>>>>>'
                print data[0], data[1]
                changes_box.update_from_data(numpy.array(data[0]), \
                        numpy.array(data[1]), ignore=changes_box.is_unit())

                if not self._doRePlot and len(data[0]) > 0:
                    end = data[0][-1]

                    if end > self.begin + self.span:
                        self.begin += self.span
                        self._doRePlot = True
                        print 'do replot'
                self.lines[i].set_data(data[0], data[1])
            else:
                self.lines[i].set_data([], [])

        if not changes_box:
            return
        #self.canvas.restore_region(self.background)
        for line in self.lines:
            self.ax.draw_artist(line)
            #print line.get_transform()
            tr = line.get_transform()

        changes_box_inframe = changes_box.transformed(tr)

        box_padding = 5
        (x, y, l, w) = changes_box_inframe.bounds
        changes_box_inframe = Bbox.from_bounds(x-box_padding, \
            y-box_padding, l+2*box_padding, w+2*box_padding)

        #print
        t0 = time.time()
        self.canvas.blit(None)
        #self.canvas.blit(changes_box_inframe)
        self.blit_time += time.time() - t0