Example #1
0
class TestFrame(wx.Frame):
    def __init__(self, parent=None, *args, **kwds):

        kwds["style"] = wx.DEFAULT_FRAME_STYLE | wx.RESIZE_BORDER | wx.TAB_TRAVERSAL

        wx.Frame.__init__(self, parent, wx.NewId(), "", wx.DefaultPosition, wx.Size(-1, -1), **kwds)
        self.SetTitle(" WXMPlot Plotting Demo")

        self.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD, False))
        menu = wx.Menu()
        ID_EXIT = wx.NewId()

        menu_exit = menu.Append(ID_EXIT, "E&xit", "Terminate the program")

        menuBar = wx.MenuBar()
        menuBar.Append(menu, "&File")
        self.SetMenuBar(menuBar)

        self.Bind(wx.EVT_MENU, self.OnExit, menu_exit)

        self.Bind(wx.EVT_CLOSE, self.OnExit)  # CloseEvent)

        self.plotframe = None

        self.create_data()
        framesizer = wx.BoxSizer(wx.VERTICAL)

        panel = wx.Panel(self, -1, size=(-1, -1))
        panelsizer = wx.BoxSizer(wx.VERTICAL)

        panelsizer.Add(
            wx.StaticText(panel, -1, "wxmplot 2D PlotPanel examples "),
            0,
            wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT | wx.EXPAND,
            10,
        )

        b10 = wx.Button(panel, -1, "Example #1", size=(-1, -1))
        b20 = wx.Button(panel, -1, "Example #2", size=(-1, -1))
        b22 = wx.Button(panel, -1, "Plot with 2 axes", size=(-1, -1))
        b31 = wx.Button(panel, -1, "Plot with Errorbars", size=(-1, -1))
        b32 = wx.Button(panel, -1, "SemiLog Plot", size=(-1, -1))
        b40 = wx.Button(panel, -1, "Start Timed Plot", size=(-1, -1))
        b50 = wx.Button(panel, -1, "Stop Timed Plot", size=(-1, -1))
        b60 = wx.Button(panel, -1, "Plot 500,000 points", size=(-1, -1))

        b10.Bind(wx.EVT_BUTTON, self.onPlot1)
        b20.Bind(wx.EVT_BUTTON, self.onPlot2)
        b22.Bind(wx.EVT_BUTTON, self.onPlot2Axes)
        b31.Bind(wx.EVT_BUTTON, self.onPlotErr)
        b32.Bind(wx.EVT_BUTTON, self.onPlotSLog)
        b40.Bind(wx.EVT_BUTTON, self.onStartTimer)
        b50.Bind(wx.EVT_BUTTON, self.onStopTimer)
        b60.Bind(wx.EVT_BUTTON, self.onPlotBig)

        panelsizer.Add(b10, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5)
        panelsizer.Add(b20, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5)
        panelsizer.Add(b22, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5)
        panelsizer.Add(b31, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5)
        panelsizer.Add(b32, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5)
        panelsizer.Add(b40, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5)
        panelsizer.Add(b50, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5)
        panelsizer.Add(b60, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5)

        panel.SetSizer(panelsizer)
        panelsizer.Fit(panel)

        framesizer.Add(panel, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.EXPAND, 2)
        self.SetSizer(framesizer)
        framesizer.Fit(self)

        self.Bind(wx.EVT_TIMER, self.onTimer)
        self.timer = wx.Timer(self)
        self.Refresh()

    def create_data(self):
        self.count = 0
        self.x = x = arange(0.0, 25.0, 0.1)
        self.y1 = 4 * cos(2 * pi * (x - 1) / 5.7) / (6 + x) + 2 * sin(2 * pi * (x - 1) / 2.2) / (10)
        self.y2 = sin(2 * pi * x / 30.0)
        self.y3 = -pi + 2 * (x / 10.0 + exp(-(x - 3) / 5.0))
        self.y4 = exp(0.01 + 0.5 * x) / (x + 2)
        self.y5 = 3000 * self.y3
        self.npts = len(self.x)
        self.bigx = linspace(0, 2500, 500000)
        self.bigy = sin(pi * self.bigx / 140.0) + cos(pi * self.bigx / 277.0) + cos(pi * self.bigx / 820.0)

    def ShowPlotFrame(self, do_raise=True, clear=True):
        "make sure plot frame is enabled, and visible"
        if self.plotframe is None:
            self.plotframe = PlotFrame(self)
            self.has_plot = False
        try:
            self.plotframe.Show()
        except PyDeadObjectError:
            self.plotframe = PlotFrame(self)
            self.plotframe.Show()

        if do_raise:
            self.plotframe.Raise()
        if clear:
            self.plotframe.panel.clear()
            self.plotframe.reset_config()

    def onPlot1(self, event=None):
        self.ShowPlotFrame()
        self.plotframe.plot(self.x, self.y1)
        self.plotframe.oplot(self.x, self.y2)
        self.plotframe.write_message("Plot 1")

    def onPlot2(self, event=None):
        self.ShowPlotFrame()
        x = arange(100)
        y1 = cos(pi * x / 72)
        y2 = sin(pi * x / 23)
        self.plotframe.plot(x, y1, color="red")
        self.plotframe.oplot(x, y2, color="green3", marker="+")
        self.plotframe.write_message("Plot 2")

    def onPlotErr(self, event=None):
        self.ShowPlotFrame()
        npts = 81
        x = linspace(0, 40.0, npts)
        y = 0.4 * cos(x / 2.0) + random.normal(scale=0.03, size=npts)
        dy = 0.03 * (ones(npts) + random.normal(scale=0.2, size=npts))

        self.plotframe.plot(
            x, y, dy=dy, color="red", linewidth=0, xlabel="x", ylabel="y", marker="o", title="Plot with error bars"
        )
        self.plotframe.write_message("Errorbars!")

    def onPlot2Axes(self, event=None):
        self.ShowPlotFrame()

        self.plotframe.plot(self.x, self.y2, color="black", style="dashed")
        self.plotframe.oplot(self.x, self.y5, color="red", side="right")
        self.plotframe.write_message("Plot with 2 axes")

    def onPlotSLog(self, event=None):
        self.ShowPlotFrame()

        self.plotframe.plot(self.x, self.y4, ylog_scale=True, color="black", style="dashed")
        self.plotframe.write_message("Semi Log Plot")

    def onPlotBig(self, event=None):
        self.ShowPlotFrame()

        t0 = time.time()
        self.plotframe.plot(self.bigx, self.bigy, marker="+", linewidth=0)
        dt = time.time() - t0
        self.plotframe.write_message("Plot array with npts=%i, elapsed time=%8.3f s" % (len(self.bigx), dt))

    def report_memory(i):
        pid = os.getpid()
        if os.name == "posix":
            mem = os.popen("ps -o rss -p %i" % pid).readlines()[1].split()[0]
        else:
            mem = 0
        return int(mem)

    def onStartTimer(self, event=None):
        self.count = 0
        self.up_count = 0
        self.n_update = 1
        self.datrange = None
        self.time0 = time.time()
        self.start_mem = self.report_memory()
        self.timer.Start(10)

    def timer_results(self):
        if self.count < 2:
            return
        etime = time.time() - self.time0
        tpp = etime / max(1, self.count)
        s = "drew %i points in %8.3f s: time/point= %8.4f s" % (self.count, etime, tpp)
        self.plotframe.write_message(s)
        self.time0 = 0
        self.count = 0
        self.datrange = None

    def onStopTimer(self, event=None):
        self.timer.Stop()
        try:
            self.timer_results()
        except:
            pass

    def onTimer(self, event):
        # print 'timer ', self.count, time.time()
        self.count += 1
        self.ShowPlotFrame(do_raise=False, clear=False)
        n = self.count
        if n < 2:
            return
        if n >= self.npts:
            self.timer.Stop()
            self.timer_results()
        elif n <= 3:
            self.plotframe.plot(self.x[:n], self.y1[:n])  # , grid=False)

        else:
            self.plotframe.update_line(0, self.x[:n], self.y1[:n], update_limits=n < 10, draw=True)

            etime = time.time() - self.time0
            s = " %i / %i points in %8.4f s" % (n, self.npts, etime)
            self.plotframe.write_message(s)

        if self.datrange is None:
            self.datrange = [min(self.x[:n]), max(self.x[:n]), min(self.y1[:n]), max(self.y1[:n])]

        dr = [min(self.x[:n]), max(self.x[:n]), min(self.y1[:n]), max(self.y1[:n])]
        lims = self.plotframe.panel.get_viewlimits()
        if dr[0] < lims[0] or dr[1] > lims[1] or dr[2] < lims[2] or dr[3] > lims[3]:
            self.datrange = dr
            if n < len(self.x):
                nmax = min(int(n * 1.6), len(self.x) - 1)
                self.datrange[1] = self.x[nmax]
            self.plotframe.panel.set_xylims(self.datrange)

    #        if (n > self.n_update-1) or
    #             (xr[0] < xv[0]) or (xr[1] > xv[1]) or
    #             (yr[0] < yv[0]) or (yr[1] > yv[1])):
    #             nx = self.n_update = min(self.npts,3+int(self.n_update*2.0))
    #             if nx > int(0.92*self.npts):
    #                 nx = self.n_update = self.npts
    #                 xylims = (min(self.x),max(self.x),
    #                           min(self.y1),max(self.y1))
    #             else:
    #                 xylims = (min(self.x[0:nx]),max(self.x[0:nx]),
    #                           min(self.y1[0:nx]),max(self.y1[0:nx]))
    #             self.up_count = self.up_count + 1
    #             self.plotframe.panel.set_xylims(xylims)

    def OnAbout(self, event):
        dlg = wx.MessageDialog(
            self,
            "This sample program shows some\n" "examples of MPlot PlotFrame.\n" "message dialog.",
            "About MPlot test",
            wx.OK | wx.ICON_INFORMATION,
        )
        dlg.ShowModal()
        dlg.Destroy()

    def OnExit(self, event):
        try:
            if self.plotframe != None:
                self.plotframe.onExit()
        except:
            pass
        self.Destroy()
