class mode_panel(wx.Panel): def __init__(self, *args, **kwds): # begin wxGlade: mode_panel.__init__ kwds["style"] = wx.TAB_TRAVERSAL wx.Panel.__init__(self, *args, **kwds) self.__set_properties() self.__do_layout() # end wxGlade self.figure = Figure(figsize=(6,4), dpi=80) self.axes_q = self.figure.add_subplot(211) self.axes_real_q = self.figure.add_subplot(212) self.canvas = FigureCanvas(self, wx.ID_ANY, self.figure) self.axes_q.set_autoscale_on(False) self.axes_q.set_xlim([0,100]) self.axes_q.set_ylim([0,1]) self.axes_q.set_xticks(range(0,101,100)) self.axes_real_q.set_autoscale_on(False) self.axes_real_q.set_xlim([0,100]) self.axes_real_q.set_ylim([0,1]) self.axes_real_q.set_xticks(range(0,101,5)) self.axes_real_q.set_yticks(range(0,2,1)) self.prob_q0 = [None] * 100 self.prob_q1 = [None] * 100 self.real_q = [None] * 100 self.real_q_up2now = [None]*100 self.q_file = open('dis_states') for i in range(100): self.real_q[i] = float(self.q_file.readline()) self.q_file.close() self.l_prob_q0, = self.axes_q.plot(range(100), self.prob_q0, 'x', label='probability of mode 0') #plot return one element tuple self.l_prob_q1, = self.axes_q.plot(range(100), self.prob_q1, 'x', label='probability of mode 1') self.l_real_q, = self.axes_real_q.plot(range(100), self.real_q_up2now,'x') self.axes_q.legend(loc='upper center', ncol=2, prop=font_manager.FontProperties(size=10)) self.axes_q.set_title('estimated probabilities of modes') self.axes_real_q.set_title('ture mode') self.axes_real_q.set_xlabel('time (s)') self.canvas.draw() self.bg_q = self.canvas.copy_from_bbox(self.axes_q.bbox) self.bg_real_q = self.canvas.copy_from_bbox(self.axes_real_q.bbox) def __set_properties(self): # begin wxGlade: mode_panel.__set_properties pass # end wxGlade def __do_layout(self): # begin wxGlade: mode_panel.__do_layout pass
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)
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
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)
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)
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()
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)
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()
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
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)
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)
class DemoPanel1(wx.Panel): def __init__(self, *args, **kwds): # begin wxGlade: DemoPanel1.__init__ kwds["style"] = wx.TAB_TRAVERSAL wx.Panel.__init__(self, *args, **kwds) self.__set_properties() self.__do_layout() # end wxGlade self.figure = Figure(figsize=(6,4), dpi=80) self.axes = self.figure.add_subplot(111) self.canvas = FigureCanvas(self, wx.ID_ANY, self.figure) self.axes.set_autoscale_on(False) self.axes.set_xlim([0,100]) self.axes.set_ylim([-30,30]) self.axes.set_xticks(range(0,101,5)) self.axes.set_yticks(range(-30,31,5)) self.exp_x = [None] * 100 self.percentile_x_95 = [None] * 100 self.percentile_x_5 = [None] * 100 self.real_x = [None] * 100 x_file = open('test_data_latent_state') for i in range(100): self.real_x[i] = float(x_file.readline()) x_file.close() self.l_exp_x, = self.axes.plot(range(100), self.exp_x, label='mean') #plot return one element tuple self.l_real_x, = self.axes.plot(range(100), self.real_x, label='real value') self.l_percentile_x_95, = self.axes.plot(range(100), self.percentile_x_95, label='95% percentile') self.l_percentile_x_5, = self.axes.plot(range(100), self.percentile_x_5, label='5% percentile') self.axes.legend(loc='upper center', ncol=4, prop=font_manager.FontProperties(size=10)) self.axes.set_title('latent state') self.axes.set_xlabel('time (s)') self.canvas.draw() self.bg = self.canvas.copy_from_bbox(self.axes.bbox) def __set_properties(self): # begin wxGlade: DemoPanel1.__set_properties pass # end wxGlade def __do_layout(self): # begin wxGlade: DemoPanel1.__do_layout pass
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)
class PlotFigure(wx.Frame): def __init__(self): wx.Frame.__init__(self,None,-1,"Cpu Status Monitor",size=(800,600)) #button和label都建立在Panel上 panel = wx.Panel(self,-1) #初始化label.输入框.按钮 self.IPLabel = wx.StaticText(panel,-1,"IP Address:") self.IPText = wx.TextCtrl(panel,-1,"192.168.150.46",size=(100,-1)) self.portLabel = wx.StaticText(panel,-1,"Port:",) self.portText = wx.TextCtrl(panel,-1,"9876",size=(100,-1)) self.button = wx.Button(panel,-1,"Start") self.button_record = False #初始化sizer对象 sizer = wx.FlexGridSizer(cols=5,hgap=6,vgap=6) sizer.AddMany([self.IPLabel,self.IPText,self.portLabel,self.portText,self.button]) panel.SetSizer(sizer) #事件绑定 self.Bind(wx.EVT_BUTTON,self.OnClick,self.button) #初始化canvas self.fig = Figure((8,6),100) self.canvas = FigureCanvas(self,-1,self.fig) self.ax = self.fig.add_subplot(221) self.ax.set_ylim([0,100]) self.ax.set_xlim([0,POINTS]) self.ax.set_autoscale_on(True) 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="User %") 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) def OnClick(self,event): exit()
class DemoPanel3(wx.Panel): def __init__(self, *args, **kwds): # begin wxGlade: DemoPanel3.__init__ kwds["style"] = wx.TAB_TRAVERSAL wx.Panel.__init__(self, *args, **kwds) self.__set_properties() self.__do_layout() # end wxGlade self.figure = Figure(figsize=(6,4), dpi=80) self.axes = self.figure.add_subplot(111) self.canvas = FigureCanvas(self, wx.ID_ANY, self.figure) self.axes.set_autoscale_on(False) self.axes.set_xlim([0,100]) self.axes.set_ylim([-5,30]) self.axes.set_xticks(range(0,101,5)) self.axes.set_yticks(range(-5,31,5)) self.data = [None] * 100 self.data_up2_now = [None] * 100 data_file = open('test_data') for i in range(100): self.data[i] = float(data_file.readline()) data_file.close() self.axes.set_title('observations') self.axes.set_xlabel('time (s)') self.l_data, = self.axes.plot(range(100), self.data_up2_now, 'kx') self.bg = self.canvas.copy_from_bbox(self.axes.bbox) def __set_properties(self): # begin wxGlade: DemoPanel3.__set_properties pass # end wxGlade def __do_layout(self): # begin wxGlade: DemoPanel3.__do_layout pass
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 pnlPlotter(wx.Panel): ### Class constants N_PLOTTER = 5 # __T_RANGE = 30 # [s] __T_RANGE = 31 # [s] __PLOT_SKIP = 9 ### T.B.REFAC. ### # __PLOT_SKIP = 39 ### T.B.REFAC. ### def __init__(self, parent): super().__init__(parent, wx.ID_ANY) # shere arguments within the class self.parent = parent self.__PLOT_COUNT = self.__PLOT_SKIP ### T.B.REFAC. ### # handle exception # self.N_PLOTTER = max(1, min(5, self.N_PLOTTER)) self.loadConfig() self.configure() ### layout = wx.GridBagSizer() layout.Add(window=self.canvas, pos=(0, 0), border=10) self.SetSizer(layout) ### Bind events # - timer to refresh time-history pane self.tmrRefresh = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.OnTimerRefresh, self.tmrRefresh) self.tmrRefresh.Start(RATE_REFLESH_PLOTTER) # Event handler: EVT_TIMER def OnTimerRefresh(self, event): # skip refresh when TLM NOT active if self.parent.F_TLM_IS_ACTIVE == False: return None ### update data set for plot # - update plot points by appending latest values self.x_series = np.append(self.x_series, self.parent.dictTlmLatestValues['GSE time']) for i in range(self.N_PLOTTER): self.y_series = np.append( self.y_series, self.parent.dictTlmLatestValues[ self.dictPlotterAttr[i]['item']]) # for debug # print(f'GUI PLT: append latest values {df_tmp.iloc[-1,self.index_x]}') # print(f'GUI PLT: x_series = {self.x_series}') # print(f'GUI PLT: y_series = {self.y_series}') # - determine time max & min self.t_max = self.x_series[-1] self.t_min = self.t_max - self.__T_RANGE # print(f'GUI PLT: t_max = {self.t_max}, t_min = {self.t_min}') # - delete plot points out of the designated time range while self.x_series[0] < self.t_min: self.x_series = np.delete(self.x_series, 0) self.y_series = np.delete(self.y_series, np.s_[0:self.N_PLOTTER]) # print('GUI PLT: a member of 'x_series' is out of the range') ### T.B.REFAC. ### # skip redraw if self.__PLOT_COUNT != self.__PLOT_SKIP: self.__PLOT_COUNT += 1 return None self.__PLOT_COUNT = 0 ### refresh plotter self.lines = [] for i in range(self.N_PLOTTER): # delete x axis and lines by restroring canvas self.canvas.restore_region(self.backgrounds[i]) # clear axes # self.axes[i].cla() # update axex attributions self.axes[i].set_xlim([self.t_min, self.t_max]) # self.axes[i].set_ylim([self.PlotterAttr[i]['y_min'], self.PlotterAttr[i]['y_max']]) # self.axes[i].set_ylabel(self.PlotterAttr[i]['y_label']) # self.axes[i].axhline(y=self.PlotterAttr[i]['alart_lim_l'], xmin=0, xmax=1, color='FIREBRICK') # self.axes[i].axhline(y=self.PlotterAttr[i]['alart_lim_u'], xmin=0, xmax=1, color='FIREBRICK') # self.axes[i].axhline(y=self.PlotterAttr[i]['alart_lim_l'], xmin=0, xmax=1, color='RED') # self.axes[i].axhline(y=self.PlotterAttr[i]['alart_lim_u'], xmin=0, xmax=1, color='RED') # update plot # NOTE: lines become iterrable hereafter self.lines.append( self.axes[i].plot(self.x_series, self.y_series[i::self.N_PLOTTER], color='LIME')[0]) # reflect updates in lines self.axes[i].draw_artist(self.lines[i]) # redraw and show updated canvas for i in range(self.N_PLOTTER): self.fig.canvas.blit(self.axes[i].bbox) # redraw and show updated canvas # self.fig.canvas.draw() self.fig.canvas.flush_events() # print("GUI PLT: redraw plots...") # Load configurations from external files def loadConfig(self): # Prepare hash: Plotter# -> {Plotter Attributions} self.dictPlotterAttr = {} for i in range(self.N_PLOTTER): dict_tmp = {} # search throughout items for strItemName in self.parent.dictTlmItemAttr: # skip if self.parent.dictTlmItemAttr[strItemName]['plot #'] != i: continue dict_tmp['item'] = strItemName dict_tmp['unit'] = str( self.parent.dictTlmItemAttr[strItemName]['unit']) dict_tmp['y_label'] = dict_tmp['item'] + ' [' + dict_tmp[ 'unit'] + ']' dict_tmp['y_min'] = float( self.parent.dictTlmItemAttr[strItemName]['y_min']) dict_tmp['y_max'] = float( self.parent.dictTlmItemAttr[strItemName]['y_max']) dict_tmp['alart_lim_l'] = float( self.parent.dictTlmItemAttr[strItemName]['alert_lim_l']) dict_tmp['alart_lim_u'] = float( self.parent.dictTlmItemAttr[strItemName]['alert_lim_u']) break self.dictPlotterAttr[i] = dict_tmp # Configure appearance for plotters to display time histories def configure(self): # initialize data set for plot self.x_series = np.empty(0) self.y_series = np.empty(0) # generate empty matplotlib Fugure # self.fig = Figure() self.fig = Figure(figsize=(6, 9.7)) # register Figure with matplotlib Canvas self.canvas = FigureCanvasWxAgg(self, wx.ID_ANY, self.fig) ### prepare axes # - generate subplots containing axes in Figure # NOTE: axes become iterrable hereafter self.axes = [] for i in range(self.N_PLOTTER): self.axes.append(self.fig.add_subplot(self.N_PLOTTER, 1, i + 1)) # - set limit for x axis # t_min = -30 t_min = -self.__T_RANGE self.axes[i].set_xlim([t_min, t_min + self.__T_RANGE]) # - set label for x axis self.axes[i].set_xlabel('time [s]') # - set limit for y axis self.axes[i].set_ylim([ self.dictPlotterAttr[i]['y_min'], self.dictPlotterAttr[i]['y_max'] ]) # - set label for y axis self.axes[i].set_ylabel(self.dictPlotterAttr[i]['y_label']) # tentatively draw canvas without plot points to save as background self.canvas.draw() # save the empty canvas as background # NOTE: backgrounds become iterrable hereafter self.backgrounds = [] for i in range(self.N_PLOTTER): self.backgrounds.append( self.canvas.copy_from_bbox(self.axes[i].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)))
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 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) )
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)
class ChartPanel(wx.Panel): index_x = 1 t_range = 30 # [s] n_plot = 5 sensor_type = ['Time [s]', 'P [MPa]', 'T [K]', 'IMU', 'House Keeping'] col_value = [6, 8, 8, 9, 8] def __init__(self, parent, reflesh_time_graph, reflesh_time_value): super().__init__(parent, wx.ID_ANY) self.configReader() self.flag_temp = True self.valueGenerator() self.chartGenerator() # layout time history pane self.layout = wx.FlexGridSizer(rows=1, cols=2, gap=(20, 0)) self.layout.Add(self.canvas, flag=wx.EXPAND) self.layout.Add(self.layout_Value, flag=wx.ALIGN_CENTER_HORIZONTAL) self.SetSizer(self.layout) # set refresh timer for time history pane self.timer_reload_graph = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.graphReloader, self.timer_reload_graph) self.timer_reload_graph.Start(reflesh_time_graph) # set refresh timer for current value pane self.timer_reload_value = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.valueReloader, self.timer_reload_value) self.timer_reload_value.Start(reflesh_time_value) def configReader(self): # load smt data config self.df_cfg_tlm = th_smt.smt.df_cfg.copy() self.df_cfg_tlm.reset_index() df_cfg_plot_tmp = pd.read_excel('./config_plot.xlsx', sheet_name='smt') self.df_cfg_plot = df_cfg_plot_tmp.dropna(how='all') self.index_plot = [self.df_cfg_plot['ID'][self.df_cfg_plot['plot_1'].astype(bool)].astype(int).iat[0], self.df_cfg_plot['ID'][self.df_cfg_plot['plot_2'].astype(bool)].astype(int).iat[0], self.df_cfg_plot['ID'][self.df_cfg_plot['plot_3'].astype(bool)].astype(int).iat[0], self.df_cfg_plot['ID'][self.df_cfg_plot['plot_4'].astype(bool)].astype(int).iat[0], self.df_cfg_plot['ID'][self.df_cfg_plot['plot_5'].astype(bool)].astype(int).iat[0]] print(self.index_plot) self.item_plot = [self.df_cfg_plot['item'][self.df_cfg_plot['plot_1'].astype(bool)].iat[0], self.df_cfg_plot['item'][self.df_cfg_plot['plot_2'].astype(bool)].iat[0], self.df_cfg_plot['item'][self.df_cfg_plot['plot_3'].astype(bool)].iat[0], self.df_cfg_plot['item'][self.df_cfg_plot['plot_4'].astype(bool)].iat[0], self.df_cfg_plot['item'][self.df_cfg_plot['plot_5'].astype(bool)].iat[0]] print(self.item_plot) self.unit_plot = [self.df_cfg_plot['unit'][self.df_cfg_plot['plot_1'].astype(bool)].iat[0], self.df_cfg_plot['unit'][self.df_cfg_plot['plot_2'].astype(bool)].iat[0], self.df_cfg_plot['unit'][self.df_cfg_plot['plot_3'].astype(bool)].iat[0], self.df_cfg_plot['unit'][self.df_cfg_plot['plot_4'].astype(bool)].iat[0], self.df_cfg_plot['unit'][self.df_cfg_plot['plot_5'].astype(bool)].iat[0]] print(self.unit_plot) self.y_min_plot = [self.df_cfg_plot['y_min'][self.df_cfg_plot['plot_1'].astype(bool)].iat[0], self.df_cfg_plot['y_min'][self.df_cfg_plot['plot_2'].astype(bool)].iat[0], self.df_cfg_plot['y_min'][self.df_cfg_plot['plot_3'].astype(bool)].iat[0], self.df_cfg_plot['y_min'][self.df_cfg_plot['plot_4'].astype(bool)].iat[0], self.df_cfg_plot['y_min'][self.df_cfg_plot['plot_5'].astype(bool)].iat[0]] print(self.y_min_plot) self.y_max_plot = [self.df_cfg_plot['y_max'][self.df_cfg_plot['plot_1'].astype(bool)].iat[0], self.df_cfg_plot['y_max'][self.df_cfg_plot['plot_2'].astype(bool)].iat[0], self.df_cfg_plot['y_max'][self.df_cfg_plot['plot_3'].astype(bool)].iat[0], self.df_cfg_plot['y_max'][self.df_cfg_plot['plot_4'].astype(bool)].iat[0], self.df_cfg_plot['y_max'][self.df_cfg_plot['plot_5'].astype(bool)].iat[0]] print(self.y_max_plot) df_cfg_sensor_tmp = pd.read_excel('./config_sensor.xlsx', sheet_name='smt') self.df_cfg_sensor = df_cfg_sensor_tmp.dropna(how='all') self.id_time = self.df_cfg_sensor[self.df_cfg_sensor['group'] == 'Time [s]']['ID'].astype(int) self.id_p = self.df_cfg_sensor[self.df_cfg_sensor['group'] == 'P [MPa]']['ID'].astype(int) self.id_T = self.df_cfg_sensor[self.df_cfg_sensor['group'] == 'T [K]']['ID'].astype(int) self.id_imu = self.df_cfg_sensor[self.df_cfg_sensor['group'] == 'IMU']['ID'].astype(int) self.id_hk = self.df_cfg_sensor[self.df_cfg_sensor['group'] == 'House Keeping']['ID'].astype(int) self.id = [self.id_time, self.id_p, self.id_T, self.id_imu, self.id_hk] def dfReloder(self): try: self.df except AttributeError: # In the case of wxpython is not opened pass else: if th_smt.df_ui.shape[0] < self.df.shape[0]: if self.flag_temp: self.data_past = self.df.values self.flag_temp = False else: self.data_past = np.append(self.data_past[-200:], self.df.values, axis=0) print('Reload data_plot : ' + str(self.data_past.shape)) self.df = th_smt.df_ui.copy() def chartGenerator(self): ''' Time history plots ''' self.fig = Figure(figsize=(6, 8)) self.axes = [] for i in range(self.n_plot): self.axes.append(self.fig.add_subplot(self.n_plot, 1, i+1)) self.canvas = FigureCanvasWxAgg(self, -1, self.fig) for i in range(self.n_plot): self.axes[i].set_ylim([self.y_min_plot[i], self.y_max_plot[i]]) for i in range(self.n_plot): self.axes[i].set_ylabel(self.item_plot[i] + ' [{}]'.format(self.unit_plot[i])) self.t_left = 0 for i in range(self.n_plot): self.axes[i].set_xlim([self.t_left, self.t_left + self.t_range]) self.canvas.draw() # Plot Empty Chart self.backgrounds = [] for i in range(self.n_plot): self.backgrounds.append(self.canvas.copy_from_bbox(self.axes[i].bbox)) # Save Empty Chart Format as Background def valueGenerator(self): ''' Current value indicators ''' # generate DataButton instances self.DataButton = [] for index in self.df_cfg_tlm['item']: self.DataButton.append(wx.ToggleButton(self, wx.ID_ANY, index)) # set presentation of values self.SensorValue = [] for i in range(len(self.df_cfg_tlm['item'])): self.SensorValue.append(wx.StaticText(self, wx.ID_ANY, str(i+1), style=wx.ALIGN_CENTRE | wx.ST_NO_AUTORESIZE)) self.SensorValue[-1].SetBackgroundColour('BLACK') self.SensorValue[-1].SetForegroundColour('GREEN') # layout current value panel self.layout_Value = wx.BoxSizer(wx.VERTICAL) self.sbox_type = [] self.sbox_font = wx.Font(15, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL) for name in self.sensor_type: self.sbox_type.append(wx.StaticBox(self, wx.ID_ANY, name)) self.sbox_type[-1].SetFont(self.sbox_font) self.sbox_type[-1].SetForegroundColour('WHITE') self.layout_type = [] for i in range(len(self.sensor_type)): self.layout_type.append(wx.StaticBoxSizer(self.sbox_type[i], wx.VERTICAL)) self.layout_Data = [] for i in range(len(self.sensor_type)): self.layout_Data.append(wx.GridSizer(rows=len(self.id[i])//self.col_value[i]+1, cols=self.col_value[i], gap=(10,5))) self.layout_Set = [] for i in range(len(self.df_cfg_tlm['item'])): self.layout_Set.append(wx.GridSizer(rows=2, cols=1, gap=(5,5))) for i in range(len(self.df_cfg_tlm['item'])): self.layout_Set[i].Add(self.DataButton[i], flag=wx.EXPAND) self.layout_Set[i].Add(self.SensorValue[i], flag=wx.EXPAND) # Set Data Button and Sensor Value for i in range(len(self.sensor_type)): for sensor in self.id[i]: self.layout_Data[i].Add(self.layout_Set[sensor], flag=wx.EXPAND) for i in range(len(self.sensor_type)): self.layout_type[i].Add(self.layout_Data[i]) for i in range(len(self.sensor_type)): self.layout_Value.Add(self.layout_type[i]) for index in self.index_plot: self.DataButton[index].SetValue(True) # for button in self.DataButton: # button.Bind(wx.EVT_TOGGLEBUTTON, self.graphTest) def graphReloader(self, event): # Set Plot Data try: self.data_past except AttributeError: self.data_plot = self.df.values else: self.data_plot = np.append(self.data_past, self.df.values, axis=0) t_temp = self.df.iloc[-1, self.index_x] if t_temp >= self.t_left+self.t_range: self.lines = [] for i in range(self.n_plot): self.axes[i].cla() self.t_left = t_temp - self.t_range / 3 for i in range(self.n_plot): self.axes[i].set_xlim([self.t_left, self.t_left + self.t_range]) for i in range(self.n_plot): self.axes[i].set_ylim([self.y_min_plot[i], self.y_max_plot[i]]) # draw alert line self.axes[0].axhline(y=1.0, xmin=0, xmax=1, color='red') """ self.axes[1].axhline(y=500.0, xmin=0, xmax=1, color='red') self.axes[2].axhline(y=500.0, xmin=0, xmax=1, color='red') """ for i in range(self.n_plot): self.axes[i].set_ylabel(self.item_plot[i] + ' [{}]'.format(self.unit_plot[i])) self.canvas.draw() for i in range(self.n_plot): self.backgrounds[i] = self.canvas.copy_from_bbox(self.axes[i].bbox) # Save Empty Chart Format as Background for i in range(self.n_plot): self.lines.append(self.axes[i].plot(self.data_plot[::2, self.index_x], self.data_plot[::2, self.index_plot[i]])[0]) else: for i in range(self.n_plot): self.lines[i].set_data(self.data_plot[::2, self.index_x], self.data_plot[::2, self.index_plot[i]]) #print(self.df.shape) for i in range(self.n_plot): self.canvas.restore_region(self.backgrounds[i]) # Re-plot Background (i.e. Delete line) for i in range(self.n_plot): self.axes[i].draw_artist(self.lines[i]) # Set new data in ax for i in range(self.n_plot): self.fig.canvas.blit(self.axes[i].bbox) # Plot New data def valueReloader(self, event): # update current values for i_sensor in range(len(self.df_cfg_tlm['item'])): self.SensorValue[i_sensor].SetLabel(str(np.round(self.df.iloc[-1, i_sensor], 2))) def graphTest(self, event): self.n_graph = 0 self.parameter = [] for button in self.DataButton: if button.GetValue(): self.n_graph += 1 self.parameter.append(button.GetLabel()) print(self.n_graph) print(self.parameter) self.chartGenerator(self.n_graph)
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.")
class EditPictureWindows(wx.Frame): """ Class avec l'editeur pour gerer la photo """ def __init__(self,parent,image_dict): wx.Frame.__init__(self, parent, title=parent.selected_photo['Name']) ico = wx.Icon(CURPATH+'/icons/calliper.png', wx.BITMAP_TYPE_PNG) self.SetIcon(ico) #store parent data les modification son repercutees sur le parent self.photo_data = parent.selected_photo self.parent = parent #Some constants self.flipud_needed = True self.photo_data['flipud'] = self.flipud_needed self.InitMenu() self.InitUI() self.Show() self.LoadImage() self.UpdateDataOnGraph() def InitUI(self): #Constant load #For the scale # self.add_scale = False self.scale_pts = [None,None] self.scale_line = None #to store the graph line of the scale self.img_s = None #corresponding length on image self.true_s = 1 #true scale in centimeter # ROI Selection self.add_roi = False #Les points du recto self.roi_pts = [None,None] self.added_roi_rect = None #variable to store mpl patch of the ROI rectangle #Exclusion zones self.add_zone = False self.new_zone_pts = [None,None] self.new_zone_rect = [] self.added_zone_rect = [] #variable to store mpl patch of the exclusion zones rectangle #Removed grain self.removed_rectangle = {} self.added_removed_rectangle = {} self.removed_label = [] #list to store label of removed grains (or items) #For reprocessing and image self.reprocess = False # --------------------------------------------------------------------- #Main panel self.panel = wx.Panel(self) # Create the toolbar # self.toolbar = self.CreateToolBar() ascale = self.toolbar.AddLabelTool(0, 'Add scale', wx.Bitmap(CURPATH+'/icons/scale_edit.png'),shortHelp='Draw scale on picture') aroi = self.toolbar.AddLabelTool(1, 'Add ROI', wx.Bitmap(CURPATH+'/icons/roi_add.png'),shortHelp='Add a region of interest') azone = self.toolbar.AddLabelTool(2, 'Add ROI', wx.Bitmap(CURPATH+'/icons/zone_add.png'),shortHelp='Add an exclusion zone') reprocess =self.toolbar.AddLabelTool(3, 'Process on close', wx.Bitmap(CURPATH+'/icons/flag_green.png'),shortHelp='Reprocess this picture') flipud_tb =self.toolbar.AddLabelTool(4, 'flipud', wx.Bitmap(CURPATH+'/icons/flipud.png'),shortHelp='Flip up-down this picture') if not self.photo_data['proceded']: self.toolbar.EnableTool(3,False) self.toolbar.Realize() self.Bind(wx.EVT_TOOL, self.AddScale, ascale) self.Bind(wx.EVT_TOOL, self.AddRoi, aroi) self.Bind(wx.EVT_TOOL, self.AddZone, azone) self.Bind(wx.EVT_TOOL, self.Reprocess, reprocess) self.Bind(wx.EVT_TOOL, self.OnFlipud, flipud_tb) # ------------------------------------------------ #Gestion de la fermeture de la fenetre -> lance le calcul self.Bind(wx.EVT_CLOSE, self.OnClose) # Create the mpl Figure and FigCanvas objects. # 5x4 inches, 100 dots-per-inch # self.dpi = 100 self.fig = Figure((5.0, 4.0), dpi=self.dpi) self.canvas = FigCanvas(self.panel, -1, self.fig) # Manage canvas events # Bind the 'pick' event for clicking on one of the bars # self.canvas.mpl_connect('button_press_event', self.OnGraphClick) self.canvas.mpl_connect('motion_notify_event', self.OnGraphMove) self.canvas.mpl_connect('pick_event', self.OnGraphPick) # 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) # Create the navigation toolbar, tied to the canvas # self.toolbar = NavigationToolbar(self.canvas) # Create text zones for scale txt_label = wx.StaticText(self.panel, label=" Scale ") scale_txt = wx.StaticText(self.panel, label="Pixels = ") scale_txt2 = wx.StaticText(self.panel, label="cm") self.imgscale_textbox = wx.TextCtrl( self.panel, size=(80,-1), style=wx.TE_READONLY) self.truescale_textbox = wx.TextCtrl( self.panel, size=(80,-1), style=wx.TE_PROCESS_ENTER) #Add action when the true scale is enter self.Bind(wx.EVT_TEXT, self.OnScaleTextEnter, self.truescale_textbox) # # Layout with box sizers # self.vbox = wx.BoxSizer(wx.VERTICAL) self.vbox.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW) self.vbox.Add(self.toolbar, 0, wx.EXPAND) self.vbox.AddSpacer(10) self.vbox.Add(txt_label, 0) self.hbox = wx.BoxSizer(wx.HORIZONTAL) flags = wx.ALIGN_LEFT | wx.ALL | wx.ALIGN_CENTER_VERTICAL self.hbox.Add(self.imgscale_textbox, 0, border=1, flag=flags) self.hbox.Add(scale_txt, 0, border=1, flag=flags) self.hbox.Add(self.truescale_textbox, 0, border=1, flag=flags) self.hbox.Add(scale_txt2, 0, border=1, flag=flags) self.vbox.Add(self.hbox, 0, flag = wx.ALIGN_LEFT | wx.TOP) self.panel.SetSizer(self.vbox) self.vbox.Fit(self) #Update the scale self.ShowScale() def InitMenu(self): #function to init the menu menubar = wx.MenuBar() #Edit Menu EditMenu = wx.Menu() remscale = EditMenu.Append(100, 'Remove scale', 'Remove the scale on the current picture') remROI = EditMenu.Append(11, 'Remove ROI', 'Remove the region of interest') remZone = EditMenu.Append(12, 'Remove exclusion zones', 'Remove exclusion zones') viewMenu = wx.Menu() #events self.Bind(wx.EVT_MENU, lambda event, keys=['scale','scale_coord'], default_values=[None,[None,None]]: self.RemoveData(event, keys, default_values), remscale) self.Bind(wx.EVT_MENU, lambda event, keys=['ROI'], default_values=[None]: self.RemoveData(event, keys, default_values), remROI) self.Bind(wx.EVT_MENU, lambda event, keys=['exclusion_zones'], default_values=[None]: self.RemoveData(event, keys, default_values), remZone) menubar.Append(EditMenu, '&Edit') self.SetMenuBar(menubar) def Reprocess(self, event): #Turn the reprocess flag to true and updata photo_data self.reprocess = True self.photo_data['proceded'] = False self.UpdateParentList() def ShowScale(self): """ pour mettre a jour l'affichage de l'echelle """ saved_scale = self.photo_data['scale_img_and_true'] if saved_scale == None: self.imgscale_textbox.ChangeValue("None") else: self.imgscale_textbox.ChangeValue(str(saved_scale[0].round(2))) self.true_s = saved_scale[1] self.img_s = saved_scale[0] self.truescale_textbox.ChangeValue(str(self.true_s)) def LoadImage(self): img = imread(self.photo_data['path']+os.path.sep+self.photo_data['Name']) if self.flipud_needed: self.axes.imshow(flipud(img), interpolation='nearest',animated=True) else: self.axes.imshow(img, interpolation='nearest',animated=True) self.canvas.draw() #store the background boundary box self.fig_bg = self.canvas.copy_from_bbox(self.axes.bbox) #Save limits self.xlims = self.axes.get_xlim() self.ylims = self.axes.get_ylim() #action when flipud toolbar button is pressed def OnFlipud(self,e): if self.flipud_needed: self.flipud_needed = False else: self.flipud_needed = True self.photo_data['flipud'] = self.flipud_needed #clear self.axes.clear() #Reload self.LoadImage() self.UpdateDataOnGraph() def OnGraphClick(self,e): # test if we are editing the scale if self.add_scale: #print 'you pressed', e.button, e.xdata, e.ydata xi, yi = (round(n,2) for n in (e.xdata, e.ydata)) if not self.scale_pts[0] and not self.scale_pts[1]: #add the first point to self.scale_pts self.scale_pts[0] = (xi,yi) #create the plot self.scale_line, = self.axes.plot(xi,yi,'go-',mec='w',ms=8,mew=2,linewidth=2,label='scale') #put the good limits self.axes.set_xlim(self.xlims) self.axes.set_ylim(self.ylims) self.canvas.draw() elif not self.scale_pts[1]: self.scale_pts[1] = (xi,yi) #release the editing scale boolean and compute the scale self.edit_scale = False self.img_s = sqrt((self.scale_pts[0][0]-self.scale_pts[1][0])**2+(self.scale_pts[0][1]-self.scale_pts[1][1])**2) #update the scale self.scale_line.set_data([[self.scale_pts[0][0],self.scale_pts[1][0]],[self.scale_pts[0][1],self.scale_pts[1][1]]]) #put the good limits self.axes.set_xlim(self.xlims) self.axes.set_ylim(self.ylims) self.canvas.draw() #unactive add_scale self.add_scale = False #Save to image dict self.SaveModification('scale',self.img_s/self.true_s) self.SaveModification('scale_img_and_true',[self.img_s, self.true_s]) #Save scale position self.SaveModification('scale_coord',self.scale_pts) #Update the scale on screen self.ShowScale() #Test if we are adding a roi if self.add_roi: self.CompleteRectangleOnClick(e,self.roi_pts,self.roi_rect,'ROI') #Test if we are adding a zone if self.add_zone: self.CompleteRectangleOnClick(e,self.new_zone_pts,self.new_zone_rect[-1],'exclusion_zones') def CompleteRectangleOnClick(self,event,pts_var,rectangle_var,name): e = event if e.xdata != None and e.ydata != None: #test sur les points if pts_var[0] == None and pts_var[1] == None: pts_var[0] = (e.xdata,e.ydata) #update the rectangle rectangle_var.set_xy(pts_var[0]) elif pts_var[1] == None: pts_var[1] = (e.xdata,e.ydata) #add with and length to the rectange rectangle_var.set_width(e.xdata-pts_var[0][0]) rectangle_var.set_height(e.ydata-pts_var[0][1]) #Save the data self.SaveModification(name,[int(pts_var[0][0]),int(pts_var[0][1]),int(pts_var[1][0]),int(pts_var[1][1])]) #Restart si exclusion_zones if name == 'exclusion_zones': self.add_zone = False self.new_zone_pts = [None,None] def OnGraphMove(self,event): if event.xdata != None and event.ydata != None: if self.add_roi: #test sur les points if self.roi_pts[0] != None and self.roi_pts[1] == None: #update rectangle with coordinate self.roi_rect.set_width(event.xdata-self.roi_pts[0][0]) self.roi_rect.set_height(event.ydata-self.roi_pts[0][1]) self.canvas.draw() #pour les zones if self.add_zone: #test sur les points if self.new_zone_pts[0] != None and self.new_zone_pts[1] == None: #update rectangle with coordinate self.new_zone_rect[-1].set_width(event.xdata-self.new_zone_pts[0][0]) self.new_zone_rect[-1].set_height(event.ydata-self.new_zone_pts[0][1]) self.canvas.draw() def OnGraphPick(self,event): """ Function to manage when an element is picked on the plot """ #print "a cl has been picked" #print event.ind #Test right click: Remove this item if event.mouseevent.button == 3: #test if we have picked a linecollection class if 'LineCollection' in str(event.artist): #get label of the selected object label = self.photo_data['data']['measurements'][event.ind[0]]['Label'] #test if label is already in removed items if label not in self.removed_label: #Rectangle limits minr, minc, maxr, maxc = self.photo_data['data']['measurements'][event.ind[0]]['BoundingBox'] if self.photo_data['data']['ROI'] != None: yo = min(self.photo_data['data']['ROI'][1],self.photo_data['data']['ROI'][3]) xo = min(self.photo_data['data']['ROI'][0],self.photo_data['data']['ROI'][2]) minc += xo maxc += xo minr += yo maxr += yo #Add a grey rectangle over the removed item self.removed_rectangle[event.ind[0]] = Rectangle((minc,minr),maxc-minc,maxr-minr,edgecolor='k',fill=False,hatch='/',zorder=1000) self.added_removed_rectangle[event.ind[0]] = self.axes.add_patch(self.removed_rectangle[event.ind[0]]) #Add the label to the list self.removed_label.append(label) #Save this to photo data self.SaveModification('removed_items_label',self.removed_label) self.canvas.draw() #Test left click: Restore this item if event.mouseevent.button == 1: #test if we have picked a linecollection class if 'LineCollection' in str(event.artist): label = self.photo_data['data']['measurements'][event.ind[0]]['Label'] #test if label is already in removed items if label in self.removed_label: #remove the mpatch of the rectangle self.added_removed_rectangle[event.ind[0]].remove() #Remove rectangle self.removed_rectangle.pop(event.ind[0]) #remove label from removed_list self.removed_label.remove(label) #Save this to photo data self.SaveModification('removed_items_label',self.removed_label) self.canvas.draw() def OnScaleTextEnter(self,event): #Action when a true scale is entered #test si nul if event.GetString() != '': #save in object self.true_s = float(event.GetString()) #if img scale != none save in image dict file if self.img_s != None: self.SaveModification('scale',self.img_s/self.true_s) self.SaveModification('scale_img_and_true',[self.img_s,self.true_s]) # Toolbar Actions def AddScale(self, e): #reset to false if is clicked again if self.add_scale or (self.scale_pts[0] != None and self.scale_pts[1] != None): self.add_scale = False else: self.add_scale = True #put other to false self.add_roi = False self.add_zone = False def AddRoi(self,e): #If false if not self.add_roi and self.roi_pts[1] == None: #Init a rectangle (xy),width,height self.roi_rect = Rectangle((0,0), 0, 0, facecolor='none') #add the rect to the plot self.added_roi_rect = self.axes.add_patch(self.roi_rect) self.add_roi = True #put other to false self.add_scale = False self.add_zone = False def AddZone(self, e): if not self.add_zone: self.new_zone_rect.append(Rectangle((0,0), 0, 0,facecolor='none',edgecolor='y')) self.added_zone_rect.append(self.axes.add_patch(self.new_zone_rect[-1])) self.add_zone = True #put other to false self.add_roi = False self.add_scale = False def SaveModification(self,key,values): #save modified things to the image dict #TODO: special append for exclusion zones #save the roi to image dict if key == 'exclusion_zones' : #test if we need to init the list if self.photo_data[key] == None: self.photo_data[key] = [] self.photo_data[key].append(values) else: self.photo_data[key] = values self.UpdateParentList() def UpdateParentList(self): """ Function to update the parent control list of pictures """ #on chop l'item de la colone statu (1) correspondant a la photo entrain d'etre travaillee self.parent.list.SetStringItem(self.parent.selected_index, 1, Create_statu_txt(self.photo_data)) def OnClose(self, e): """ Gestion de la fermeture de l'editeur de figure -> Lance OnComputationStart de la fenetre parente """ #Ajout un option pour relance le calcul #self.parent.OnComputationStart() #fermeture de cette fenetre self.Destroy() def UpdateDataOnGraph(self,no_redraw=['']): """ gestion des donnees a tracer no_redraw allow to not redraw some part """ #TODO: un filtre pour afficher grain tourves oui/non if self.photo_data['data'] != None and 'data' not in no_redraw: if 'labeled_objects_found' in self.photo_data['data']: obg_shape = shape(self.photo_data['data']['labeled_objects_found']) xi = arange(obg_shape[1]) yi = arange(obg_shape[0]) if self.photo_data['data']['ROI'] != None: xi += min(self.photo_data['data']['ROI'][0],self.photo_data['data']['ROI'][2]) yi += min(self.photo_data['data']['ROI'][1],self.photo_data['data']['ROI'][3]) #Store the contour line cl = self.axes.contour(xi,yi,ndimage.binary_fill_holes(self.photo_data['data']['labeled_objects_found']), 1, linewidths=1.5, colors='c') #Add a picker radius to each lines for line in cl.collections: line.set_picker(20) #Calcul des axes pour les afficher sur les cailloux self.PlotItemAxis() #Plot the roi if self.photo_data['ROI'] != None and 'ROI' not in no_redraw: self.roi_pts = self.photo_data['ROI'] if self.added_roi_rect == None: self.roi_rect = Rectangle((0,0), 0, 0,fc='none') self.roi_rect.set_xy((self.photo_data['ROI'][0],self.photo_data['ROI'][1])) self.roi_rect.set_width(self.photo_data['ROI'][2] - self.photo_data['ROI'][0]) self.roi_rect.set_height(self.photo_data['ROI'][3] - self.photo_data['ROI'][1]) self.added_roi_rect = self.axes.add_patch(self.roi_rect) if self.photo_data['exclusion_zones'] != None and 'exclusion_zones' not in no_redraw: for zone in self.photo_data['exclusion_zones'] : self.new_zone_rect.append(Rectangle((zone[0],zone[1]),zone[2] - zone[0],zone[3] - zone[1],facecolor='none',edgecolor='y')) #add patch to axes self.added_zone_rect.append(self.axes.add_patch(self.new_zone_rect[-1])) if self.photo_data['scale'] != None and 'scale' not in no_redraw: self.scale_pts = self.photo_data['scale_coord'] self.scale_line = self.axes.plot((self.scale_pts[0][0],self.scale_pts[1][0]), (self.scale_pts[0][1],self.scale_pts[1][1]), 'bo-',mec='w',ms=8,mew=2,linewidth=2,picker=5,label='scale') #plot the removed items if 'removed_items_label' in self.photo_data: #Load the list in self.removed_label self.removed_label = self.photo_data['removed_items_label'] for label in self.removed_label: minr, minc, maxr, maxc = self.photo_data['data']['measurements'][label-1]['BoundingBox'] if self.photo_data['data']['ROI'] != None: yo = min(self.photo_data['data']['ROI'][1],self.photo_data['data']['ROI'][3]) xo = min(self.photo_data['data']['ROI'][0],self.photo_data['data']['ROI'][2]) minc += xo maxc += xo minr += yo maxr += yo #Add a grey rectangle over the removed item self.removed_rectangle[label-1] = Rectangle((minc,minr),maxc-minc,maxr-minr,edgecolor='k',fill=False,hatch='/',zorder=1000) self.added_removed_rectangle[label-1] = self.axes.add_patch(self.removed_rectangle[label-1]) #limits self.axes.set_xlim(self.xlims) self.axes.set_ylim(self.ylims) #refresh canvas. self.canvas.draw() def PlotItemAxis(self): for measure in self.photo_data['data']['measurements']: Orientation= GetOrientation(measure['CentralMoments']) #compute ellipse orientation x0 = measure['Centroid'][1] y0 = measure['Centroid'][0] x1 = x0 + cos(Orientation) * 0.5 * measure['MajorAxisLength'] y1 = y0 - sin(Orientation) * 0.5 * measure['MajorAxisLength'] x2 = x0 - sin(Orientation) * 0.5 * measure['MinorAxisLength'] y2 = y0 - cos(Orientation) * 0.5 * measure['MinorAxisLength'] #Ajout de la ROI if self.photo_data['data']['ROI'] != None: xroi = min(self.photo_data['data']['ROI'][0],self.photo_data['data']['ROI'][2]) yroi = min(self.photo_data['data']['ROI'][1],self.photo_data['data']['ROI'][3]) else: xroi = 0 yroi = 0 self.axes.plot(array([x0, x1])+xroi, array([y0, y1])+yroi, '-r', linewidth=2.5) self.axes.plot(array([x0, x2])+xroi, array([y0, y2])+yroi, '-r', linewidth=2.5) self.axes.plot(x0+xroi, y0+yroi, '.g', markersize=8) def RemoveData(self,event,keys,default_values): #remove the data from photo_data dict and put the default value for key, value in zip(keys,default_values): self.photo_data[key] = value #put special value if key == 'scale': self.scale_pts = [None,None] self.ShowScale() #clean lines if self.scale_line != None: self.scale_line.remove() #reset scale_line to None self.scale_line = None if key == 'ROI': self.roi_pts = [None,None] if self.added_roi_rect != None: self.added_roi_rect.remove() self.added_roi_rect = None if key == 'exclusion_zones': self.new_zone_pts = [None,None] self.new_zone_rect = [] if self.added_zone_rect != []: for added_zone in self.added_zone_rect: added_zone.remove() #remove the Rectangle on the plot #reset the added_zone to empty list self.added_zone_rect = [] #update parent self.UpdateDataOnGraph() self.UpdateParentList()
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)
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 )
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()
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 MainPanel(wx.Panel): __T_RANGE = 30 # [s] # __N_PLOTTER = 1 __N_PLOTTER = 5 # index_x = 1 # sensor_type = ['Time [s]', 'P [MPa]', 'T [K]', 'IMU', 'House Keeping'] # col_value = [6, 8, 8, 9, 8] def __init__(self, parent): super().__init__(parent, wx.ID_ANY) ### initialize self.NNN = 0 # self.__F_TLM_IS_ACTIVE = False # self.dfTlm = pd.DataFrame() # - plotter config self.load_config_plotter() ### configure appearanc self.configure_plotter() ### layout elements self.layout = wx.FlexGridSizer(rows=1, cols=1, gap=(0, 0)) self.layout.Add(self.canvas, flag=wx.EXPAND) self.SetSizer(self.layout) ### bind events # - set timer to refresh time-history pane self.tmrRefreshPlotter = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.OnRefreshPlotter, self.tmrRefreshPlotter) self.tmrRefreshPlotter.Start(REFLESH_RATE_PLOTTER) # Event handler: EVT_TIMER def OnRefreshPlotter(self, event): # return None # for debug # update plot points by appending latest values self.x_series = np.append(self.x_series, x_val[self.NNN]) # self.y1_series = np.append(self.y1_series, y1_val[self.NNN]) # self.y2_series = np.append(self.y2_series, y2_val[self.NNN]) for i in range(self.__N_PLOTTER): self.y_series = np.append(self.y_series, self.y_val[i][self.NNN]) # pseudo-time incriment USED ONLY IN TEST self.NNN += 1 if self.NNN == len(x_val): self.NNN = 0 # reset pseudo-time # update time range to plot t_max = self.x_series[-1] t_min = t_max - self.__T_RANGE # print("GUI PLT: t_max = {}, t_min = {}".format(t_max, t_min)) # delete plot points out of the designated time range while self.x_series[0] < t_min: print("GUI PLT: a member of 'x_series' is out of the range") self.x_series = np.delete(self.x_series, 0) self.y_series = np.delete(self.y_series, np.s_[0:self.__N_PLOTTER]) # self.y1_series = np.delete(self.y1_series, 0) # self.y2_series = np.delete(self.y2_series, 0) # self.y_series = np.delete(self.y_series, self.__N_PLOT) # print("GUI PLT: length x: {}, y: {}".format(len(self.x_series),len(self.y_series))) # prepare redraw self.lines = [] for i in range(self.__N_PLOTTER): # delete x axis and lines by restroring canvas self.canvas.restore_region(self.backgrounds[i]) # clear axes self.axes[i].cla() # update limit for x axis self.axes[i].set_xlim([t_min, t_max]) # set limit for y axis self.axes[i].set_ylim( [self.plt_attr[i].y_min, self.plt_attr[i].y_max]) # set label for y axis self.axes[i].set_ylabel(self.plt_attr[i].y_label) # update alert line self.axes[i].axhline(y=self.plt_attr[i].alart_lim_u, xmin=0, xmax=1, color='red') self.axes[i].axhline(y=self.plt_attr[i].alart_lim_u, xmin=0, xmax=1, color='red') # update plot # NOTE: lines become iterrable hereafter self.lines.append(self.axes[i].plot( self.x_series, self.y_series[i::self.__N_PLOTTER])[0]) # reflect updates in lines self.axes[i].draw_artist(self.lines[i]) # # redraw and show updated canvas # self.fig.canvas.blit(self.axes[i].bbox) # redraw and show updated canvas self.fig.canvas.draw() # self.fig.canvas.flush_events() print("GUI PLT: redraw plots...") # Load configurations from external files def load_config_plotter(self): ### TBREFAC.: TEMPORALLY DESIGNATED BY LITERALS ### plt_attr_1 = PltAttr(y_label="Series 1", y_min=0.0, y_max=4.0, alart_lim_u=3.0, alart_lim_l=1.0) plt_attr_2 = PltAttr( y_label="Series 2", y_min=0.0, y_max=3.0, alart_lim_u=2.5, alart_lim_l=0.5, ) plt_attr_3 = PltAttr( y_label="Series 3", y_min=0.0, y_max=3.0, alart_lim_u=2.5, alart_lim_l=0.5, ) plt_attr_4 = PltAttr( y_label="Series 4", y_min=0.0, y_max=3.0, alart_lim_u=2.5, alart_lim_l=0.5, ) plt_attr_5 = PltAttr( y_label="Series 5", y_min=0.0, y_max=3.0, alart_lim_u=2.5, alart_lim_l=0.5, ) self.plt_attr = [] self.plt_attr.append(plt_attr_1) if self.__N_PLOTTER <= 1: return self.plt_attr.append(plt_attr_2) if self.__N_PLOTTER <= 2: return self.plt_attr.append(plt_attr_3) if self.__N_PLOTTER <= 3: return self.plt_attr.append(plt_attr_4) if self.__N_PLOTTER <= 4: return self.plt_attr.append(plt_attr_5) if self.__N_PLOTTER <= 5: return else: self.__N_PLOTTER == 5 # self.y_label = [, "Series 2"] # self.y_min = [0.0, 0.0] # self.y_max = [4.0, 3.0] # self.alart_lim_u = [3.0, 2.5] # self.alart_lim_l = [1.0, 0.5] # self.item_plot = [self.df_cfg_plot['item'][self.df_cfg_plot['plot_1'].astype(bool)].iat[0], # self.df_cfg_plot['item'][self.df_cfg_plot['plot_2'].astype(bool)].iat[0]] # Configure appearance for plotters to display time histories def configure_plotter(self): # initialize data set self.x_series = np.empty(0) self.y_series = np.empty(0) # self.y1_series = np.empty(0) # self.y2_series = np.empty(0) # print("GUI PLT: x_series = {}".format(self.x_series)) # print("GUI PLT: y_series = {}".format(self.y_series)) # USED ONLY IN TEST self.y_val = [y1_val, y2_val, y3_val, y4_val, y5_val] # generate empty matplotlib Fugure self.fig = Figure(figsize=(8, 8)) # register Figure with matplotlib Canvas self.canvas = FigureCanvasWxAgg(self, wx.ID_ANY, self.fig) # return None # for debug ### prepare axes # - generate subplots containing axes in Figure # NOTE: axes become iterrable hereafter self.axes = [] for i in range(self.__N_PLOTTER): self.axes.append(self.fig.add_subplot(self.__N_PLOTTER, 1, i + 1)) # - set limit for x axis t_min = 0 self.axes[i].set_xlim([t_min, t_min + self.__T_RANGE]) # - set limit for y axis self.axes[i].set_ylim( [self.plt_attr[i].y_min, self.plt_attr[i].y_max]) # - set label for y axis self.axes[i].set_ylabel(self.plt_attr[i].y_label) # tentatively draw canvas without plot points to save as background self.canvas.draw() # save the empty canvas as background # NOTE: backgrounds become iterrable hereafter self.backgrounds = [] for i in range(self.__N_PLOTTER): self.backgrounds.append( self.canvas.copy_from_bbox(self.axes[i].bbox))
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)
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()
class parameter_panel2(wx.Panel): def __init__(self, *args, **kwds): # begin wxGlade: parameter_panel2.__init__ kwds["style"] = wx.TAB_TRAVERSAL wx.Panel.__init__(self, *args, **kwds) self.__set_properties() self.__do_layout() # end wxGlade self.figure = Figure(figsize=(6,4), dpi=80) self.canvas = FigureCanvas(self, wx.ID_ANY, self.figure) self.axes_alpha_beta = self.figure.add_subplot(211) self.axes_ab = self.figure.add_subplot(212) self.axes_alpha_beta.set_autoscale_on(False) #self.axes_ab.set_autoscale_on(False) self.axes_alpha_beta.set_xlim([0,100]) self.axes_alpha_beta.set_ylim([0,1]) self.axes_alpha_beta.set_xticks(range(0,101,100)) self.axes_ab.set_xlim([0,100]) #self.axes_ab.set_ylim([]) self.axes_ab.set_xticks(range(0,101,5)) self.params = [None]*9; self.param_file = open('params') for i in range(9): self.params[i] = float(self.param_file.readline()) self.param_file.close() self.alpha = [None] * 100 self.beta = [None] * 100 self.a00 = [None] * 100 self.b00 = [None] * 100 self.a11 = [None] * 100 self.b11 = [None] * 100 self.real_alpha = [self.params[3]] * 100 self.real_beta = [self.params[4]] * 100 self.real_a00 = [self.params[5]] * 100 self.real_b00 = [self.params[6]] * 100 self.real_a11 = [self.params[7]] * 100 self.real_b11 = [self.params[8]] * 100 self.l_alpha, = self.axes_alpha_beta.plot(range(100), self.alpha, label='estimated alpha') self.l_real_alpha, = self.axes_alpha_beta.plot(range(100), self.real_alpha, label='alpha') self.l_beta, = self.axes_alpha_beta.plot(range(100), self.beta, label='estimated beta') self.l_real_beta, = self.axes_alpha_beta.plot(range(100), self.real_beta, label='beta') self.l_a00, = self.axes_ab.plot(range(100), self.a00, label='estimated a00') self.l_real_a00, = self.axes_ab.plot(range(100), self.real_a00, label='a00') self.l_b00, = self.axes_ab.plot(range(100), self.b00, label='estimated b00') self.l_real_b00, = self.axes_ab.plot(range(100), self.real_b00, label='b00') self.l_a11, = self.axes_ab.plot(range(100), self.a11, label='estimated a11') self.l_real_a11, = self.axes_ab.plot(range(100), self.real_a11, label='a11') self.l_b11, = self.axes_ab.plot(range(100), self.b11, label='estimated b11') self.l_real_b11, = self.axes_ab.plot(range(100), self.real_b11, label='b11') self.axes_alpha_beta.legend(loc='upper center', ncol=4, prop=font_manager.FontProperties(size=9)) self.axes_ab.legend(loc='upper center', ncol=4, prop=font_manager.FontProperties(size=7)) self.axes_ab.set_xlabel('time (s)') self.axes_alpha_beta.set_title("parameters") self.canvas.draw() self.bg_alpha_beta = self.canvas.copy_from_bbox(self.axes_alpha_beta.bbox) self.bg_ab = self.canvas.copy_from_bbox(self.axes_ab.bbox) def __set_properties(self): # begin wxGlade: parameter_panel2.__set_properties pass # end wxGlade def __do_layout(self): # begin wxGlade: parameter_panel2.__do_layout pass
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)
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
class ChartPanel(wx.Panel): n_time = 3 index_x = 1 index_plot1 = 11 # Pple,o(8+3) index_plot2 = 2 # Tth,rde(18+3) index_plot3 = 22 # Tcpde(19+3) t_range = 20 def __init__(self, parent, reflesh_time_graph, reflesh_time_value): super().__init__(parent, wx.ID_ANY) self.configReader() self.valueGenerator() self.chartGenerator() # layout time history pane layout = wx.FlexGridSizer(rows=2, cols=1, gap=(0, 20)) layout.Add(self.canvas, flag=wx.EXPAND) layout.Add(self.layout_Data) self.SetSizer(layout) # set refresh timer for time history pane self.timer_reload_graph = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.graphReloader, self.timer_reload_graph) self.timer_reload_graph.Start(reflesh_time_graph) # set refresh timer for current value pane self.timer_reload_value = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.valueReloader, self.timer_reload_value) self.timer_reload_value.Start(reflesh_time_value) def configReader(self): # load smt data config self.df_cfg_plot = th_smt.smt.df_cfg.copy() self.df_cfg_plot.reset_index() self.p_number = np.array( list(self.df_cfg_plot.query('type == "p"').index)) self.T_number = np.array( list(self.df_cfg_plot.query('type == "T"').index)) def chartGenerator(self): ''' Time history plots ''' self.fig = Figure(figsize=(6, 4)) self.ax1 = self.fig.add_subplot(311) self.ax2 = self.fig.add_subplot(312) self.ax3 = self.fig.add_subplot(313) self.canvas = FigureCanvasWxAgg(self, -1, self.fig) self.ax1.set_ylim([0.0, 1.5]) self.ax2.set_ylim([0.0, 100000.0]) self.ax3.set_ylim([200.0, 600.0]) self.t_left = 0 self.ax1.set_xlim([self.t_left, self.t_left + self.t_range]) self.ax2.set_xlim([self.t_left, self.t_left + self.t_range]) self.ax3.set_xlim([self.t_left, self.t_left + self.t_range]) self.canvas.draw() # Plot Empty Chart self.background1 = self.canvas.copy_from_bbox( self.ax1.bbox) # Save Empty Chart Format as Background self.background2 = self.canvas.copy_from_bbox( self.ax2.bbox) # Save Empty Chart Format as Background self.background3 = self.canvas.copy_from_bbox( self.ax3.bbox) # Save Empty Chart Format as Background def valueGenerator(self): ''' Current value indicators ''' self.row_value = 4 self.col_value = 6 # generate DataButton instances self.DataButton = [] for index in th_smt.smt.df_mf.columns[self.p_number]: self.DataButton.append(wx.ToggleButton(self, wx.ID_ANY, index)) self.DataButton.append(wx.ToggleButton(self, wx.ID_ANY, 'Pc,rde')) self.DataButton.append(wx.ToggleButton(self, wx.ID_ANY, 'Pc,pde')) for index in th_smt.smt.df_mf.columns[self.T_number]: self.DataButton.append(wx.ToggleButton(self, wx.ID_ANY, index)) self.DataButton.append(wx.ToggleButton(self, wx.ID_ANY, 'n/a')) self.DataButton.append(wx.ToggleButton(self, wx.ID_ANY, 'n/a')) # set presentation of values self.SensorValue = [] for i in range(self.row_value * self.col_value): self.SensorValue.append( wx.StaticText(self, wx.ID_ANY, str(i + 1), style=wx.ALIGN_CENTRE | wx.ST_NO_AUTORESIZE)) self.SensorValue[-1].SetBackgroundColour('BLACK') self.SensorValue[-1].SetForegroundColour('GREEN') #self.SensorValue[-1].SetFont(self.font) # layout current value pane self.layout_Data = wx.GridSizer(rows=self.row_value * 2, cols=self.col_value, gap=(10, 5)) for k in range(self.row_value): for l in range(self.col_value): self.layout_Data.Add(self.DataButton[self.col_value * k + l], flag=wx.EXPAND) for n in range(self.col_value): self.layout_Data.Add(self.SensorValue[self.col_value * k + n], flag=wx.EXPAND) # enable plots by activating buttons self.DataButton[self.p_number[8] - self.p_number[0]].SetValue( True) # Pple,o(8) self.DataButton[self.T_number[6] - self.T_number[0] + len(self.p_number) + 2].SetValue(True) # Tth,rde(18) self.DataButton[self.T_number[7] - self.T_number[0] + len(self.p_number) + 2].SetValue(True) # Tcpde(19) def dfReloder(self): self.df = th_smt.df_ui.copy() def graphReloader(self, event): t_temp = self.df.iloc[-1, self.index_x] print(t_temp) # Alert of Pple,o (Threshold : 1.0 MPa) #if self.df.iloc[-1, self.p_number[8]] > 1.0: # self.ax1.set_facecolor('red') #else: # self.ax1.set_facecolor('black') # Alert of Tth,rde (Threshold : 500 K) #if self.df.iloc[-1, self.T_number[6]] > 500: # self.ax2.set_facecolor('red') #else: # self.ax2.set_facecolor('black') # Alert of Tc,pde (Threshold : 500 K) #if self.df.iloc[-1, self.T_number[7]] > 500: # self.ax2.set_facecolor('red') #else: # self.ax2.set_facecolor('black') if t_temp >= self.t_left + self.t_range: self.i_left = self.df.shape[0] self.lines1 = [] self.lines2 = [] self.lines3 = [] self.ax1.cla() self.ax2.cla() self.ax3.cla() self.t_left = self.df.iloc[-1, self.index_x] self.ax1.set_xlim([self.t_left, self.t_left + self.t_range]) self.ax2.set_xlim([self.t_left, self.t_left + self.t_range]) self.ax3.set_xlim([self.t_left, self.t_left + self.t_range]) self.ax1.set_ylim([-1.0, 1.5]) self.ax2.set_ylim([0.0, 100000.0]) self.ax3.set_ylim([200.0, 600.0]) # draw alert line self.ax1.axhline(y=1.0, xmin=0, xmax=1, color='red') """ self.ax2.axhline(y=500.0, xmin=0, xmax=1, color='red') self.ax3.axhline(y=500.0, xmin=0, xmax=1, color='red') """ self.ax1.set_ylabel('Pple,o [MPa]') self.ax2.set_ylabel('Tth,rde [K]') self.ax3.set_ylabel('Tcpde [K]') self.canvas.draw() self.background1 = self.canvas.copy_from_bbox( self.ax1.bbox) # Save Empty Chart Format as Background self.background2 = self.canvas.copy_from_bbox( self.ax2.bbox) # Save Empty Chart Format as Background self.background3 = self.canvas.copy_from_bbox( self.ax3.bbox) # Save Empty Chart Format as Background # plot Pple,o histories self.lines1.append( self.ax1.plot(self.df.iloc[self.i_left::2, self.index_x], self.df.iloc[self.i_left::2, self.index_plot1])[0]) # plot Tth,rde histories self.lines2.append( self.ax2.plot(self.df.iloc[self.i_left::2, self.index_x], self.df.iloc[self.i_left::2, self.index_plot2])[0]) # plot Tcpde histories self.lines3.append( self.ax3.plot(self.df.iloc[self.i_left::2, self.index_x], self.df.iloc[self.i_left::2, self.index_plot3])[0]) else: # reflesh Pple,o histories plot for i_p_line in range(len(self.lines1)): self.lines1[i_p_line].set_data( self.df.iloc[self.i_left::2, self.index_x], self.df.iloc[self.i_left::2, self.index_plot1]) # reflesh Tth,rde histories plot for i_T_line in range(len(self.lines2)): self.lines2[i_T_line].set_data( self.df.iloc[self.i_left::2, self.index_x], self.df.iloc[self.i_left::2, self.index_plot2]) # reflesh Tcpde histories plot for i_T_line in range(len(self.lines2)): self.lines3[i_T_line].set_data( self.df.iloc[self.i_left::2, self.index_x], self.df.iloc[self.i_left::2, self.index_plot3]) self.canvas.restore_region( self.background1) # Re-plot Background (i.e. Delete line) self.canvas.restore_region( self.background2) # Re-plot Background (i.e. Delete line) self.canvas.restore_region( self.background3) # Re-plot Background (i.e. Delete line) for line in self.lines1: self.ax1.draw_artist(line) # Set new data in ax for line in self.lines2: self.ax2.draw_artist(line) # Set new data in ax for line in self.lines3: self.ax3.draw_artist(line) # Set new data in ax self.fig.canvas.blit(self.ax1.bbox) # Plot New data self.fig.canvas.blit(self.ax2.bbox) # Plot New data self.fig.canvas.blit(self.ax3.bbox) # Plot New data def valueReloader(self, event): # update current values for i_sensor in self.p_number: self.SensorValue[i_sensor - self.p_number[0]].SetLabel( str(np.round(self.df.iloc[-1, i_sensor], 2))) self.SensorValue[i_sensor - self.p_number[0] + 1].SetLabel('0.10') self.SensorValue[i_sensor - self.p_number[0] + 2].SetLabel('0.10') for i_sensor in self.T_number: self.SensorValue[i_sensor - self.T_number[0] + len(self.p_number) + 2].SetLabel(str(int(self.df.iloc[-1, i_sensor]))) #self.SensorValue[i_sensor-self.T_number[0]+len(self.p_number)+2].SetLabel(str(np.round(self.df.iloc[-1, i_sensor]))) # Alert Pple,o (Threshold : 1.0 MPa) if self.df.iloc[-1, self.p_number[8]] > 1.0: self.SensorValue[self.p_number[8] - self.p_number[0]].SetForegroundColour('RED') else: self.SensorValue[self.p_number[8] - self.p_number[0]].SetForegroundColour('GREEN') # Alert Tth,rde (Threshold : 500 K) if self.df.iloc[-1, self.T_number[6]] > 500.0: self.SensorValue[self.T_number[6] - self.T_number[0] + len(self.p_number)].SetForegroundColour('RED') else: self.SensorValue[self.T_number[6] - self.T_number[0] + len(self.p_number)].SetForegroundColour('GREEN') # Alert Tc,pde (Threshold : 500 K) if self.df.iloc[-1, self.T_number[7]] > 500.0: self.SensorValue[self.T_number[7] - self.T_number[0] + len(self.p_number)].SetForegroundColour('RED') else: self.SensorValue[self.T_number[7] - self.T_number[0] + len(self.p_number)].SetForegroundColour('GREEN')
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
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()
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)
class AttitudePanel(wx.Panel): def __init__(self, parent, stl, data, reflesh_time): super().__init__(parent, wx.ID_ANY) self.stl = stl self.stl.x -= 2.5 self.stl.y -= 1.37 self.stl.z -= 10.0 self.df = data self.i = 0 self.chartGenerator() layout = wx.GridSizer(rows=1, cols=1, gap=(0, 0)) layout.Add(self.canvas, flag=wx.FIXED_MINSIZE) self.SetSizer(layout) self.timer_reload = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.graphReloader, self.timer_reload) self.timer_reload.Start(reflesh_time) def chartGenerator(self): """ Generate data for Real time plot test """ self.fig = Figure(figsize=(3, 3)) self.ax = mplot3d.Axes3D(self.fig) self.canvas = FigureCanvasWxAgg(self, -1, self.fig) self.line0 = mplot3d.art3d.Line3DCollection(self.stl.vectors, linewidths=0.05, colors="blue") self.ax.add_collection3d(self.line0) self.scale = self.stl.points.flatten() self.ax.auto_scale_xyz(self.scale + 5, self.scale + 2, self.scale) self.ax.grid(False) self.ax.set_axis_off() self.canvas.draw() self.background = self.canvas.copy_from_bbox( self.ax.bbox) # Save Empty Chart Format as Background def graphReloader(self, event): self.i += 1 if self.i > len(self.df): sys.exit() self.stl_rotate = self.rotate_stl(stl=self.stl, roll=self.df.iat[self.i, 1], pitch=self.df.iat[self.i, 2], yaw=self.df.iat[self.i, 3]) # Clear the current axes self.ax.cla() self.ax.grid(False) self.ax.set_axis_off() self.ax.add_collection3d( mplot3d.art3d.Line3DCollection(self.stl_rotate.vectors, linewidths=0.05, colors="blue")) self.ax.auto_scale_xyz(self.scale + 5, self.scale + 2, self.scale) self.canvas.draw() def rotate_stl(self, stl, roll, pitch, yaw): """ Rotate stl in the (roll, pitch, yaw) direction """ stl.rotate([1, 0, 0], np.deg2rad(roll)) # rotate stl model in roll angle stl.rotate([0, 1, 0], np.deg2rad(pitch)) # rotate stl model in pitch angle stl.rotate([0, 0, 1], np.deg2rad(yaw)) # rotate stl model in yaw angle return stl
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 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 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)
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()
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)
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
class Plots ( object ): def __init__( self, panels, sizers, id, cam ): self.panels = panels self.sizers = sizers self.id = id self.cam = cam self.CM = np.array([0,0]) self.figC = Figure() #tight_layout=True) # dpi=30, tight_layout=True, frameon=False self.figX = Figure() #tight_layout=True) self.figY = Figure() #tight_layout=True) self.canvasC = FigCanvas(panels[0], -1, self.figC); self.canvasC.SetMinSize(wx.Size(1,1)) self.canvasX = FigCanvas(panels[1], -1, self.figX); self.canvasX.SetMinSize(wx.Size(1,1)) self.canvasY = FigCanvas(panels[2], -1, self.figY); self.canvasY.SetMinSize(wx.Size(1,1)) # Dando este argumento se arregla el problema de tener espacios blancos al borde self.axesC = self.figC.add_axes([0., 0., 1., 1.]) #self.figC.add_subplot(111) self.axesX = self.figX.add_axes([0., 0., 1., 1.]) self.axesY = self.figY.add_axes([0., 0., 1., 1.]) sizers[0].Add(self.canvasC, 1, wx.ALL|wx.EXPAND, border=1) sizers[1].Add(self.canvasX, 1, wx.ALL|wx.EXPAND, border=1) sizers[2].Add(self.canvasY, 1, wx.ALL|wx.EXPAND, border=1) x = np.array( range(WIDTH) ) x_ = x[80:120] # self.plot_dataC = self.axesC.scatter([100], [100], s=20) self.plot_dataC = self.axesC.plot(x_, x_, "+", mew=10, color=(0, 0, 1),)[0] self.plot_dataX = self.axesX.plot(x, x, linewidth=1, color=(0, 0, 1),)[0] self.plot_dataY = self.axesY.plot(x, x, linewidth=1, color=(0, 0, 1),)[0] self.firstPlot = 0 # self.axesC.set_xbound(lower=80, upper=120); self.axesC.set_ybound(lower=80, upper=120); #self.axesC.grid(True) # dev = 5.0; cent = WIDTH/2.0 # low = cent-dev; up = cent+dev # print low, " ", up # self.axesC.set_xbound(lower=low, upper=up); self.axesC.set_ybound(lower=low, upper=up); #self.axesC.grid(True) self.axesX.set_xbound(lower=0, upper=WIDTH); self.axesX.set_ybound(lower=0, upper=100); #self.axesX.grid(True) self.axesY.set_xbound(lower=0, upper=100); self.axesY.set_ybound(lower=0, upper=WIDTH); #self.axesY.grid(True) if id in [0, 2]: self.axesY.invert_xaxis() if id in [2, 3]: self.axesX.invert_yaxis() self.axesC.invert_yaxis() self.axesY.invert_yaxis() self.axesC.get_xaxis().set_visible(False); self.axesC.get_yaxis().set_visible(False) self.axesX.get_xaxis().set_visible(False); self.axesX.get_yaxis().set_visible(False) self.axesY.get_xaxis().set_visible(False); self.axesY.get_yaxis().set_visible(False) # self.axesC.set_axis_off() # self.axesX.set_axis_off() # self.axesY.set_axis_off() self.axesC.axis('image') self.axesX.axis('image') self.axesY.axis('image') self.canvasC.draw() self.canvasX.draw() self.canvasY.draw() def CalculateProfiles ( self, frame ): if self.firstPlot < 1: self.background = self.canvasC.copy_from_bbox(self.axesC.bbox) self.firstPlot += 1 for i in range(3): self.panels[i].Layout() # Necesario para re-ajustar la escala else: x1 = np.array(range(HEIGHT)) x2 = np.array(range(WIDTH)) y1 = np.array([ frame[:,i].sum() for i in xrange(HEIGHT) ], dtype=np.double) y2 = np.array([ frame[i,:].sum() for i in xrange(WIDTH) ], dtype=np.double) y1 = y1 / (y1.max()+1) * 100.0 y2 = y2 / (y2.max()+1) * 100.0 self.CM = ndimage.measurements.center_of_mass(frame) # print CM self.figC.suptitle("Sat = " + str(self.cam.saturation[self.id] * 100.0) + "%") self.plot_dataC.set_xdata([self.CM[1]]); self.plot_dataC.set_ydata([self.CM[0]]); self.canvasC.draw(); #wx.Yield() self.plot_dataX.set_xdata(x1); self.plot_dataX.set_ydata(y1); self.canvasX.draw(); #wx.Yield() self.plot_dataY.set_xdata(y2); self.plot_dataY.set_ydata(x2); self.canvasY.draw(); #wx.Yield()
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))
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
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
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)
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)))
class MPL_Panel_base(wx.Panel): ''' #MPL_Panel_base面板,可以继承或者创建实例''' def __init__(self,parent): wx.Panel.__init__(self,parent=parent, id=-1) self.Figure = matplotlib.figure.Figure(figsize=(8,6)) self.axes = self.Figure.add_axes([0.1,0.1,0.8,0.8]) self.FigureCanvas = FigureCanvas(self,-1,self.Figure) self.NavigationToolbar = NavigationToolbar(self.FigureCanvas) self.StaticText = wx.StaticText(self,-1,label='Show Help String') self.SubBoxSizer = wx.BoxSizer(wx.HORIZONTAL) self.SubBoxSizer.Add(self.NavigationToolbar,proportion =0, border = 2,flag = wx.ALL | wx.EXPAND) self.SubBoxSizer.Add(self.StaticText,proportion =-1, border = 2,flag = wx.ALL | wx.EXPAND) self.TopBoxSizer = wx.BoxSizer(wx.VERTICAL) self.TopBoxSizer.Add(self.SubBoxSizer,proportion =-1, border = 2,flag = wx.ALL | wx.EXPAND) self.TopBoxSizer.Add(self.FigureCanvas,proportion =-10, border = 2,flag = wx.ALL | wx.EXPAND) self.SetSizer(self.TopBoxSizer) ###方便调用 self.pylab=pylab self.pl=pylab self.pyplot=pyplot self.numpy=np self.np=np self.plt=pyplot self.bg = self.FigureCanvas.copy_from_bbox(self.axes.bbox) #self.xticker() self.axes.set_autoscale_on(False) self.xlim(0,POINTS) self.ylim(0,100) def UpdatePlot(self): '''#修改图形的任何属性后都必须使用self.UpdatePlot()更新GUI界面 ''' self.grid(True) self.xlim(0,POINTS) self.ylim(0,100) self.FigureCanvas.draw() def plot(self,*args,**kwargs): '''#最常用的绘图命令plot ''' self.axes.plot(*args,**kwargs) self.UpdatePlot() def semilogx(self,*args,**kwargs): ''' #对数坐标绘图命令 ''' self.axes.semilogx(*args,**kwargs) self.UpdatePlot() def semilogy(self,*args,**kwargs): ''' #对数坐标绘图命令 ''' self.axes.semilogy(*args,**kwargs) self.UpdatePlot() def loglog(self,*args,**kwargs): ''' #对数坐标绘图命令 ''' self.axes.loglog(*args,**kwargs) self.UpdatePlot() def grid(self,flag=True): ''' ##显示网格 ''' if flag: self.axes.grid() else: self.axes.grid(False) def title_MPL(self,TitleString="wxMatPlotLib Example In wxPython"): ''' # 给图像添加一个标题 ''' self.axes.set_title(TitleString) def xlabel(self,XabelString="X"): ''' # Add xlabel to the plotting ''' self.axes.set_xlabel(XabelString) def ylabel(self,YabelString="Y"): ''' # Add ylabel to the plotting ''' self.axes.set_ylabel(YabelString) def xticker(self,major_ticker=5,minor_ticker=5): ''' # 设置X轴的刻度大小 ''' self.axes.xaxis.set_major_locator( MultipleLocator(major_ticker) ) self.axes.xaxis.set_minor_locator( MultipleLocator(minor_ticker) ) def yticker(self,major_ticker=5,minor_ticker=5): ''' # 设置Y轴的刻度大小 ''' self.axes.yaxis.set_major_locator( MultipleLocator(major_ticker) ) self.axes.yaxis.set_minor_locator( MultipleLocator(minor_ticker) ) def legend(self,*args,**kwargs): ''' #图例legend for the plotting ''' self.axes.legend(*args,**kwargs) def xlim(self,x_min,x_max): ''' # 设置x轴的显示范围 ''' self.axes.set_xlim(x_min,x_max) def ylim(self,y_min,y_max): ''' # 设置y轴的显示范围 ''' self.axes.set_ylim(y_min,y_max) def savefig(self,*args,**kwargs): ''' #保存图形到文件 ''' self.Figure.savefig(*args,**kwargs) def cla(self): ''' # 再次画图前,必须调用该命令清空原来的图形 ''' self.axes.clear() #self.Figure.set_canvas(self.FigureCanvas) #self.UpdatePlot() def ShowHelpString(self,HelpString="Show Help String"): ''' #可以用它来显示一些帮助信息,如鼠标位置等 ''' self.StaticText.SetLabel(HelpString)
class con_states_panel1(wx.Panel): def __init__(self, *args, **kwds): # begin wxGlade: con_states_panel1.__init__ kwds["style"] = wx.TAB_TRAVERSAL wx.Panel.__init__(self, *args, **kwds) self.__set_properties() self.__do_layout() # end wxGlade self.figure = Figure(figsize=(6,4), dpi=80) self.axes_x = self.figure.add_subplot(211) self.axes_vol = self.figure.add_subplot(212) self.canvas = FigureCanvas(self, wx.ID_ANY, self.figure) self.axes_x.set_autoscale_on(False) self.axes_x.set_xlim([0,100]) self.axes_x.set_ylim([-5,5]) self.axes_x.set_xticks(range(0,101,100)) #self.axes_x.set_yticks(range(-10,11,2)) self.exp_x = [None] * 100 self.percentile_x_95 = [None] * 100 self.percentile_x_5 = [None] * 100 self.real_x = [None] * 100 self.axes_vol.set_autoscale_on(False) self.axes_vol.set_xlim([0,100]) self.axes_vol.set_ylim([0,6]) self.axes_vol.set_xticks(range(0,101,5)) #self.axes_vol.set_yticks(range(0,7,1)) self.exp_vol = [None] * 100 self.percentile_vol_95 = [None] * 100 self.percentile_vol_5 = [None] * 100 self.real_vol = [None] * 100 self.real_x_up2now = [None] * 100 self.real_vol_up2now = [None] * 100 self.con_states_file = open('con_states') for i in range(100): self.real_x[i] = float(self.con_states_file.readline()) self.real_vol[i] = float(self.con_states_file.readline()) self.con_states_file.close() self.l_exp_x, = self.axes_x.plot(range(100), self.exp_x, label='estimated value') #plot return one element tuple self.l_real_x, = self.axes_x.plot(range(100), self.real_x_up2now, label='real value') self.l_percentile_x_95, = self.axes_x.plot(range(100), self.percentile_x_95, label='95% percentile') self.l_percentile_x_5, = self.axes_x.plot(range(100), self.percentile_x_5, label='5% percentile') self.axes_x.legend(loc='upper center', ncol=4, prop=font_manager.FontProperties(size=8)) self.axes_x.set_title('return') self.l_exp_vol, = self.axes_vol.plot(range(100), self.exp_vol, label='estimated value') #plot return one element tuple self.l_real_vol, = self.axes_vol.plot(range(100), self.real_vol_up2now, label='real value') self.l_percentile_vol_95, = self.axes_vol.plot(range(100), self.percentile_vol_95, label='95% percentile') self.l_percentile_vol_5, = self.axes_vol.plot(range(100), self.percentile_vol_5, label='5% percentile') #self.axes_vol.legend(loc='upper center', ncol=4, prop=font_manager.FontProperties(size=10)) self.axes_vol.set_title('volatility') self.axes_vol.set_xlabel('time (s)') self.canvas.draw() self.bg_x = self.canvas.copy_from_bbox(self.axes_x.bbox) self.bg_vol = self.canvas.copy_from_bbox(self.axes_vol.bbox) def __set_properties(self): # begin wxGlade: con_states_panel1.__set_properties pass # end wxGlade def __do_layout(self): # begin wxGlade: con_states_panel1.__do_layout pass
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()
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): """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 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))
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)))