ロジスティック写像をプロットする(5)

  • 今回の改良点
    • matplotlibで描いた絵をファイルに保存して貼り付けるのではなく直接wxで使うように変更。
    • グラフ描画をthreadモジュールで実行するようにする。
  • 改良の結果...
    • グラフ描画が高速になった(ような気がする)。
    • 安定に動作するようになった。stopボタンでちゃんと止まる。

これにより、ちゃんと動くようになった。

ここまでのソースは次の通り。

import wx
import matplotlib
matplotlib.use('WXAgg')
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
import thread
import os
import time
from pylab import *

class MainFrame(wx.Frame):
    def __init__(self, id, title):
        width, height = -1, -1
        wx.Frame.__init__(self, id, title="Logistic equation",
                          size=wx.Size(width, height))
        Pan = wx.Panel(self, -1)
        figure = matplotlib.figure.Figure()
        self.canvas = FigureCanvasWxAgg(Pan, wx.ID_ANY, figure)
        self.plot = figure.add_subplot(111, xlabel='n', ylabel='X')

        Sizer0 = wx.BoxSizer(wx.VERTICAL)
        Sizer1 = wx.BoxSizer(wx.HORIZONTAL)
        Sizer2 = wx.BoxSizer(wx.HORIZONTAL)
        Sizer3 = wx.BoxSizer(wx.HORIZONTAL)
        
        StTxt1 = wx.StaticText(Pan, -1, "Constant 0<a<4 :")
        StTxt2 = wx.StaticText(Pan, -1, "Initial Value 0<X0<1:")
        self.TxtCtrl1 = wx.TextCtrl(Pan, -1, "3.8", size=(50, -1))
        self.TxtCtrl2 = wx.TextCtrl(Pan, -1, "0.5", size=(50, -1))
        
        self.RBtn1 = wx.Button(Pan, -1, "Start")
        self.RBtn2 = wx.Button(Pan, -1, "Stop ")
        self.RBtn1.Bind(wx.EVT_BUTTON, self.Start)
        self.RBtn2.Bind(wx.EVT_BUTTON, self.Stop)

        Sizer1.Add(StTxt1, 0, wx.ALL, 2)
        Sizer1.Add(self.TxtCtrl1, 0, wx.ALL, 2)
        Sizer2.Add(StTxt2, 0, wx.ALL, 2)
        Sizer2.Add(self.TxtCtrl2, 0, wx.ALL, 2)
        Sizer3.Add(self.RBtn1, 0, wx.ALL, 2)
        Sizer3.Add(self.RBtn2, 0, wx.ALL, 2)
        Sizer0.Add(self.canvas, 0, wx.ALL, 2)
        Sizer0.Add(Sizer1, 0, wx.ALL, 2)
        Sizer0.Add(Sizer2, 0, wx.ALL, 2)
        Sizer0.Add(Sizer3, 0, wx.ALL, 2)
        Pan.SetSizer(Sizer0)
        Sizer0.Fit(self)

    def Start(self, event):
        thread.start_new_thread(self.Run, ())

    def Run(self):
        const_a = float(self.TxtCtrl1.GetValue())
        x_init  = float(self.TxtCtrl2.GetValue())

        x=x_init
        n = 0
        self.RunFlag = 1
        while True:
            n = n + 1
            if self.RunFlag:
                nval = arange(n)
                xval = []
                for i in nval:
                    y = const_a *x*(1.0-x)
                    xval.append(y)
                    x = y
                self.MakeFig(nval, xval)
                x = xval[0]
            else:
                break  # これ重要!

    def Stop(self, event):
        self.RunFlag = 0

    def MakeFig(self, nval, xval):
        self.plot.plot(nval, xval, 'o', markersize=1)
        self.canvas.draw()
        
class Application(wx.App):
    def OnInit(self):
        frame = MainFrame(None, -1)
        frame.Show(True)
        self.SetTopWindow(frame)
        return True

def main():
    import time
    app = Application(0)
    print "info> start-up time: %s." % time.ctime(time.time())
    appl_boot_path = os.getcwd()
    print "info> start-up directory: %s." % appl_boot_path
    app.MainLoop()

if __name__ == '__main__':
    main()