Example #2
0
class TestFrame(wx.Frame):
    def __init__(self, parent=None, *args, **kwds):

        kwds[
            "style"] = wx.DEFAULT_FRAME_STYLE | wx.RESIZE_BORDER | wx.TAB_TRAVERSAL

        wx.Frame.__init__(self, parent, -1, '', wx.DefaultPosition,
                          wx.Size(-1, -1), **kwds)
        self.SetTitle(" WXMPlot Plotting Demo")

        self.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD, False))
        menu = wx.Menu()
        menu_exit = menu.Append(-1, "E&xit", "Terminate the program")

        menuBar = wx.MenuBar()
        menuBar.Append(menu, "&File")
        self.SetMenuBar(menuBar)

        self.Bind(wx.EVT_MENU, self.OnExit, menu_exit)

        self.Bind(wx.EVT_CLOSE, self.OnExit)

        self.plotframe = None

        self.create_data()
        framesizer = wx.BoxSizer(wx.VERTICAL)

        panel = wx.Panel(self, -1, size=(-1, -1))
        panelsizer = wx.BoxSizer(wx.VERTICAL)

        panelsizer.Add(
            wx.StaticText(panel, -1, 'wxmplot 2D PlotPanel examples '), 0,
            wx.ALIGN_LEFT | wx.LEFT | wx.EXPAND, 10)

        b10 = wx.Button(panel, -1, 'Example #1', size=(-1, -1))
        b20 = wx.Button(panel, -1, 'Example #2', size=(-1, -1))
        b22 = wx.Button(panel, -1, 'Plot with 2 axes', size=(-1, -1))
        b31 = wx.Button(panel, -1, 'Plot with Errorbars', size=(-1, -1))
        b32 = wx.Button(panel, -1, 'SemiLog Plot', size=(-1, -1))
        b40 = wx.Button(panel, -1, 'Start Timed Plot', size=(-1, -1))
        b50 = wx.Button(panel, -1, 'Stop Timed Plot', size=(-1, -1))
        b60 = wx.Button(panel, -1, 'Plot 500,000 points', size=(-1, -1))
        bmany1 = wx.Button(panel,
                           -1,
                           'Plot 20 traces (delay_draw=False)',
                           size=(-1, -1))
        bmany2 = wx.Button(panel,
                           -1,
                           'Plot 20 traces (delay_draw=True)',
                           size=(-1, -1))
        bmany3 = wx.Button(panel,
                           -1,
                           'Plot 20 traces (use plot_many())',
                           size=(-1, -1))

        b10.Bind(wx.EVT_BUTTON, self.onPlot1)
        b20.Bind(wx.EVT_BUTTON, self.onPlot2)
        b22.Bind(wx.EVT_BUTTON, self.onPlot2Axes)
        b31.Bind(wx.EVT_BUTTON, self.onPlotErr)
        b32.Bind(wx.EVT_BUTTON, self.onPlotSLog)
        b40.Bind(wx.EVT_BUTTON, self.onStartTimer)
        b50.Bind(wx.EVT_BUTTON, self.onStopTimer)
        b60.Bind(wx.EVT_BUTTON, self.onPlotBig)

        bmany1.Bind(wx.EVT_BUTTON, self.onPlotMany_Slow)
        bmany2.Bind(wx.EVT_BUTTON, self.onPlotMany_Delay)
        bmany3.Bind(wx.EVT_BUTTON, self.onPlotMany_Fast)

        panelsizer.Add(b10, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5)
        panelsizer.Add(b20, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5)
        panelsizer.Add(b22, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5)
        panelsizer.Add(b31, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5)
        panelsizer.Add(b32, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5)
        panelsizer.Add(b40, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5)
        panelsizer.Add(b50, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5)
        panelsizer.Add(b60, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5)

        panelsizer.Add(bmany1, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5)
        panelsizer.Add(bmany2, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5)
        panelsizer.Add(bmany3, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5)

        panel.SetSizer(panelsizer)
        panelsizer.Fit(panel)

        framesizer.Add(panel, 0, wx.ALIGN_LEFT | wx.EXPAND, 2)
        self.SetSizer(framesizer)
        framesizer.Fit(self)

        self.Bind(wx.EVT_TIMER, self.onTimer)
        self.timer = wx.Timer(self)
        self.Refresh()

    def create_data(self):
        self.count = 0
        self.x = x = arange(0.0, 25.0, 0.1)
        self.y1 = 4 * cos(2 * pi * (x - 1) / 5.7) / (6 + x) + 2 * sin(
            2 * pi * (x - 1) / 2.2) / (10)
        self.y2 = sin(2 * pi * x / 30.0)
        self.y3 = -pi + 2 * (x / 10. + exp(-(x - 3) / 5.0))
        self.y4 = exp(0.01 + 0.5 * x) / (x + 2)
        self.y5 = 3000 * self.y3
        self.npts = len(self.x)
        self.bigx = linspace(0, 2500, 500000)
        self.bigy = (sin(pi * self.bigx / 140.0) +
                     cos(pi * self.bigx / 277.0) + cos(pi * self.bigx / 820.0))

        self.many_dlist = [(self.x, self.y1)]
        for i in range(19):
            self.many_dlist.append((self.x, sin(2 * (i + 1) * x / 23.0)))

    def ShowPlotFrame(self, do_raise=True, clear=True):
        "make sure plot frame is enabled, and visible"
        if self.plotframe is None:
            self.plotframe = PlotFrame(self)
            self.has_plot = False
        try:
            self.plotframe.Show()
        except PyDeadObjectError:
            self.plotframe = PlotFrame(self)
            self.plotframe.Show()

        if do_raise:
            self.plotframe.Raise()
        if clear:
            self.plotframe.panel.clear()
            self.plotframe.reset_config()

    def onPlot1(self, event=None):
        self.ShowPlotFrame()
        self.plotframe.plot(self.x, self.y1)
        self.plotframe.oplot(self.x, self.y2)
        self.plotframe.write_message("Plot 1")

    def onPlot2(self, event=None):
        self.ShowPlotFrame()
        x = arange(100)
        y1 = cos(pi * x / 72)
        y2 = sin(pi * x / 23)
        self.plotframe.plot(x, y1, color='red')
        self.plotframe.oplot(x, y2, color='green3', marker='+')
        self.plotframe.write_message("Plot 2")

    def onPlotErr(self, event=None):
        self.ShowPlotFrame()
        npts = 81
        x = linspace(0, 40.0, npts)
        y = 0.4 * cos(x / 2.0) + random.normal(scale=0.03, size=npts)
        dy = 0.03 * (ones(npts) + random.normal(scale=0.2, size=npts))

        self.plotframe.plot(x,
                            y,
                            dy=dy,
                            color='red',
                            linewidth=0,
                            xlabel='x',
                            ylabel='y',
                            marker='o',
                            title='Plot with error bars')
        self.plotframe.write_message("Errorbars!")

    def onPlot2Axes(self, event=None):
        self.ShowPlotFrame()

        self.plotframe.plot(self.x, self.y2, color='black', style='dashed')
        self.plotframe.oplot(self.x, self.y5, color='red', side='right')
        self.plotframe.write_message("Plot with 2 axes")

    def onPlotSLog(self, event=None):
        self.ShowPlotFrame()

        self.plotframe.plot(self.x,
                            self.y4,
                            ylog_scale=True,
                            color='black',
                            style='dashed')
        self.plotframe.write_message("Semi Log Plot")

    def onPlotBig(self, event=None):
        self.ShowPlotFrame()

        t0 = time.time()
        self.plotframe.plot(self.bigx, self.bigy, marker='+', linewidth=0)
        dt = time.time() - t0
        self.plotframe.write_message(
            "Plot array with npts=%i, elapsed time=%8.3f s" %
            (len(self.bigx), dt))

    def onPlotMany_Slow(self, event=None):
        self.ShowPlotFrame()
        dlist = self.many_dlist

        t0 = time.time()
        opts = dict(title='Plot 20 traces without delay_draw',
                    show_legend=True,
                    xlabel='x')

        self.plotframe.plot(dlist[0][0], dlist[0][1], **opts)
        for tdat in dlist[1:]:
            self.plotframe.oplot(tdat[0], tdat[1])

        dt = time.time() - t0
        self.plotframe.write_message(
            "Plot 20 traces without delay_draw=True, elapsed time=%8.3f s" %
            (dt))

    def onPlotMany_Delay(self, event=None):
        self.ShowPlotFrame()
        dlist = self.many_dlist

        t0 = time.time()
        opts = dict(title='Plot 20 traces with delay_draw',
                    show_legend=True,
                    xlabel='x')

        self.plotframe.plot(dlist[0][0], dlist[0][1], delay_draw=True, **opts)
        for tdat in dlist[1:-1]:
            self.plotframe.oplot(tdat[0], tdat[1], delay_draw=True)
        self.plotframe.oplot(dlist[-1][0], dlist[-1][1])
        dt = time.time() - t0
        self.plotframe.write_message(
            "Plot 20 traces with delay_draw=True, elapsed time=%8.3f s" % (dt))

    def onPlotMany_Fast(self, event=None):
        self.ShowPlotFrame()
        dlist = self.many_dlist

        t0 = time.time()
        opts = dict(title='Plot 20 traces using plot_many()',
                    show_legend=True,
                    xlabel='x')
        self.plotframe.plot_many(dlist, **opts)

        dt = time.time() - t0
        self.plotframe.write_message(
            "Plot 20 traces with plot_many(), elapsed time=%8.3f s" % (dt))

    def report_memory(i):
        pid = os.getpid()
        if os.name == 'posix':
            mem = os.popen("ps -o rss -p %i" % pid).readlines()[1].split()[0]
        else:
            mem = 0
        return int(mem)

    def onStartTimer(self, event=None):
        self.count = 0
        self.up_count = 0
        self.n_update = 1
        self.datrange = None
        self.time0 = time.time()
        self.start_mem = self.report_memory()
        self.timer.Start(10)

    def timer_results(self):
        if (self.count < 2): return
        etime = time.time() - self.time0
        tpp = etime / max(1, self.count)
        s = "drew %i points in %8.3f s: time/point= %8.4f s" % (self.count,
                                                                etime, tpp)
        self.plotframe.write_message(s)
        self.time0 = 0
        self.count = 0
        self.datrange = None

    def onStopTimer(self, event=None):
        self.timer.Stop()
        try:
            self.timer_results()
        except:
            pass

    def onTimer(self, event):
        # print 'timer ', self.count, time.time()
        self.count += 1
        n = self.count
        if n < 2:
            self.ShowPlotFrame(do_raise=False, clear=False)
            return
        if n >= self.npts:
            self.timer.Stop()
            self.timer_results()
        elif n <= 3:
            self.plotframe.plot(self.x[:n], self.y1[:n])  # , grid=False)

        else:
            self.plotframe.update_line(0,
                                       self.x[:n],
                                       self.y1[:n],
                                       update_limits=True,
                                       draw=True)
            etime = time.time() - self.time0
            s = " %i / %i points in %8.4f s" % (n, self.npts, etime)
            self.plotframe.write_message(s)

    def OnAbout(self, event):
        dlg = wx.MessageDialog(
            self, "This sample program shows some\n"
            "examples of WXMPlot PlotFrame.\n"
            "message dialog.", "About WXMPlot test",
            wx.OK | wx.ICON_INFORMATION)
        dlg.ShowModal()
        dlg.Destroy()

    def OnExit(self, event):
        try:
            if self.plotframe != None: self.plotframe.onExit()
        except:
            pass
        self.Destroy()
