Matplotlib: scrolling plot

前端 未结 1 1836
無奈伤痛
無奈伤痛 2021-01-21 08:58

I\'m new to Python and I want to implement a scrolling plot for a very long time series data. I\'ve found an example from Matplotlib as follows.

http://scipy-cookbook.re

相关标签:
1条回答
  • 2021-01-21 09:19

    Here's an improved version of the example. (Disclaimer: I started digging into it half an hour ago, never before used wx/matplotlib scrollbars so there might be a much better solution.)

    The path I took: first I checked the wx scroll events, then found out that the canvas is FigureCanvasWxAgg derived from wxPanel, inheriting wxWindow methods. There you may find the scroll position handling methods GetScrollPos and SetScrollPos.

    from numpy import arange, sin, pi, float, size
    
    import matplotlib
    matplotlib.use('WXAgg')
    from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
    from matplotlib.figure import Figure
    
    import wx
    
    class MyFrame(wx.Frame):
        def __init__(self, parent, id):
            wx.Frame.__init__(self,parent, id, 'scrollable plot',
                    style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER,
                    size=(800, 400))
            self.panel = wx.Panel(self, -1)
    
            self.fig = Figure((5, 4), 75)
            self.canvas = FigureCanvasWxAgg(self.panel, -1, self.fig)
            self.scroll_range = 400
            self.canvas.SetScrollbar(wx.HORIZONTAL, 0, 5,
                                     self.scroll_range)
    
            sizer = wx.BoxSizer(wx.VERTICAL)
            sizer.Add(self.canvas, -1, wx.EXPAND)
    
            self.panel.SetSizer(sizer)
            self.panel.Fit()
    
            self.init_data()
            self.init_plot()
    
            self.canvas.Bind(wx.EVT_SCROLLWIN, self.OnScrollEvt)
    
        def init_data(self):
    
            # Generate some data to plot:
            self.dt = 0.01
            self.t = arange(0,5,self.dt)
            self.x = sin(2*pi*self.t)
    
            # Extents of data sequence:
            self.i_min = 0
            self.i_max = len(self.t)
    
            # Size of plot window:
            self.i_window = 100
    
            # Indices of data interval to be plotted:
            self.i_start = 0
            self.i_end = self.i_start + self.i_window
    
        def init_plot(self):
            self.axes = self.fig.add_subplot(111)
            self.plot_data = \
                      self.axes.plot(self.t[self.i_start:self.i_end],
                                     self.x[self.i_start:self.i_end])[0]
    
        def draw_plot(self):
    
            # Update data in plot:
            self.plot_data.set_xdata(self.t[self.i_start:self.i_end])
            self.plot_data.set_ydata(self.x[self.i_start:self.i_end])
    
            # Adjust plot limits:
            self.axes.set_xlim((min(self.t[self.i_start:self.i_end]),
                               max(self.t[self.i_start:self.i_end])))
            self.axes.set_ylim((min(self.x[self.i_start:self.i_end]),
                                max(self.x[self.i_start:self.i_end])))
    
            # Redraw:
            self.canvas.draw()
    
        def update_scrollpos(self, new_pos):
            self.i_start = self.i_min + new_pos
            self.i_end = self.i_min + self.i_window + new_pos
            self.canvas.SetScrollPos(wx.HORIZONTAL, new_pos)
            self.draw_plot()
    
        def OnScrollEvt(self, event):
            evtype = event.GetEventType()
    
            if evtype == wx.EVT_SCROLLWIN_THUMBTRACK.typeId:
                pos = event.GetPosition()
                self.update_scrollpos(pos)
            elif evtype == wx.EVT_SCROLLWIN_LINEDOWN.typeId:
                pos = self.canvas.GetScrollPos(wx.HORIZONTAL)
                self.update_scrollpos(pos + 1)
            elif evtype == wx.EVT_SCROLLWIN_LINEUP.typeId:
                pos = self.canvas.GetScrollPos(wx.HORIZONTAL)
                self.update_scrollpos(pos - 1)
            elif evtype == wx.EVT_SCROLLWIN_PAGEUP.typeId:
                pos = self.canvas.GetScrollPos(wx.HORIZONTAL)
                self.update_scrollpos(pos - 10)
            elif evtype == wx.EVT_SCROLLWIN_PAGEDOWN.typeId:
                pos = self.canvas.GetScrollPos(wx.HORIZONTAL)
                self.update_scrollpos(pos + 10)
            else:
                print "unhandled scroll event, type id:", evtype
    
    class MyApp(wx.App):
        def OnInit(self):
            self.frame = MyFrame(parent=None,id=-1)
            self.frame.Show()
            self.SetTopWindow(self.frame)
            return True
    
    if __name__ == '__main__':
        app = MyApp()
        app.MainLoop()
    

    You may adjust e.g. the increments for PAGEUP/PAGEDOWN if you feel it too slow.

    Also if you wish, the events can be handled separately setting up the specific event handlers instead of their collection EVT_SCROLLWIN, then instead of if/elifs there will be OnScrollPageUpEvt etc.

    0 讨论(0)
提交回复
热议问题