Example #3
0
class ADFrame(wx.Frame):
    """
    AreaDetector Display Frame
    """
    def __init__(self, configfile=None):
        wx.Frame.__init__(self,
                          None,
                          -1,
                          'AreaDetector Viewer',
                          style=wx.DEFAULT_FRAME_STYLE)

        if configfile is None:
            wcard = 'Detector Config Files (*.yaml)|*.yaml|All files (*.*)|*.*'
            configfile = FileOpen(self,
                                  "Read Detector Configuration File",
                                  default_file='det.yaml',
                                  wildcard=wcard)
        if configfile is None:
            sys.exit()

        self.config = read_adconfig(configfile)
        self.prefix = self.config['general']['prefix']
        self.fname = self.config['general']['name']
        self.colormode = self.config['general']['colormode'].lower()
        self.cam_attrs = self.config['cam_attributes']
        self.img_attrs = self.config['img_attributes']
        self.fsaver = self.config['general']['filesaver']

        self.SetTitle(self.config['general']['title'])
        self.scandb = None
        if ScanDB is not None:
            self.scandb = ScanDB()
            if self.scandb.engine is None:  # not connected to running scandb server
                self.scandb = None

        self.calib = None
        self.ad_img = None
        self.ad_cam = None
        self.lineplotter = None
        self.integrator = None
        self.int_panel = None
        self.int_lastid = None
        self.contrast_levels = None
        self.thumbnail = None

        self.buildMenus()
        self.buildFrame()

    def buildFrame(self):
        self.SetFont(Font(11))

        sbar = self.CreateStatusBar(3, wx.CAPTION)
        self.SetStatusWidths([-1, -1, -1])
        self.SetStatusText('', 0)

        sizer = wx.GridBagSizer(3, 3)
        panel = self.panel = wx.Panel(self)
        pvpanel = PVConfigPanel(panel, self.prefix, self.config['controls'])

        wsize = (100, -1)
        lsize = (250, -1)

        start_btn = wx.Button(panel, label='Start', size=wsize)
        stop_btn = wx.Button(panel, label='Stop', size=wsize)
        start_btn.Bind(wx.EVT_BUTTON, partial(self.onButton, key='start'))
        stop_btn.Bind(wx.EVT_BUTTON, partial(self.onButton, key='stop'))

        self.contrast = ContrastControl(panel,
                                        callback=self.set_contrast_level)
        self.imagesize = wx.StaticText(panel,
                                       label='? x ?',
                                       size=(150, 30),
                                       style=txtstyle)

        def lin(len=200, wid=2, style=wx.LI_HORIZONTAL):
            return wx.StaticLine(panel, size=(len, wid), style=style)

        irow = 0
        sizer.Add(pvpanel, (irow, 0), (1, 3), labstyle)

        irow += 1
        sizer.Add(start_btn, (irow, 0), (1, 1), labstyle)
        sizer.Add(stop_btn, (irow, 1), (1, 1), labstyle)

        if self.config['general'].get('show_free_run', False):
            free_btn = wx.Button(panel, label='Free Run', size=wsize)
            free_btn.Bind(wx.EVT_BUTTON, partial(self.onButton, key='free'))
            irow += 1
            sizer.Add(free_btn, (irow, 0), (1, 2), labstyle)

        irow += 1
        sizer.Add(lin(200, wid=4), (irow, 0), (1, 3), labstyle)

        irow += 1
        sizer.Add(self.imagesize, (irow, 0), (1, 3), labstyle)

        if self.colormode.startswith('mono'):
            self.cmap_choice = wx.Choice(panel,
                                         size=(80, -1),
                                         choices=self.config['colormaps'])
            self.cmap_choice.SetSelection(0)
            self.cmap_choice.Bind(wx.EVT_CHOICE, self.onColorMap)
            self.cmap_reverse = wx.CheckBox(panel,
                                            label='Reverse',
                                            size=(60, -1))
            self.cmap_reverse.Bind(wx.EVT_CHECKBOX, self.onColorMap)

            irow += 1
            sizer.Add(wx.StaticText(panel, label='Color Map: '), (irow, 0),
                      (1, 1), labstyle)

            sizer.Add(self.cmap_choice, (irow, 1), (1, 1), labstyle)
            sizer.Add(self.cmap_reverse, (irow, 2), (1, 1), labstyle)

        irow += 1
        sizer.Add(self.contrast.label, (irow, 0), (1, 1), labstyle)
        sizer.Add(self.contrast.choice, (irow, 1), (1, 1), labstyle)

        if self.config['general']['show_1dintegration']:
            self.show1d_btn = wx.Button(panel,
                                        label='Show 1D Integration',
                                        size=(200, -1))
            self.show1d_btn.Bind(wx.EVT_BUTTON, self.onShowIntegration)
            self.show1d_btn.Disable()
            irow += 1
            sizer.Add(self.show1d_btn, (irow, 0), (1, 2), labstyle)

        if self.config['general']['show_thumbnail']:
            t_size = self.config['general'].get('thumbnail_size', 100)

            self.thumbnail = ThumbNailImagePanel(panel,
                                                 imgsize=t_size,
                                                 size=(350, 350),
                                                 motion_writer=partial(
                                                     self.write, panel=0))

            label = wx.StaticText(panel,
                                  label='Thumbnail size (pixels): ',
                                  size=(200, -1),
                                  style=txtstyle)

            self.thumbsize = FloatSpin(panel,
                                       value=100,
                                       min_val=10,
                                       increment=5,
                                       action=self.onThumbSize,
                                       size=(150, -1),
                                       style=txtstyle)

            irow += 1
            sizer.Add(label, (irow, 0), (1, 1), labstyle)
            sizer.Add(self.thumbsize, (irow, 1), (1, 1), labstyle)
            irow += 1
            sizer.Add(self.thumbnail, (irow, 0), (1, 2), labstyle)

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

        # image panel
        self.image = ADMonoImagePanel(
            self,
            prefix=self.prefix,
            rot90=self.config['general']['default_rotation'],
            size=(750, 750),
            writer=partial(self.write, panel=1),
            thumbnail=self.thumbnail,
            motion_writer=partial(self.write, panel=2))

        mainsizer = wx.BoxSizer(wx.HORIZONTAL)
        mainsizer.Add(panel, 0, wx.LEFT | wx.GROW | wx.ALL)
        mainsizer.Add(self.image, 1, wx.CENTER | wx.GROW | wx.ALL)
        self.SetSizer(mainsizer)
        mainsizer.Fit(self)

        self.SetAutoLayout(True)
        iconfile = self.config['general'].get('iconfile', None)
        if iconfile is None or not os.path.exists(iconfile):
            iconfile = DEFAULT_ICONFILE
        try:
            self.SetIcon(wx.Icon(iconfile, wx.BITMAP_TYPE_ICO))
        except:
            pass
        self.connect_pvs()

    def onThumbSize(self, event=None):
        self.thumbnail.imgsize = int(self.thumbsize.GetValue())

    def onColorMap(self, event=None):
        cmap_name = self.cmap_choice.GetStringSelection()
        if self.cmap_reverse.IsChecked():
            cmap_name = cmap_name + '_r'
        self.image.colormap = getattr(colormap, cmap_name)
        self.image.Refresh()

    def onCopyImage(self, event=None):
        "copy bitmap of canvas to system clipboard"
        bmp = wx.BitmapDataObject()
        bmp.SetBitmap(wx.Bitmap(self.image.GrabWxImage()))
        wx.TheClipboard.Open()
        wx.TheClipboard.SetData(bmp)
        wx.TheClipboard.Close()
        wx.TheClipboard.Flush()

    def onReadCalibFile(self, event=None):
        "read calibration file"
        wcards = "Poni Files(*.poni)|*.poni|All files (*.*)|*.*"
        dlg = wx.FileDialog(None,
                            message='Read Calibration File',
                            defaultDir=os.getcwd(),
                            wildcard=wcards,
                            style=wx.FD_OPEN)
        ppath = None
        if dlg.ShowModal() == wx.ID_OK:
            ppath = os.path.abspath(dlg.GetPath())

        if os.path.exists(ppath):
            self.setup_calibration(ppath)

    def setup_calibration(self, ponifile):
        """set up calibration from PONI file"""
        calib = read_poni(ponifile)
        # if self.image.rot90 in (1, 3):
        #     calib['rot3'] = np.pi/2.0
        self.calib = calib
        if HAS_PYFAI:
            self.integrator = AzimuthalIntegrator(**calib)
            self.show1d_btn.Enable()
        else:
            self.write('Warning: PyFAI is not installed')

        if self.scandb is not None:
            _, calname = os.path.split(ponifile)
            self.scandb.set_detectorconfig(calname, json.dumps(calib))
            self.scandb.set_info('xrd_calibration', calname)

    def onShowIntegration(self, event=None):

        if self.calib is None or 'poni1' not in self.calib:
            return
        shown = False
        try:
            self.int_panel.Raise()
            shown = True
        except:
            self.int_panel = None
        if not shown:
            self.int_panel = PlotFrame(self)
            self.show_1dpattern(init=True)
        else:
            self.show_1dpattern()

    def onAutoIntegration(self, event=None):
        if not event.IsChecked():
            self.int_timer.Stop()
            return

        if self.calib is None or 'poni1' not in self.calib:
            return
        shown = False
        try:
            self.int_panel.Raise()
            shown = True
        except:
            self.int_panel = None
        if not shown:
            self.int_panel = PlotFrame(self)
            self.show_1dpattern(init=True)
        else:
            self.show_1dpattern()
        self.int_timer.Start(500)

    def show_1dpattern(self, init=False):
        if self.calib is None or not HAS_PYFAI:
            return

        img = self.ad_img.PV('ArrayData').get()

        h, w = self.image.GetImageSize()
        img.shape = (w, h)

        # may need to trim outer pixels (int1d_trimx/int1d_trimy in config)
        xstride = 1
        if self.config['general'].get('int1d_flipx', False):
            xstride = -1

        xslice = slice(None, None, xstride)
        trimx = int(self.config['general'].get('int1d_trimx', 0))
        if trimx != 0:
            xslice = slice(trimx * xstride, -trimx * xstride, xstride)

        ystride = 1
        if self.config['general'].get('int1d_flipy', True):
            ystride = -1

        yslice = slice(None, None, ystride)
        trimy = int(self.config['general'].get('int1d_trimy', 0))
        if trimy > 0:
            yslice = slice(trimy * ystride, -trimy * ystride, ystride)

        img = img[yslice, xslice]

        img_id = self.ad_cam.ArrayCounter_RBV
        q, xi = self.integrator.integrate1d(img,
                                            2048,
                                            unit='q_A^-1',
                                            correctSolidAngle=True,
                                            polarization_factor=0.999)
        if init:
            self.int_panel.plot(q,
                                xi,
                                xlabel=r'$Q (\rm\AA^{-1})$',
                                marker='+',
                                title='Image %d' % img_id)
            self.int_panel.Raise()
            self.int_panel.Show()
        else:
            self.int_panel.update_line(0, q, xi, draw=True)
            self.int_panel.set_title('Image %d' % img_id)

    @EpicsFunction
    def onSaveImage(self, event=None):
        "prompts for and save image to file"
        defdir = os.getcwd()
        self.fname = "Image_%i.tiff" % self.ad_cam.ArrayCounter_RBV
        dlg = wx.FileDialog(None,
                            message='Save Image as',
                            defaultDir=os.getcwd(),
                            defaultFile=self.fname,
                            style=wx.FD_SAVE)
        path = None
        if dlg.ShowModal() == wx.ID_OK:
            path = os.path.abspath(dlg.GetPath())

        root, fname = os.path.split(path)
        epics.caput("%s%sFileName" % self.prefix, self.fsaver, fname)
        epics.caput("%s%sFileWriteMode" % self.prefix, self.fsaver, 0)
        time.sleep(0.05)
        epics.caput("%s%sWriteFile" % self.prefix, self.fsaver, 1)
        time.sleep(0.05)

        file_pv = "%s%sFullFileName_RBV" % (self.prefix, self.prefix)
        print("Saved image File ", epics.caget(file_pv, as_string=True))

    def onExit(self, event=None):
        try:
            wx.Yield()
        except:
            pass
        self.Destroy()

    def onAbout(self, event=None):
        msg = """areaDetector Display version 0.2
Matt Newville <*****@*****.**>"""

        dlg = wx.MessageDialog(self, msg, "About areaDetector Display",
                               wx.OK | wx.ICON_INFORMATION)
        dlg.ShowModal()
        dlg.Destroy()

    def buildMenus(self):
        fmenu = wx.Menu()
        MenuItem(self, fmenu, "&Save\tCtrl+S", "Save Image", self.onSaveImage)
        MenuItem(self, fmenu, "&Copy\tCtrl+C", "Copy Image to Clipboard",
                 self.onCopyImage)
        MenuItem(self, fmenu, "Read Calibration File", "Read PONI Calibration",
                 self.onReadCalibFile)
        fmenu.AppendSeparator()
        MenuItem(self, fmenu, "E&xit\tCtrl+Q", "Exit Program", self.onExit)

        omenu = wx.Menu()
        MenuItem(self, omenu, "&Rotate CCW\tCtrl+R",
                 "Rotate Counter Clockwise", self.onRot90)
        MenuItem(self, omenu, "Flip Up/Down\tCtrl+T", "Flip Up/Down",
                 self.onFlipV)
        MenuItem(self, omenu, "Flip Left/Right\tCtrl+F", "Flip Left/Right",
                 self.onFlipH)
        MenuItem(self, omenu, "Reset Rotations and Flips", "Reset",
                 self.onResetRotFlips)
        omenu.AppendSeparator()

        hmenu = wx.Menu()
        MenuItem(self, hmenu, "About", "About areaDetector Display",
                 self.onAbout)

        mbar = wx.MenuBar()
        mbar.Append(fmenu, "File")
        mbar.Append(omenu, "Options")

        mbar.Append(hmenu, "&Help")
        self.SetMenuBar(mbar)

    def onResetRotFlips(self, event):
        self.image.rot90 = 0
        self.image.flipv = self.image.fliph = False

    def onRot90(self, event):
        self.image.rot90 = (self.image.rot90 - 1) % 4

    def onFlipV(self, event):
        self.image.flipv = not self.image.flipv

    def onFlipH(self, event):
        self.image.fliph = not self.image.fliph

    def set_contrast_level(self, contrast_level=0):
        self.image.contrast_levels = [contrast_level, 100.0 - contrast_level]
        self.image.Refresh()

    def write(self, s, panel=0):
        """write a message to the Status Bar"""
        self.SetStatusText(text=s, number=panel)

    @EpicsFunction
    def onButton(self, event=None, key='free'):
        key = key.lower()
        if key.startswith('free'):
            ftime = self.config['general']['free_run_time']
            self.image.restart_fps_counter()
            self.ad_cam.AcquireTime = ftime
            self.ad_cam.AcquirePeriod = ftime
            self.ad_cam.NumImages = int((3 * 86400.) / ftime)
            self.ad_cam.Acquire = 1
        elif key.startswith('start'):
            self.image.restart_fps_counter()
            self.ad_cam.Acquire = 1
        elif key.startswith('stop'):
            self.ad_cam.Acquire = 0

    @EpicsFunction
    def connect_pvs(self, verbose=True):
        if self.prefix is None or len(self.prefix) < 2:
            return
        self.write('Connecting to areaDetector %s' % self.prefix)

        self.ad_img = epics.Device(self.prefix + 'image1:',
                                   delim='',
                                   attrs=self.img_attrs)
        self.ad_cam = epics.Device(self.prefix + 'cam1:',
                                   delim='',
                                   attrs=self.cam_attrs)

        if self.config['general']['use_filesaver']:
            epics.caput("%s%sEnableCallbacks" % (self.prefix, self.fsaver), 1)
            epics.caput("%s%sAutoSave" % (self.prefix, self.fsaver), 0)
            epics.caput("%s%sAutoIncrement" % (self.prefix, self.fsaver), 0)
            epics.caput("%s%sFileWriteMode" % (self.prefix, self.fsaver), 0)

        time.sleep(0.002)
        if not self.ad_img.PV('UniqueId_RBV').connected:
            epics.poll()
            if not self.ad_img.PV('UniqueId_RBV').connected:
                self.write('Warning: detector seems to not be connected!')
                return
        if verbose:
            self.write('Connected to detector %s' % self.prefix)

        self.SetTitle("Epics areaDetector Display: %s" % self.prefix)

        sizex = self.ad_cam.MaxSizeX_RBV
        sizey = self.ad_cam.MaxSizeY_RBV

        sizelabel = 'Image Size: %i x %i pixels'
        try:
            sizelabel = sizelabel % (sizex, sizey)
        except:
            sizelabel = sizelabel % (0, 0)

        self.imagesize.SetLabel(sizelabel)

        self.ad_cam.add_callback('DetectorState_RBV', self.onDetState)
        self.contrast.set_level_str('0.01')

    @DelayedEpicsCallback
    def onDetState(self, pvname=None, value=None, char_value=None, **kw):
        self.write(char_value, panel=0)
Example #4
0
class ADFrame(wx.Frame):
    """
    AreaDetector Display Frame
    """
    def __init__(self, configfile=None):
        wx.Frame.__init__(self, None, -1, 'AreaDetector Viewer',
                          style=wx.DEFAULT_FRAME_STYLE)

        if configfile is None:
            wcard = 'Detector Config Files (*.yaml)|*.yaml|All files (*.*)|*.*'
            configfile = FileOpen(self, "Read Detector Configuration File",
                                  default_file='det.yaml',
                                  wildcard=wcard)
        if configfile is None:
            sys.exit()

        self.config = read_adconfig(configfile)
        self.prefix = self.config['general']['prefix']
        self.fname = self.config['general']['name']
        self.colormode = self.config['general']['colormode'].lower()
        self.cam_attrs = self.config['cam_attributes']
        self.img_attrs = self.config['img_attributes']
        self.fsaver = self.config['general']['filesaver']

        self.SetTitle(self.config['general']['title'])
        self.scandb = None
        if ScanDB is not None:
            self.scandb = ScanDB()
            if self.scandb.engine is None: # not connected to running scandb server
                self.scandb = None

        self.calib = None
        self.ad_img = None
        self.ad_cam = None
        self.lineplotter = None
        self.integrator = None
        self.int_panel = None
        self.int_lastid = None
        self.contrast_levels = None
        self.thumbnail = None

        self.buildMenus()
        self.buildFrame()

    def buildFrame(self):
        self.SetFont(Font(11))

        sbar = self.CreateStatusBar(3, wx.CAPTION)
        self.SetStatusWidths([-1, -1, -1])
        self.SetStatusText('',0)

        sizer = wx.GridBagSizer(3, 3)
        panel = self.panel = wx.Panel(self)
        pvpanel = PVConfigPanel(panel, self.prefix, self.config['controls'])

        wsize = (100, -1)
        lsize = (250, -1)

        start_btn = wx.Button(panel, label='Start',    size=wsize)
        stop_btn  = wx.Button(panel, label='Stop',     size=wsize)
        start_btn.Bind(wx.EVT_BUTTON, partial(self.onButton, key='start'))
        stop_btn.Bind(wx.EVT_BUTTON,  partial(self.onButton, key='stop'))

        self.contrast = ContrastControl(panel, callback=self.set_contrast_level)
        self.imagesize = wx.StaticText(panel, label='? x ?',
                                       size=(150, 30), style=txtstyle)


        def lin(len=200, wid=2, style=wx.LI_HORIZONTAL):
            return wx.StaticLine(panel, size=(len, wid), style=style)

        irow = 0
        sizer.Add(pvpanel,  (irow, 0), (1, 3), labstyle)

        irow += 1
        sizer.Add(start_btn, (irow, 0), (1, 1), labstyle)
        sizer.Add(stop_btn,  (irow, 1), (1, 1), labstyle)

        if self.config['general'].get('show_free_run', False):
            free_btn  = wx.Button(panel, label='Free Run', size=wsize)
            free_btn.Bind(wx.EVT_BUTTON,  partial(self.onButton, key='free'))
            irow += 1
            sizer.Add(free_btn,  (irow, 0), (1, 2), labstyle)

        irow += 1
        sizer.Add(lin(200, wid=4),  (irow, 0), (1, 3), labstyle)

        irow += 1
        sizer.Add(self.imagesize, (irow, 0), (1, 3), labstyle)

        if self.colormode.startswith('mono'):
            self.cmap_choice = wx.Choice(panel, size=(80, -1),
                                         choices=self.config['colormaps'])
            self.cmap_choice.SetSelection(0)
            self.cmap_choice.Bind(wx.EVT_CHOICE,  self.onColorMap)
            self.cmap_reverse = wx.CheckBox(panel, label='Reverse', size=(60, -1))
            self.cmap_reverse.Bind(wx.EVT_CHECKBOX,  self.onColorMap)

            irow += 1
            sizer.Add(wx.StaticText(panel, label='Color Map: '),
                      (irow, 0), (1, 1), labstyle)

            sizer.Add(self.cmap_choice,  (irow, 1), (1, 1), labstyle)
            sizer.Add(self.cmap_reverse, (irow, 2), (1, 1), labstyle)

        irow += 1
        sizer.Add(self.contrast.label,  (irow, 0), (1, 1), labstyle)
        sizer.Add(self.contrast.choice, (irow, 1), (1, 1), labstyle)

        if self.config['general']['show_1dintegration']:
            self.show1d_btn = wx.Button(panel, label='Show 1D Integration',
                                         size=(200, -1))
            self.show1d_btn.Bind(wx.EVT_BUTTON, self.onShowIntegration)
            self.show1d_btn.Disable()
            irow += 1
            sizer.Add(self.show1d_btn, (irow, 0), (1, 2), labstyle)

        if self.config['general']['show_thumbnail']:
            t_size=self.config['general'].get('thumbnail_size', 100)

            self.thumbnail = ThumbNailImagePanel(panel, imgsize=t_size,
                                                 size=(350, 350),
                                                 motion_writer=partial(self.write, panel=0))

            label = wx.StaticText(panel, label='Thumbnail size (pixels): ',
                                       size=(200, -1), style=txtstyle)

            self.thumbsize = FloatSpin(panel, value=100, min_val=10, increment=5,
                                       action=self.onThumbSize,
                                       size=(150, -1), style=txtstyle)

            irow += 1
            sizer.Add(label,          (irow, 0), (1, 1), labstyle)
            sizer.Add(self.thumbsize, (irow, 1), (1, 1), labstyle)
            irow += 1
            sizer.Add(self.thumbnail, (irow, 0), (1, 2), labstyle)

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

        # image panel
        self.image = ADMonoImagePanel(self, prefix=self.prefix,
                                      rot90=self.config['general']['default_rotation'],
                                      size=(750, 750),
                                      writer=partial(self.write, panel=1),
                                      thumbnail=self.thumbnail,
                                      motion_writer=partial(self.write, panel=2))

        mainsizer = wx.BoxSizer(wx.HORIZONTAL)
        mainsizer.Add(panel, 0, wx.LEFT|wx.GROW|wx.ALL)
        mainsizer.Add(self.image, 1, wx.CENTER|wx.GROW|wx.ALL)
        self.SetSizer(mainsizer)
        mainsizer.Fit(self)

        self.SetAutoLayout(True)
        iconfile = self.config['general'].get('iconfile', None)
        if iconfile is None or not os.path.exists(iconfile):
            iconfile = DEFAULT_ICONFILE
        try:
            self.SetIcon(wx.Icon(iconfile, wx.BITMAP_TYPE_ICO))
        except:
            pass
        self.connect_pvs()


    def onThumbSize(self, event=None):
        self.thumbnail.imgsize = int(self.thumbsize.GetValue())

    def onColorMap(self, event=None):
        cmap_name = self.cmap_choice.GetStringSelection()
        if self.cmap_reverse.IsChecked():
            cmap_name = cmap_name + '_r'
        self.image.colormap = getattr(colormap, cmap_name)
        self.image.Refresh()

    def onCopyImage(self, event=None):
        "copy bitmap of canvas to system clipboard"
        bmp = wx.BitmapDataObject()
        bmp.SetBitmap(wx.Bitmap(self.image.GrabWxImage()))
        wx.TheClipboard.Open()
        wx.TheClipboard.SetData(bmp)
        wx.TheClipboard.Close()
        wx.TheClipboard.Flush()

    def onReadCalibFile(self, event=None):
        "read calibration file"
        wcards = "Poni Files(*.poni)|*.poni|All files (*.*)|*.*"
        dlg = wx.FileDialog(None, message='Read Calibration File',
                            defaultDir=os.getcwd(),
                            wildcard=wcards,
                            style=wx.FD_OPEN)
        ppath = None
        if dlg.ShowModal() == wx.ID_OK:
            ppath = os.path.abspath(dlg.GetPath())

        if os.path.exists(ppath):
            self.setup_calibration(ppath)

    def setup_calibration(self, ponifile):
        """set up calibration from PONI file"""
        calib = read_poni(ponifile)
        # if self.image.rot90 in (1, 3):
        #     calib['rot3'] = np.pi/2.0
        self.calib = calib
        if HAS_PYFAI:
            self.integrator = AzimuthalIntegrator(**calib)
            self.show1d_btn.Enable()
        else:
            self.write('Warning: PyFAI is not installed')

        if self.scandb is not None:
            _, calname  = os.path.split(ponifile)
            self.scandb.set_detectorconfig(calname, json.dumps(calib))
            self.scandb.set_info('xrd_calibration', calname)

    def onShowIntegration(self, event=None):

        if self.calib is None or 'poni1' not in self.calib:
            return
        shown = False
        try:
            self.int_panel.Raise()
            shown = True
        except:
            self.int_panel = None
        if not shown:
            self.int_panel = PlotFrame(self)
            self.show_1dpattern(init=True)
        else:
            self.show_1dpattern()

    def onAutoIntegration(self, event=None):
        if not event.IsChecked():
            self.int_timer.Stop()
            return

        if self.calib is None or 'poni1' not in self.calib:
            return
        shown = False
        try:
            self.int_panel.Raise()
            shown = True
        except:
            self.int_panel = None
        if not shown:
            self.int_panel = PlotFrame(self)
            self.show_1dpattern(init=True)
        else:
            self.show_1dpattern()
        self.int_timer.Start(500)

    def show_1dpattern(self, init=False):
        if self.calib is None or not HAS_PYFAI:
            return

        img = self.ad_img.PV('ArrayData').get()

        h, w = self.image.GetImageSize()
        img.shape = (w, h)

        # may need to trim outer pixels (int1d_trimx/int1d_trimy in config)
        xstride = 1
        if self.config['general'].get('int1d_flipx', False):
            xstride = -1

        xslice = slice(None, None, xstride)
        trimx = int(self.config['general'].get('int1d_trimx', 0))
        if trimx != 0:
            xslice = slice(trimx*xstride, -trimx*xstride, xstride)

        ystride = 1
        if self.config['general'].get('int1d_flipy', True):
            ystride = -1

        yslice = slice(None, None, ystride)
        trimy = int(self.config['general'].get('int1d_trimy', 0))
        if trimy > 0:
            yslice = slice(trimy*ystride, -trimy*ystride, ystride)

        img = img[yslice, xslice]

        img_id = self.ad_cam.ArrayCounter_RBV
        q, xi = self.integrator.integrate1d(img, 2048, unit='q_A^-1',
                                            correctSolidAngle=True,
                                            polarization_factor=0.999)
        if init:
            self.int_panel.plot(q, xi, xlabel=r'$Q (\rm\AA^{-1})$', marker='+',
                                title='Image %d' % img_id)
            self.int_panel.Raise()
            self.int_panel.Show()
        else:
            self.int_panel.update_line(0, q, xi, draw=True)
            self.int_panel.set_title('Image %d' % img_id)

    @EpicsFunction
    def onSaveImage(self, event=None):
        "prompts for and save image to file"
        defdir = os.getcwd()
        self.fname = "Image_%i.tiff"  % self.ad_cam.ArrayCounter_RBV
        dlg = wx.FileDialog(None, message='Save Image as',
                            defaultDir=os.getcwd(),
                            defaultFile=self.fname,
                            style=wx.FD_SAVE)
        path = None
        if dlg.ShowModal() == wx.ID_OK:
            path = os.path.abspath(dlg.GetPath())


        root, fname = os.path.split(path)
        epics.caput("%s%sFileName" % self.prefix, self.fsaver, fname)
        epics.caput("%s%sFileWriteMode" % self.prefix, self.fsaver, 0)
        time.sleep(0.05)
        epics.caput("%s%sWriteFile" % self.prefix, self.fsaver, 1)
        time.sleep(0.05)

        file_pv = "%s%sFullFileName_RBV" % (self.prefix, self.prefix)
        print("Saved image File ", epics.caget(file_pv,  as_string=True))

    def onExit(self, event=None):
        try:
            wx.Yield()
        except:
            pass
        self.Destroy()

    def onAbout(self, event=None):
        msg =  """areaDetector Display version 0.2
Matt Newville <*****@*****.**>"""

        dlg = wx.MessageDialog(self, msg, "About areaDetector Display",
                               wx.OK | wx.ICON_INFORMATION)
        dlg.ShowModal()
        dlg.Destroy()

    def buildMenus(self):
        fmenu = wx.Menu()
        MenuItem(self, fmenu, "&Save\tCtrl+S", "Save Image", self.onSaveImage)
        MenuItem(self, fmenu, "&Copy\tCtrl+C", "Copy Image to Clipboard",
                 self.onCopyImage)
        MenuItem(self, fmenu, "Read Calibration File", "Read PONI Calibration",
                 self.onReadCalibFile)
        fmenu.AppendSeparator()
        MenuItem(self, fmenu, "E&xit\tCtrl+Q",  "Exit Program", self.onExit)

        omenu = wx.Menu()
        MenuItem(self, omenu,  "&Rotate CCW\tCtrl+R", "Rotate Counter Clockwise", self.onRot90)
        MenuItem(self, omenu,  "Flip Up/Down\tCtrl+T", "Flip Up/Down", self.onFlipV)
        MenuItem(self, omenu,  "Flip Left/Right\tCtrl+F", "Flip Left/Right", self.onFlipH)
        MenuItem(self, omenu,  "Reset Rotations and Flips", "Reset", self.onResetRotFlips)
        omenu.AppendSeparator()

        hmenu = wx.Menu()
        MenuItem(self, hmenu, "About", "About areaDetector Display", self.onAbout)

        mbar = wx.MenuBar()
        mbar.Append(fmenu, "File")
        mbar.Append(omenu, "Options")

        mbar.Append(hmenu, "&Help")
        self.SetMenuBar(mbar)

    def onResetRotFlips(self, event):
        self.image.rot90 = 0
        self.image.flipv = self.image.fliph = False

    def onRot90(self, event):
        self.image.rot90 = (self.image.rot90 - 1) % 4

    def onFlipV(self, event):
        self.image.flipv= not self.image.flipv

    def onFlipH(self, event):
        self.image.fliph = not self.image.fliph

    def set_contrast_level(self, contrast_level=0):
        self.image.contrast_levels = [contrast_level, 100.0-contrast_level]
        self.image.Refresh()

    def write(self, s, panel=0):
        """write a message to the Status Bar"""
        self.SetStatusText(text=s, number=panel)

    @EpicsFunction
    def onButton(self, event=None, key='free'):
        key = key.lower()
        if key.startswith('free'):
            ftime = self.config['general']['free_run_time']
            self.image.restart_fps_counter()
            self.ad_cam.AcquireTime   = ftime
            self.ad_cam.AcquirePeriod = ftime
            self.ad_cam.NumImages = int((3*86400.)/ftime)
            self.ad_cam.Acquire = 1
        elif key.startswith('start'):
            self.image.restart_fps_counter()
            self.ad_cam.Acquire = 1
        elif key.startswith('stop'):
            self.ad_cam.Acquire = 0

    @EpicsFunction
    def connect_pvs(self, verbose=True):
        if self.prefix is None or len(self.prefix) < 2:
            return
        self.write('Connecting to areaDetector %s' % self.prefix)

        self.ad_img = epics.Device(self.prefix + 'image1:', delim='',
                                   attrs=self.img_attrs)
        self.ad_cam = epics.Device(self.prefix + 'cam1:', delim='',
                                   attrs=self.cam_attrs)

        if self.config['general']['use_filesaver']:
            epics.caput("%s%sEnableCallbacks" % (self.prefix, self.fsaver), 1)
            epics.caput("%s%sAutoSave" % (self.prefix, self.fsaver), 0)
            epics.caput("%s%sAutoIncrement" % (self.prefix, self.fsaver), 0)
            epics.caput("%s%sFileWriteMode" % (self.prefix, self.fsaver), 0)

        time.sleep(0.002)
        if not self.ad_img.PV('UniqueId_RBV').connected:
            epics.poll()
            if not self.ad_img.PV('UniqueId_RBV').connected:
                self.write('Warning: detector seems to not be connected!')
                return
        if verbose:
            self.write('Connected to detector %s' % self.prefix)

        self.SetTitle("Epics areaDetector Display: %s" % self.prefix)

        sizex = self.ad_cam.MaxSizeX_RBV
        sizey = self.ad_cam.MaxSizeY_RBV

        sizelabel = 'Image Size: %i x %i pixels'
        try:
            sizelabel = sizelabel  % (sizex, sizey)
        except:
            sizelabel = sizelabel  % (0, 0)

        self.imagesize.SetLabel(sizelabel)

        self.ad_cam.add_callback('DetectorState_RBV',  self.onDetState)
        self.contrast.set_level_str('0.01')

    @DelayedEpicsCallback
    def onDetState(self, pvname=None, value=None, char_value=None, **kw):
        self.write(char_value, panel=0)
Example #5
0
class EigerFrame(wx.Frame):
    """AreaDetector Display """

    img_attrs = ('ArrayData', 'UniqueId_RBV')
    cam_attrs = ('Acquire', 'DetectorState_RBV',
                 'ArrayCounter', 'ArrayCounter_RBV',
                 'ThresholdEnergy', 'ThresholdEnergy_RBV',
                 'PhotonEnergy', 'PhotonEnergy_RBV',
                 'NumImages', 'NumImages_RBV',
                 'AcquireTime', 'AcquireTime_RBV',
                 'AcquirePeriod', 'AcquirePeriod_RBV',
                 'TriggerMode', 'TriggerMode_RBV')

    # plugins to enable
    enabled_plugins = ('image1', 'Over1', 'ROI1', 'JPEG1', 'TIFF1')

    def __init__(self, prefix=None, url=None, scale=1.0):
        self.ad_img = None
        self.ad_cam = None
        if prefix is None:
            dlg = SavedParameterDialog(label='Detector Prefix',
                                       title='Connect to Eiger Detector',
                                       configfile='.ad_eigerdisplay.dat')
            res = dlg.GetResponse()
            dlg.Destroy()
            if res.ok:
                prefix = res.value

        self.prefix = prefix
        self.fname = 'Eiger.tif'
        self.esimplon = None
        if url is not None and HAS_SIMPLON:
            self.esimplon = EigerSimplon(url, prefix=prefix+'cam1:')

        self.lineplotter = None
        self.calib = {}
        self.integrator = None
        self.int_panel = None
        self.int_lastid = None
        self.contrast_levels = None
        self.scandb = None
        wx.Frame.__init__(self, None, -1, "Eiger500K Area Detector Display",
                          style=wx.DEFAULT_FRAME_STYLE)

        self.buildMenus()
        self.buildFrame()

        wx.CallAfter(self.connect_escandb)

    def connect_escandb(self):
        if HAS_ESCAN and os.environ.get('ESCAN_CREDENTIALS', None) is not None:
            self.scandb = ScanDB()
            calib_loc = self.scandb.get_info('eiger_calibration')
            cal = self.scandb.get_detectorconfig(calib_loc)
            self.setup_calibration(json.loads(cal.text))

    def buildFrame(self):
        sbar = self.CreateStatusBar(3, wx.CAPTION) # |wx.THICK_FRAME)
        self.SetStatusWidths([-1, -1, -1])
        sfont = sbar.GetFont()
        sfont.SetWeight(wx.BOLD)
        sfont.SetPointSize(10)
        sbar.SetFont(sfont)

        self.SetStatusText('',0)

        sizer = wx.GridBagSizer(3, 3)
        panel = self.panel = wx.Panel(self)

        pvpanel = PVConfigPanel(panel, self.prefix, display_pvs)

        wsize = (100, -1)
        lsize = (250, -1)

        start_btn = wx.Button(panel, label='Start',    size=wsize)
        stop_btn  = wx.Button(panel, label='Stop',     size=wsize)
        free_btn  = wx.Button(panel, label='Free Run', size=wsize)
        start_btn.Bind(wx.EVT_BUTTON, partial(self.onButton, key='start'))
        stop_btn.Bind(wx.EVT_BUTTON,  partial(self.onButton, key='stop'))
        free_btn.Bind(wx.EVT_BUTTON,  partial(self.onButton, key='free'))

        self.cmap_choice = wx.Choice(panel, size=(80, -1),
                                             choices=colormaps)
        self.cmap_choice.SetSelection(0)
        self.cmap_choice.Bind(wx.EVT_CHOICE,  self.onColorMap)

        self.cmap_reverse = wx.CheckBox(panel, label='Reverse', size=(60, -1))
        self.cmap_reverse.Bind(wx.EVT_CHECKBOX,  self.onColorMap)

        self.show1d_btn =  wx.Button(panel, label='Show 1D Integration', size=(200, -1))
        self.show1d_btn.Bind(wx.EVT_BUTTON, self.onShowIntegration)
        self.show1d_btn.Disable()

        self.imagesize = wx.StaticText(panel, label='? x ?',
                                       size=(250, 30), style=txtstyle)

        self.contrast = ContrastChoice(panel, callback=self.set_contrast_level)

        def lin(len=200, wid=2, style=wx.LI_HORIZONTAL):
            return wx.StaticLine(panel, size=(len, wid), style=style)


        irow = 0
        sizer.Add(pvpanel,  (irow, 0), (1, 3), labstyle)

        irow += 1
        sizer.Add(start_btn, (irow, 0), (1, 1), labstyle)
        sizer.Add(stop_btn,  (irow, 1), (1, 1), labstyle)
        sizer.Add(free_btn,  (irow, 2), (1, 1), labstyle)

        irow += 1
        sizer.Add(lin(300),  (irow, 0), (1, 3), labstyle)

        irow += 1
        sizer.Add(self.imagesize, (irow, 0), (1, 3), labstyle)

        irow += 1
        sizer.Add(wx.StaticText(panel, label='Color Map: '),
                  (irow, 0), (1, 1), labstyle)

        sizer.Add(self.cmap_choice,  (irow, 1), (1, 1), labstyle)
        sizer.Add(self.cmap_reverse, (irow, 2), (1, 1), labstyle)

        irow += 1
        sizer.Add(self.contrast.label,  (irow, 0), (1, 1), labstyle)
        sizer.Add(self.contrast.choice, (irow, 1), (1, 1), labstyle)

        irow += 1
        sizer.Add(self.show1d_btn, (irow, 0), (1, 2), labstyle)

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

        # image panel
        self.image = ADMonoImagePanel(self, prefix=self.prefix,
                                      rot90=DEFAULT_ROTATION,
                                      size=(400, 750),
                                      writer=partial(self.write, panel=2))

        mainsizer = wx.BoxSizer(wx.HORIZONTAL)
        mainsizer.Add(panel, 0, wx.LEFT|wx.GROW|wx.ALL)
        mainsizer.Add(self.image, 1, wx.CENTER|wx.GROW|wx.ALL)
        self.SetSizer(mainsizer)
        mainsizer.Fit(self)

        self.SetAutoLayout(True)

        try:
            self.SetIcon(wx.Icon(ICONFILE, wx.BITMAP_TYPE_ICO))
        except:
            pass

        wx.CallAfter(self.connect_pvs )

    def onColorMap(self, event=None):
        cmap_name = self.cmap_choice.GetStringSelection()
        if self.cmap_reverse.IsChecked():
            cmap_name = cmap_name + '_r'
        self.image.colormap = getattr(colormap, cmap_name)
        self.image.Refresh()

    def onCopyImage(self, event=None):
        "copy bitmap of canvas to system clipboard"
        bmp = wx.BitmapDataObject()
        bmp.SetBitmap(wx.Bitmap(self.image.GrabWxImage()))
        wx.TheClipboard.Open()
        wx.TheClipboard.SetData(bmp)
        wx.TheClipboard.Close()
        wx.TheClipboard.Flush()

    def onReadCalibFile(self, event=None):
        "read calibration file"
        wcards = "Poni Files(*.poni)|*.poni|All files (*.*)|*.*"
        dlg = wx.FileDialog(None, message='Read Calibration File',
                            defaultDir=os.getcwd(),
                            wildcard=wcards,
                            style=wx.FD_OPEN)
        ppath = None
        if dlg.ShowModal() == wx.ID_OK:
            ppath = os.path.abspath(dlg.GetPath())

        if os.path.exists(ppath):
            if self.scandb is not None:
                CalibrationDialog(self, ppath).Show()
            else:
                self.setup_calibration(read_poni(ppath))

    def setup_calibration(self, calib):
        """set up calibration from calibration dict"""
        if self.image.rot90 in (1, 3):
            calib['rot3'] = np.pi/2.0
        self.calib = calib
        if HAS_PYFAI:
            self.integrator = AzimuthalIntegrator(**calib)
            self.show1d_btn.Enable()

    def onShowIntegration(self, event=None):

        if self.calib is None or 'poni1' not in self.calib:
            return
        shown = False
        try:
            self.int_panel.Raise()
            shown = True
        except:
            self.int_panel = None
        if not shown:
            self.int_panel = PlotFrame(self)
            self.show_1dpattern(init=True)
        else:
            self.show_1dpattern()

    def onAutoIntegration(self, event=None):
        if not event.IsChecked():
            self.int_timer.Stop()
            return

        if self.calib is None or 'poni1' not in self.calib:
            return
        shown = False
        try:
            self.int_panel.Raise()
            shown = True
        except:
            self.int_panel = None
        if not shown:
            self.int_panel = PlotFrame(self)
            self.show_1dpattern(init=True)
        else:
            self.show_1dpattern()
        self.int_timer.Start(500)

    def show_1dpattern(self, init=False):
        if self.calib is None or not HAS_PYFAI:
            return

        img = self.ad_img.PV('ArrayData').get()


        h, w = self.image.GetImageSize()
        img.shape = (w, h)
        img = img[3:-3, 1:-1][::-1, :]

        img_id = self.ad_cam.ArrayCounter_RBV
        q, xi = self.integrator.integrate1d(img, 2048, unit='q_A^-1',
                                            correctSolidAngle=True,
                                            polarization_factor=0.999)
        if init:
            self.int_panel.plot(q, xi, xlabel=r'$Q (\rm\AA^{-1})$', marker='+',
                                title='Image %d' % img_id)
            self.int_panel.Raise()
            self.int_panel.Show()
        else:
            self.int_panel.update_line(0, q, xi, draw=True)
            self.int_panel.set_title('Image %d' % img_id)

    @EpicsFunction
    def onSaveImage(self, event=None):
        "prompts for and save image to file"
        defdir = os.getcwd()
        self.fname = "Image_%i.tiff"  % self.ad_cam.ArrayCounter_RBV
        dlg = wx.FileDialog(None, message='Save Image as',
                            defaultDir=os.getcwd(),
                            defaultFile=self.fname,
                            style=wx.FD_SAVE)
        path = None
        if dlg.ShowModal() == wx.ID_OK:
            path = os.path.abspath(dlg.GetPath())


        root, fname = os.path.split(path)
        epics.caput("%sTIFF1:FileName" % self.prefix, fname)
        epics.caput("%sTIFF1:FileWriteMode" % self.prefix, 0)
        time.sleep(0.05)
        epics.caput("%sTIFF1:WriteFile" % self.prefix, 1)
        time.sleep(0.05)

        print("Saved TIFF File ",
              epics.caget("%sTIFF1:FullFileName_RBV" % self.prefix, as_string=True))

    def onExit(self, event=None):
        try:
            wx.Yield()
        except:
            pass
        self.Destroy()

    def onAbout(self, event=None):
        msg =  """Eiger Image Display version 0.1
Matt Newville <*****@*****.**>"""

        dlg = wx.MessageDialog(self, msg, "About Epics Image Display",
                               wx.OK | wx.ICON_INFORMATION)
        dlg.ShowModal()
        dlg.Destroy()

    def buildMenus(self):
        fmenu = wx.Menu()
        MenuItem(self, fmenu, "&Save\tCtrl+S", "Save Image", self.onSaveImage)
        MenuItem(self, fmenu, "&Copy\tCtrl+C", "Copy Image to Clipboard",
                 self.onCopyImage)
        MenuItem(self, fmenu, "Read Calibration File", "Read PONI Calibration",
                 self.onReadCalibFile)
        fmenu.AppendSeparator()
        MenuItem(self, fmenu, "E&xit\tCtrl+Q",  "Exit Program", self.onExit)

        omenu = wx.Menu()
        MenuItem(self, omenu,  "&Rotate CCW\tCtrl+R", "Rotate Counter Clockwise", self.onRot90)
        MenuItem(self, omenu,  "Flip Up/Down\tCtrl+T", "Flip Up/Down", self.onFlipV)
        MenuItem(self, omenu,  "Flip Left/Right\tCtrl+F", "Flip Left/Right", self.onFlipH)
        MenuItem(self, omenu,  "Reset Rotations and Flips", "Reset", self.onResetRotFlips)
        omenu.AppendSeparator()

        hmenu = wx.Menu()
        MenuItem(self, hmenu, "About", "About Epics AreadDetector Display", self.onAbout)

        mbar = wx.MenuBar()
        mbar.Append(fmenu, "File")
        mbar.Append(omenu, "Options")

        mbar.Append(hmenu, "&Help")
        self.SetMenuBar(mbar)

    def onResetRotFlips(self, event):
        self.image.rot90 = DEFAULT_ROTATION
        self.image.flipv = self.fliph = False

    def onRot90(self, event):
        self.image.rot90 = (self.image.rot90 - 1) % 4

    def onFlipV(self, event):
        self.image.flipv= not self.image.flipv

    def onFlipH(self, event):
        self.image.fliph = not self.image.fliph

    def set_contrast_level(self, contrast_level=0):
        self.image.contrast_levels = [contrast_level, 100.0-contrast_level]

    def write(self, s, panel=0):
        """write a message to the Status Bar"""
        self.SetStatusText(text=s, number=panel)

    @EpicsFunction
    def onButton(self, event=None, key='free'):
        key = key.lower()
        if key.startswith('free'):
            self.image.restart_fps_counter()
            self.ad_cam.AcquireTime = 0.25
            self.ad_cam.AcquirePeriod = 0.25
            self.ad_cam.NumImages = 345600
            self.ad_cam.Acquire = 1
        elif key.startswith('start'):
            self.image.restart_fps_counter()
            self.ad_cam.Acquire = 1
        elif key.startswith('stop'):
            self.ad_cam.Acquire = 0

    @EpicsFunction
    def connect_pvs(self, verbose=True):
        if self.prefix is None or len(self.prefix) < 2:
            return

        if self.prefix.endswith(':'):
            self.prefix = self.prefix[:-1]
        if self.prefix.endswith(':image1'):
            self.prefix = self.prefix[:-7]
        if self.prefix.endswith(':cam1'):
            self.prefix = self.prefix[:-5]

        self.write('Connecting to AD %s' % self.prefix)
        self.ad_img = epics.Device(self.prefix + ':image1:', delim='',
                                   attrs=self.img_attrs)
        self.ad_cam = epics.Device(self.prefix + ':cam1:', delim='',
                                   attrs=self.cam_attrs)

        epics.caput("%s:TIFF1:EnableCallbacks" % self.prefix, 1)
        epics.caput("%s:TIFF1:AutoSave" % self.prefix, 0)
        epics.caput("%s:TIFF1:AutoIncrement" % self.prefix, 0)
        epics.caput("%s:TIFF1:FileWriteMode" % self.prefix, 0)

        time.sleep(0.002)
        if not self.ad_img.PV('UniqueId_RBV').connected:
            epics.poll()
            if not self.ad_img.PV('UniqueId_RBV').connected:
                self.write('Warning:  Camera seems to not be connected!')
                return
        if verbose:
            self.write('Connected to AD %s' % self.prefix)

        self.SetTitle("Epics Image Display: %s" % self.prefix)

        sizex = self.ad_cam.MaxSizeX_RBV
        sizey = self.ad_cam.MaxSizeY_RBV

        sizelabel = 'Image Size: %i x %i pixels'
        try:
            sizelabel = sizelabel  % (sizex, sizey)
        except:
            sizelabel = sizelabel  % (0, 0)

        self.imagesize.SetLabel(sizelabel)

        self.ad_cam.add_callback('DetectorState_RBV',  self.onDetState)
        self.contrast.set_level_str('0.05')

    @DelayedEpicsCallback
    def onDetState(self, pvname=None, value=None, char_value=None, **kw):
        self.write(char_value, panel=1)
Example #6
0
class EigerFrame(wx.Frame):
    """AreaDetector Display """

    img_attrs = ('ArrayData', 'UniqueId_RBV')
    cam_attrs = ('Acquire', 'DetectorState_RBV', 'ArrayCounter',
                 'ArrayCounter_RBV', 'ThresholdEnergy', 'ThresholdEnergy_RBV',
                 'PhotonEnergy', 'PhotonEnergy_RBV', 'NumImages',
                 'NumImages_RBV', 'AcquireTime', 'AcquireTime_RBV',
                 'AcquirePeriod', 'AcquirePeriod_RBV', 'TriggerMode',
                 'TriggerMode_RBV')

    # plugins to enable
    enabled_plugins = ('image1', 'Over1', 'ROI1', 'JPEG1', 'TIFF1')

    def __init__(self, prefix=None, url=None, scale=1.0):
        self.ad_img = None
        self.ad_cam = None
        if prefix is None:
            dlg = SavedParameterDialog(label='Detector Prefix',
                                       title='Connect to Eiger Detector',
                                       configfile='.ad_eigerdisplay.dat')
            res = dlg.GetResponse()
            dlg.Destroy()
            if res.ok:
                prefix = res.value

        self.prefix = prefix
        self.fname = 'Eiger.tif'
        self.esimplon = None
        if url is not None and HAS_SIMPLON:
            self.esimplon = EigerSimplon(url, prefix=prefix + 'cam1:')

        self.lineplotter = None
        self.calib = {}
        self.integrator = None
        self.int_panel = None
        self.int_lastid = None
        self.contrast_levels = None
        self.scandb = None
        wx.Frame.__init__(self,
                          None,
                          -1,
                          "Eiger500K Area Detector Display",
                          style=wx.DEFAULT_FRAME_STYLE)

        self.buildMenus()
        self.buildFrame()

        wx.CallAfter(self.connect_escandb)

    def connect_escandb(self):
        if HAS_ESCAN and os.environ.get('ESCAN_CREDENTIALS', None) is not None:
            self.scandb = ScanDB()
            calib_loc = self.scandb.get_info('eiger_calibration')
            cal = self.scandb.get_detectorconfig(calib_loc)
            self.setup_calibration(json.loads(cal.text))

    def buildFrame(self):
        sbar = self.CreateStatusBar(3, wx.CAPTION)  # |wx.THICK_FRAME)
        self.SetStatusWidths([-1, -1, -1])
        sfont = sbar.GetFont()
        sfont.SetWeight(wx.BOLD)
        sfont.SetPointSize(10)
        sbar.SetFont(sfont)

        self.SetStatusText('', 0)

        sizer = wx.GridBagSizer(3, 3)
        panel = self.panel = wx.Panel(self)

        pvpanel = PVConfigPanel(panel, self.prefix, display_pvs)

        wsize = (100, -1)
        lsize = (250, -1)

        start_btn = wx.Button(panel, label='Start', size=wsize)
        stop_btn = wx.Button(panel, label='Stop', size=wsize)
        free_btn = wx.Button(panel, label='Free Run', size=wsize)
        start_btn.Bind(wx.EVT_BUTTON, partial(self.onButton, key='start'))
        stop_btn.Bind(wx.EVT_BUTTON, partial(self.onButton, key='stop'))
        free_btn.Bind(wx.EVT_BUTTON, partial(self.onButton, key='free'))

        self.cmap_choice = wx.Choice(panel, size=(80, -1), choices=colormaps)
        self.cmap_choice.SetSelection(0)
        self.cmap_choice.Bind(wx.EVT_CHOICE, self.onColorMap)

        self.cmap_reverse = wx.CheckBox(panel, label='Reverse', size=(60, -1))
        self.cmap_reverse.Bind(wx.EVT_CHECKBOX, self.onColorMap)

        self.show1d_btn = wx.Button(panel,
                                    label='Show 1D Integration',
                                    size=(200, -1))
        self.show1d_btn.Bind(wx.EVT_BUTTON, self.onShowIntegration)
        self.show1d_btn.Disable()

        self.imagesize = wx.StaticText(panel,
                                       label='? x ?',
                                       size=(250, 30),
                                       style=txtstyle)

        self.contrast = ContrastChoice(panel, callback=self.set_contrast_level)

        def lin(len=200, wid=2, style=wx.LI_HORIZONTAL):
            return wx.StaticLine(panel, size=(len, wid), style=style)

        irow = 0
        sizer.Add(pvpanel, (irow, 0), (1, 3), labstyle)

        irow += 1
        sizer.Add(start_btn, (irow, 0), (1, 1), labstyle)
        sizer.Add(stop_btn, (irow, 1), (1, 1), labstyle)
        sizer.Add(free_btn, (irow, 2), (1, 1), labstyle)

        irow += 1
        sizer.Add(lin(300), (irow, 0), (1, 3), labstyle)

        irow += 1
        sizer.Add(self.imagesize, (irow, 0), (1, 3), labstyle)

        irow += 1
        sizer.Add(wx.StaticText(panel, label='Color Map: '), (irow, 0), (1, 1),
                  labstyle)

        sizer.Add(self.cmap_choice, (irow, 1), (1, 1), labstyle)
        sizer.Add(self.cmap_reverse, (irow, 2), (1, 1), labstyle)

        irow += 1
        sizer.Add(self.contrast.label, (irow, 0), (1, 1), labstyle)
        sizer.Add(self.contrast.choice, (irow, 1), (1, 1), labstyle)

        irow += 1
        sizer.Add(self.show1d_btn, (irow, 0), (1, 2), labstyle)

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

        # image panel
        self.image = ADMonoImagePanel(self,
                                      prefix=self.prefix,
                                      rot90=DEFAULT_ROTATION,
                                      size=(400, 750),
                                      writer=partial(self.write, panel=2))

        mainsizer = wx.BoxSizer(wx.HORIZONTAL)
        mainsizer.Add(panel, 0, wx.LEFT | wx.GROW | wx.ALL)
        mainsizer.Add(self.image, 1, wx.CENTER | wx.GROW | wx.ALL)
        self.SetSizer(mainsizer)
        mainsizer.Fit(self)

        self.SetAutoLayout(True)

        try:
            self.SetIcon(wx.Icon(ICONFILE, wx.BITMAP_TYPE_ICO))
        except:
            pass

        wx.CallAfter(self.connect_pvs)

    def onColorMap(self, event=None):
        cmap_name = self.cmap_choice.GetStringSelection()
        if self.cmap_reverse.IsChecked():
            cmap_name = cmap_name + '_r'
        self.image.colormap = getattr(colormap, cmap_name)
        self.image.Refresh()

    def onCopyImage(self, event=None):
        "copy bitmap of canvas to system clipboard"
        bmp = wx.BitmapDataObject()
        bmp.SetBitmap(wx.Bitmap(self.image.GrabWxImage()))
        wx.TheClipboard.Open()
        wx.TheClipboard.SetData(bmp)
        wx.TheClipboard.Close()
        wx.TheClipboard.Flush()

    def onReadCalibFile(self, event=None):
        "read calibration file"
        wcards = "Poni Files(*.poni)|*.poni|All files (*.*)|*.*"
        dlg = wx.FileDialog(None,
                            message='Read Calibration File',
                            defaultDir=os.getcwd(),
                            wildcard=wcards,
                            style=wx.FD_OPEN)
        ppath = None
        if dlg.ShowModal() == wx.ID_OK:
            ppath = os.path.abspath(dlg.GetPath())

        if os.path.exists(ppath):
            if self.scandb is not None:
                CalibrationDialog(self, ppath).Show()
            else:
                self.setup_calibration(read_poni(ppath))

    def setup_calibration(self, calib):
        """set up calibration from calibration dict"""
        if self.image.rot90 in (1, 3):
            calib['rot3'] = np.pi / 2.0
        self.calib = calib
        if HAS_PYFAI:
            self.integrator = AzimuthalIntegrator(**calib)
            self.show1d_btn.Enable()

    def onShowIntegration(self, event=None):

        if self.calib is None or 'poni1' not in self.calib:
            return
        shown = False
        try:
            self.int_panel.Raise()
            shown = True
        except:
            self.int_panel = None
        if not shown:
            self.int_panel = PlotFrame(self)
            self.show_1dpattern(init=True)
        else:
            self.show_1dpattern()

    def onAutoIntegration(self, event=None):
        if not event.IsChecked():
            self.int_timer.Stop()
            return

        if self.calib is None or 'poni1' not in self.calib:
            return
        shown = False
        try:
            self.int_panel.Raise()
            shown = True
        except:
            self.int_panel = None
        if not shown:
            self.int_panel = PlotFrame(self)
            self.show_1dpattern(init=True)
        else:
            self.show_1dpattern()
        self.int_timer.Start(500)

    def show_1dpattern(self, init=False):
        if self.calib is None or not HAS_PYFAI:
            return

        img = self.ad_img.PV('ArrayData').get()

        h, w = self.image.GetImageSize()
        img.shape = (w, h)
        img = img[3:-3, 1:-1][::-1, :]

        img_id = self.ad_cam.ArrayCounter_RBV
        q, xi = self.integrator.integrate1d(img,
                                            2048,
                                            unit='q_A^-1',
                                            correctSolidAngle=True,
                                            polarization_factor=0.999)
        if init:
            self.int_panel.plot(q,
                                xi,
                                xlabel=r'$Q (\rm\AA^{-1})$',
                                marker='+',
                                title='Image %d' % img_id)
            self.int_panel.Raise()
            self.int_panel.Show()
        else:
            self.int_panel.update_line(0, q, xi, draw=True)
            self.int_panel.set_title('Image %d' % img_id)

    @EpicsFunction
    def onSaveImage(self, event=None):
        "prompts for and save image to file"
        defdir = os.getcwd()
        self.fname = "Image_%i.tiff" % self.ad_cam.ArrayCounter_RBV
        dlg = wx.FileDialog(None,
                            message='Save Image as',
                            defaultDir=os.getcwd(),
                            defaultFile=self.fname,
                            style=wx.FD_SAVE)
        path = None
        if dlg.ShowModal() == wx.ID_OK:
            path = os.path.abspath(dlg.GetPath())

        root, fname = os.path.split(path)
        epics.caput("%sTIFF1:FileName" % self.prefix, fname)
        epics.caput("%sTIFF1:FileWriteMode" % self.prefix, 0)
        time.sleep(0.05)
        epics.caput("%sTIFF1:WriteFile" % self.prefix, 1)
        time.sleep(0.05)

        print(
            "Saved TIFF File ",
            epics.caget("%sTIFF1:FullFileName_RBV" % self.prefix,
                        as_string=True))

    def onExit(self, event=None):
        try:
            wx.Yield()
        except:
            pass
        self.Destroy()

    def onAbout(self, event=None):
        msg = """Eiger Image Display version 0.1
Matt Newville <*****@*****.**>"""

        dlg = wx.MessageDialog(self, msg, "About Epics Image Display",
                               wx.OK | wx.ICON_INFORMATION)
        dlg.ShowModal()
        dlg.Destroy()

    def buildMenus(self):
        fmenu = wx.Menu()
        MenuItem(self, fmenu, "&Save\tCtrl+S", "Save Image", self.onSaveImage)
        MenuItem(self, fmenu, "&Copy\tCtrl+C", "Copy Image to Clipboard",
                 self.onCopyImage)
        MenuItem(self, fmenu, "Read Calibration File", "Read PONI Calibration",
                 self.onReadCalibFile)
        fmenu.AppendSeparator()
        MenuItem(self, fmenu, "E&xit\tCtrl+Q", "Exit Program", self.onExit)

        omenu = wx.Menu()
        MenuItem(self, omenu, "&Rotate CCW\tCtrl+R",
                 "Rotate Counter Clockwise", self.onRot90)
        MenuItem(self, omenu, "Flip Up/Down\tCtrl+T", "Flip Up/Down",
                 self.onFlipV)
        MenuItem(self, omenu, "Flip Left/Right\tCtrl+F", "Flip Left/Right",
                 self.onFlipH)
        MenuItem(self, omenu, "Reset Rotations and Flips", "Reset",
                 self.onResetRotFlips)
        omenu.AppendSeparator()

        hmenu = wx.Menu()
        MenuItem(self, hmenu, "About", "About Epics AreadDetector Display",
                 self.onAbout)

        mbar = wx.MenuBar()
        mbar.Append(fmenu, "File")
        mbar.Append(omenu, "Options")

        mbar.Append(hmenu, "&Help")
        self.SetMenuBar(mbar)

    def onResetRotFlips(self, event):
        self.image.rot90 = DEFAULT_ROTATION
        self.image.flipv = self.fliph = False

    def onRot90(self, event):
        self.image.rot90 = (self.image.rot90 - 1) % 4

    def onFlipV(self, event):
        self.image.flipv = not self.image.flipv

    def onFlipH(self, event):
        self.image.fliph = not self.image.fliph

    def set_contrast_level(self, contrast_level=0):
        self.image.contrast_levels = [contrast_level, 100.0 - contrast_level]

    def write(self, s, panel=0):
        """write a message to the Status Bar"""
        self.SetStatusText(text=s, number=panel)

    @EpicsFunction
    def onButton(self, event=None, key='free'):
        key = key.lower()
        if key.startswith('free'):
            self.image.restart_fps_counter()
            self.ad_cam.AcquireTime = 0.25
            self.ad_cam.AcquirePeriod = 0.25
            self.ad_cam.NumImages = 345600
            self.ad_cam.Acquire = 1
        elif key.startswith('start'):
            self.image.restart_fps_counter()
            self.ad_cam.Acquire = 1
        elif key.startswith('stop'):
            self.ad_cam.Acquire = 0

    @EpicsFunction
    def connect_pvs(self, verbose=True):
        if self.prefix is None or len(self.prefix) < 2:
            return

        if self.prefix.endswith(':'):
            self.prefix = self.prefix[:-1]
        if self.prefix.endswith(':image1'):
            self.prefix = self.prefix[:-7]
        if self.prefix.endswith(':cam1'):
            self.prefix = self.prefix[:-5]

        self.write('Connecting to AD %s' % self.prefix)
        self.ad_img = epics.Device(self.prefix + ':image1:',
                                   delim='',
                                   attrs=self.img_attrs)
        self.ad_cam = epics.Device(self.prefix + ':cam1:',
                                   delim='',
                                   attrs=self.cam_attrs)

        epics.caput("%s:TIFF1:EnableCallbacks" % self.prefix, 1)
        epics.caput("%s:TIFF1:AutoSave" % self.prefix, 0)
        epics.caput("%s:TIFF1:AutoIncrement" % self.prefix, 0)
        epics.caput("%s:TIFF1:FileWriteMode" % self.prefix, 0)

        time.sleep(0.002)
        if not self.ad_img.PV('UniqueId_RBV').connected:
            epics.poll()
            if not self.ad_img.PV('UniqueId_RBV').connected:
                self.write('Warning:  Camera seems to not be connected!')
                return
        if verbose:
            self.write('Connected to AD %s' % self.prefix)

        self.SetTitle("Epics Image Display: %s" % self.prefix)

        sizex = self.ad_cam.MaxSizeX_RBV
        sizey = self.ad_cam.MaxSizeY_RBV

        sizelabel = 'Image Size: %i x %i pixels'
        try:
            sizelabel = sizelabel % (sizex, sizey)
        except:
            sizelabel = sizelabel % (0, 0)

        self.imagesize.SetLabel(sizelabel)

        self.ad_cam.add_callback('DetectorState_RBV', self.onDetState)
        self.contrast.set_level_str('0.05')

    @DelayedEpicsCallback
    def onDetState(self, pvname=None, value=None, char_value=None, **kw):
        self.write(char_value, panel=1)
Example #7
0
class TestFrame(wx.Frame):
    def __init__(self, parent=None, *args,**kwds):

        kwds["style"] = wx.DEFAULT_FRAME_STYLE|wx.RESIZE_BORDER|wx.TAB_TRAVERSAL

        wx.Frame.__init__(self, parent, -1, '',
                         wx.DefaultPosition, wx.Size(-1,-1), **kwds)
        self.SetTitle(" WXMPlot Plotting Demo")

        self.SetFont(wx.Font(12,wx.SWISS,wx.NORMAL,wx.BOLD,False))
        menu = wx.Menu()
        menu_exit = menu.Append(-1, "E&xit", "Terminate the program")

        menuBar = wx.MenuBar()
        menuBar.Append(menu, "&File");
        self.SetMenuBar(menuBar)

        self.Bind(wx.EVT_MENU, self.OnExit, menu_exit)

        self.Bind(wx.EVT_CLOSE, self.OnExit)

        self.plotframe  = None

        self.create_data()
        framesizer = wx.BoxSizer(wx.VERTICAL)

        panel      = wx.Panel(self, -1, size=(-1, -1))
        panelsizer = wx.BoxSizer(wx.VERTICAL)

        panelsizer.Add( wx.StaticText(panel, -1, 'wxmplot 2D PlotPanel examples '),
                        0, wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.LEFT|wx.EXPAND, 10)

        b10 = wx.Button(panel, -1, 'Example #1',          size=(-1,-1))
        b20 = wx.Button(panel, -1, 'Example #2',          size=(-1,-1))
        b22 = wx.Button(panel, -1, 'Plot with 2 axes',    size=(-1,-1))
        b31 = wx.Button(panel, -1, 'Plot with Errorbars', size=(-1,-1))
        b32 = wx.Button(panel, -1, 'SemiLog Plot',        size=(-1,-1))
        b40 = wx.Button(panel, -1, 'Start Timed Plot',    size=(-1,-1))
        b50 = wx.Button(panel, -1, 'Stop Timed Plot',     size=(-1,-1))
        b60 = wx.Button(panel, -1, 'Plot 500,000 points',  size=(-1,-1))
        bmany1 = wx.Button(panel, -1, 'Plot 20 traces (delay_draw=False)', size=(-1,-1))
        bmany2 = wx.Button(panel, -1, 'Plot 20 traces (delay_draw=True)', size=(-1,-1))
        bmany3 = wx.Button(panel, -1, 'Plot 20 traces (use plot_many())', size=(-1,-1))

        b10.Bind(wx.EVT_BUTTON,self.onPlot1)
        b20.Bind(wx.EVT_BUTTON,self.onPlot2)
        b22.Bind(wx.EVT_BUTTON,self.onPlot2Axes)
        b31.Bind(wx.EVT_BUTTON,self.onPlotErr)
        b32.Bind(wx.EVT_BUTTON,self.onPlotSLog)
        b40.Bind(wx.EVT_BUTTON,self.onStartTimer)
        b50.Bind(wx.EVT_BUTTON,self.onStopTimer)
        b60.Bind(wx.EVT_BUTTON,self.onPlotBig)

        bmany1.Bind(wx.EVT_BUTTON,self.onPlotMany_Slow)
        bmany2.Bind(wx.EVT_BUTTON,self.onPlotMany_Delay)
        bmany3.Bind(wx.EVT_BUTTON,self.onPlotMany_Fast)

        panelsizer.Add(b10, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.LEFT, 5)
        panelsizer.Add(b20, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.LEFT, 5)
        panelsizer.Add(b22, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.LEFT, 5)
        panelsizer.Add(b31, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.LEFT, 5)
        panelsizer.Add(b32, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.LEFT, 5)
        panelsizer.Add(b40, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.LEFT, 5)
        panelsizer.Add(b50, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.LEFT, 5)
        panelsizer.Add(b60, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.LEFT, 5)

        panelsizer.Add(bmany1, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.LEFT, 5)
        panelsizer.Add(bmany2, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.LEFT, 5)
        panelsizer.Add(bmany3, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.LEFT, 5)

        panel.SetSizer(panelsizer)
        panelsizer.Fit(panel)

        framesizer.Add(panel, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.EXPAND,2)
        self.SetSizer(framesizer)
        framesizer.Fit(self)

        self.Bind(wx.EVT_TIMER, self.onTimer)
        self.timer = wx.Timer(self)
        self.Refresh()

    def create_data(self):
        self.count = 0
        self.x  = x = arange(0.0,25.0,0.1)
        self.y1 = 4*cos(2*pi*(x-1)/5.7)/(6+x) + 2*sin(2*pi*(x-1)/2.2)/(10)
        self.y2 = sin(2*pi*x/30.0)
        self.y3 =  -pi + 2*(x/10. + exp(-(x-3)/5.0))
        self.y4 =  exp(0.01 + 0.5*x ) / (x+2)
        self.y5 =  3000 * self.y3
        self.npts = len(self.x)
        self.bigx   = linspace(0, 2500, 500000)
        self.bigy   = (sin(pi*self.bigx/140.0) +
                       cos(pi*self.bigx/277.0) +
                       cos(pi*self.bigx/820.0))


        self.many_dlist = [(self.x, self.y1)]
        for i in range(19):
            self.many_dlist.append((self.x, sin(2*(i+1)*x/23.0)))


    def ShowPlotFrame(self, do_raise=True, clear=True):
        "make sure plot frame is enabled, and visible"
        if self.plotframe is None:
            self.plotframe = PlotFrame(self)
            self.has_plot = False
        try:
            self.plotframe.Show()
        except PyDeadObjectError:
            self.plotframe = PlotFrame(self)
            self.plotframe.Show()

        if do_raise:
            self.plotframe.Raise()
        if clear:
            self.plotframe.panel.clear()
            self.plotframe.reset_config()


    def onPlot1(self,event=None):
        self.ShowPlotFrame()
        self.plotframe.plot(self.x,self.y1)
        self.plotframe.oplot(self.x,self.y2)
        self.plotframe.write_message("Plot 1")

    def onPlot2(self,event=None):
        self.ShowPlotFrame()
        x  = arange(100)
        y1 = cos(pi*x/72)
        y2 = sin(pi*x/23)
        self.plotframe.plot(x, y1, color='red')
        self.plotframe.oplot(x, y2, color='green3', marker='+')
        self.plotframe.write_message("Plot 2")


    def onPlotErr(self,event=None):
        self.ShowPlotFrame()
        npts = 81
        x  = linspace(0, 40.0, npts)
        y  = 0.4 * cos(x/2.0) + random.normal(scale=0.03, size=npts)
        dy = 0.03 * (ones(npts) + random.normal(scale=0.2, size=npts))

        self.plotframe.plot(x, y, dy=dy, color='red', linewidth=0,
                            xlabel='x', ylabel='y', marker='o',
                            title='Plot with error bars')
        self.plotframe.write_message("Errorbars!")


    def onPlot2Axes(self,event=None):
        self.ShowPlotFrame()

        self.plotframe.plot( self.x,self.y2, color='black',style='dashed')
        self.plotframe.oplot(self.x,self.y5, color='red', side='right')
        self.plotframe.write_message("Plot with 2 axes")


    def onPlotSLog(self,event=None):
        self.ShowPlotFrame()

        self.plotframe.plot( self.x,self.y4,ylog_scale=True,
                             color='black',style='dashed')
        self.plotframe.write_message("Semi Log Plot")

    def onPlotBig(self,event=None):
        self.ShowPlotFrame()

        t0 = time.time()
        self.plotframe.plot(self.bigx, self.bigy, marker='+', linewidth=0)
        dt = time.time()-t0
        self.plotframe.write_message(
            "Plot array with npts=%i, elapsed time=%8.3f s" % (len(self.bigx),dt))

    def onPlotMany_Slow(self, event=None):
        self.ShowPlotFrame()
        dlist = self.many_dlist

        t0 = time.time()
        opts = dict(title='Plot 20 traces without delay_draw',
            show_legend=True, xlabel='x')

        self.plotframe.plot(dlist[0][0], dlist[0][1], **opts)
        for tdat in dlist[1:]:
            self.plotframe.oplot(tdat[0], tdat[1])

        dt = time.time()-t0
        self.plotframe.write_message(
            "Plot 20 traces without delay_draw=True, elapsed time=%8.3f s" % (dt))

    def onPlotMany_Delay(self, event=None):
        self.ShowPlotFrame()
        dlist = self.many_dlist

        t0 = time.time()
        opts = dict(title='Plot 20 traces with delay_draw',
            show_legend=True, xlabel='x')

        self.plotframe.plot(dlist[0][0], dlist[0][1], delay_draw=True, **opts)
        for tdat in dlist[1:-1]:
            self.plotframe.oplot(tdat[0], tdat[1], delay_draw=True)
        self.plotframe.oplot(dlist[-1][0], dlist[-1][1])
        dt = time.time()-t0
        self.plotframe.write_message(
            "Plot 20 traces with delay_draw=True, elapsed time=%8.3f s" % (dt))


    def onPlotMany_Fast(self, event=None):
        self.ShowPlotFrame()
        dlist = self.many_dlist

        t0 = time.time()
        opts = dict(title='Plot 20 traces using plot_many()',
            show_legend=True, xlabel='x')
        self.plotframe.plot_many(dlist, **opts)

        dt = time.time()-t0
        self.plotframe.write_message(
            "Plot 20 traces with plot_many(), elapsed time=%8.3f s" % (dt))

    def report_memory(i):
        pid = os.getpid()
        if os.name == 'posix':
            mem = os.popen("ps -o rss -p %i" % pid).readlines()[1].split()[0]
        else:
            mem = 0
        return int(mem)

    def onStartTimer(self,event=None):
        self.count    = 0
        self.up_count = 0
        self.n_update = 1
        self.datrange = None
        self.time0    = time.time()
        self.start_mem= self.report_memory()
        self.timer.Start(10)

    def timer_results(self):
        if (self.count < 2): return
        etime = time.time() - self.time0
        tpp   = etime/max(1,self.count)
        s = "drew %i points in %8.3f s: time/point= %8.4f s" % (self.count,etime,tpp)
        self.plotframe.write_message(s)
        self.time0 = 0
        self.count = 0
        self.datrange = None

    def onStopTimer(self,event=None):
        self.timer.Stop()
        try:
            self.timer_results()
        except:
            pass

    def onTimer(self, event):
        # print 'timer ', self.count, time.time()
        self.count += 1
        n = self.count
        if n < 2:
            self.ShowPlotFrame(do_raise=False, clear=False)
            return
        if n >= self.npts:
            self.timer.Stop()
            self.timer_results()
        elif n <= 3:
            self.plotframe.plot(self.x[:n], self.y1[:n])# , grid=False)

        else:
            self.plotframe.update_line(0, self.x[:n], self.y1[:n], update_limits=True, draw=True)
            etime = time.time() - self.time0
            s = " %i / %i points in %8.4f s" % (n,self.npts,etime)
            self.plotframe.write_message(s)

    def OnAbout(self, event):
        dlg = wx.MessageDialog(self, "This sample program shows some\n"
                              "examples of WXMPlot PlotFrame.\n"
                              "message dialog.",
                              "About WXMPlot test", wx.OK | wx.ICON_INFORMATION)
        dlg.ShowModal()
        dlg.Destroy()

    def OnExit(self, event):
        try:
            if self.plotframe != None:  self.plotframe.onExit()
        except:
            pass
        self.Destroy()