class TelemetrySoftware(wx.Frame):
    def __init__(self):
        super(TelemetrySoftware, self).__init__(None, title="URSS Telemetry")

        # initial data values
        self.voltage = MAX_VOLTAGE
        self.amperage = MIN_AMPERAGE
        self.rpm = MIN_RPM
        self.controllerTemp = MIN_CONTROLLER_TEMP

        # plot data
        self.voltage_values = []
        self.amperage_values = []
        self.timestamps = []
        self.goalVoltageLineDisplayed = False

        # fake telemetry flag
        self.fake_telemetry = True
        self.fake_telemetry_counter = 0

        self.Maximize(True)
        self.InitUI()
        self.InitTelemetryThread()
        self.Centre()
        self.Show()

    def InitUI(self):
        panelRoot = wx.Panel(self)
        panelRootSizer = wx.BoxSizer(wx.VERTICAL)

        topSplitter = wx.SplitterWindow(panelRoot,
                                        style=wx.SP_LIVE_UPDATE | wx.SP_3DSASH)
        topVerticalSplitter = wx.SplitterWindow(topSplitter,
                                                style=wx.SP_LIVE_UPDATE
                                                | wx.SP_3DSASH)

        #############################################
        #   TOP-LEFT PANEL (STATUS AND CONTROLS)    #
        #############################################

        panelTopLeft = wx.Panel(topVerticalSplitter)
        panelTopLeftSizer = wx.BoxSizer(wx.VERTICAL)

        # create gauges and set initial values
        self.voltageGauge = wx.Gauge(panelTopLeft, -1,
                                     MAX_VOLTAGE - MIN_VOLTAGE, (0, 0),
                                     (250, 25))
        self.voltageGauge.SetValue(self.voltage - MIN_VOLTAGE)

        self.amperageGauge = wx.Gauge(panelTopLeft, -1,
                                      MAX_AMPERAGE - MIN_AMPERAGE, (0, 0),
                                      (250, 25))
        self.amperageGauge.SetValue(self.amperage - MIN_AMPERAGE)

        self.rpmGauge = wx.Gauge(panelTopLeft, -1, MAX_RPM - MIN_RPM, (0, 0),
                                 (250, 25))
        self.rpmGauge.SetValue(self.rpm - MIN_RPM)

        self.controllerTempGauge = wx.Gauge(
            panelTopLeft, -1, MAX_CONTROLLER_TEMP - MIN_CONTROLLER_TEMP,
            (0, 0), (250, 25))
        self.controllerTempGauge.SetValue(self.controllerTemp -
                                          MIN_CONTROLLER_TEMP)

        # create labels
        self.voltageLabel = wx.StaticText(
            panelTopLeft, -1, "Voltage (" + str(self.voltage) + ")")
        self.amperagLabel = wx.StaticText(
            panelTopLeft, -1, "Amperage (" + str(self.amperage) + ")")
        self.rpmLabel = wx.StaticText(panelTopLeft, -1,
                                      "RPM (" + str(self.rpm) + ")")
        self.controllerTempLabel = wx.StaticText(
            panelTopLeft, -1,
            "Controller Temperature (" + str(self.controllerTemp) + ")")

        # Add voltage Gauge and label to BoxSizer
        panelTopLeftSizer.Add(self.voltageLabel, 0, wx.ALIGN_CENTRE_HORIZONTAL)
        panelTopLeftSizer.Add(self.voltageGauge, 1, wx.ALIGN_CENTRE_HORIZONTAL)
        # Add amperage Gauge and label to BoxSizer
        panelTopLeftSizer.Add(self.amperagLabel, 0, wx.ALIGN_CENTRE_HORIZONTAL)
        panelTopLeftSizer.Add(self.amperageGauge, 1,
                              wx.ALIGN_CENTRE_HORIZONTAL)
        # Add RPM Gauge and label to BoxSizer
        panelTopLeftSizer.Add(self.rpmLabel, 0, wx.ALIGN_CENTRE_HORIZONTAL)
        panelTopLeftSizer.Add(self.rpmGauge, 1, wx.ALIGN_CENTRE_HORIZONTAL)
        # Add controller temp Gauge and label to BoxSizer
        panelTopLeftSizer.Add(self.controllerTempLabel, 0,
                              wx.ALIGN_CENTRE_HORIZONTAL)
        panelTopLeftSizer.Add(self.controllerTempGauge, 1,
                              wx.ALIGN_CENTRE_HORIZONTAL)

        # Add BoxSizer to panel
        panelTopLeft.SetSizer(panelTopLeftSizer)

        ################################
        #   TOP-RIGHT PANEL (GRAPH)    #
        ################################

        panelTopRight = wx.Panel(topVerticalSplitter)
        panelTopRightSizer = wx.BoxSizer(wx.VERTICAL)

        # create top button bar
        topButtonPanel = wx.Panel(panelTopRight, -1)
        topButtonSizer = wx.BoxSizer(wx.HORIZONTAL)

        goalVoltageLabel = wx.StaticText(
            topButtonPanel, -1, '    End Goal Voltage Value (V):    ')
        self.goalEndVoltage = FloatCtrl(topButtonPanel,
                                        size=(100, -1),
                                        value=34.5,
                                        precision=1)
        endTimeLabel = wx.StaticText(topButtonPanel, -1,
                                     '    End Time (min):    ')
        self.endTime = FloatCtrl(topButtonPanel,
                                 size=(100, -1),
                                 value=120,
                                 precision=0)
        plotGoalVoltageButton = wx.Button(topButtonPanel,
                                          -1,
                                          'Plot Goal Voltage',
                                          size=(250, -1))
        plotGoalVoltageButton.Bind(wx.EVT_BUTTON, self.OnPlotGoalVoltage)

        topButtonSizer.Add(goalVoltageLabel)
        topButtonSizer.Add(self.goalEndVoltage)
        topButtonSizer.Add(endTimeLabel)
        topButtonSizer.Add(self.endTime)
        topButtonSizer.Add(plotGoalVoltageButton)

        topButtonPanel.SetSizer(topButtonSizer)
        topButtonSizer.Fit(topButtonPanel)

        # create plot panel

        self.plotPanel = PlotPanel(panelTopRight)

        # create bottom button bar

        bottomButtonPanel = wx.Panel(panelTopRight, -1)
        bottomButtonSizer = wx.BoxSizer(wx.HORIZONTAL)

        exportButton = wx.Button(bottomButtonPanel,
                                 -1,
                                 'Export Plot to CSV',
                                 size=(250, -1))
        exportButton.Bind(wx.EVT_BUTTON, self.ExportPlotDataToCSV)
        resetButton = wx.Button(bottomButtonPanel,
                                -1,
                                'Reset Graph',
                                size=(250, -1))
        resetButton.Bind(wx.EVT_BUTTON, self.ResetGraph)

        bottomButtonSizer.Add(exportButton, 1)
        bottomButtonSizer.Add(resetButton, 1)

        bottomButtonPanel.SetSizer(bottomButtonSizer)
        bottomButtonSizer.Fit(bottomButtonPanel)

        # Add panels to top right sizer
        panelTopRightSizer.Add(topButtonPanel, 0, wx.EXPAND | wx.ALL)
        panelTopRightSizer.Add(self.plotPanel, 1, wx.EXPAND | wx.ALL)
        panelTopRightSizer.Add(bottomButtonPanel, 0)

        # Add BoxSizer to panel
        panelTopRight.SetSizer(panelTopRightSizer)

        # add top panels to vertical splitter
        topVerticalSplitter.SplitVertically(panelTopLeft, panelTopRight)
        topVerticalSplitter.SetSashGravity(0.25)

        #############################################
        #   BOTTOM PANEL (LOG & TELEMETRY INPUT)    #
        #############################################

        panelBottom = wx.Panel(topSplitter)
        panelBottomSizer = wx.BoxSizer(wx.VERTICAL)

        self.logPane = LogPane(panelBottom)

        logPaneLabel = wx.StaticText(
            panelBottom,
            label="Telemetry Message Log (Last 100 messages shown):")
        logPaneLabel.SetFont(
            wx.Font(14, wx.FONTFAMILY_TELETYPE, wx.NORMAL, wx.BOLD))
        panelBottomSizer.Add(logPaneLabel, 0, wx.ALIGN_TOP)
        panelBottomSizer.Add(self.logPane, 1, wx.EXPAND | wx.ALL)

        panelBottom.SetSizer(panelBottomSizer)

        topSplitter.SplitHorizontally(topVerticalSplitter, panelBottom)
        topSplitter.SetSashGravity(0.75)

        panelRootSizer.Add(topSplitter, 1, wx.EXPAND | wx.ALL)
        panelRoot.SetSizer(panelRootSizer)

    def InitTelemetryThread(self):
        print("Initializing telemetry thread...")

        if not self.fake_telemetry:
            success = False
            try:
                self.serial = serial.Serial("/dev/cu.usbserial-DN01236H",
                                            57600)
                success = True
                if not self.serial.is_open:
                    success = False
            except Exception:
                print("Could not open serial radio!")

            if not success:
                # If we fail to connect to serial, display error and then quitself.
                dial = wx.MessageDialog(
                    None,
                    'Could not connect to serial radio. Please plug in the serial radio adapter and restart your computer!',
                    'Error', wx.OK | wx.ICON_ERROR)
                dial.ShowModal()
                exit(0)

        thread = threading.Thread(target=self.TelemetryThread)
        thread.start()

        print("Done.")

    def TelemetryCallback(self, message):
        timestamp = int(round(time.time()))
        if len(self.timestamps) == 0:
            self.t0 = timestamp

        self.logPane.AddLine(message)

        if not self.fake_telemetry:
            # parse JSON message
            m = json.loads(message)
            split_message = m['message'].split(',')
            if split_message[0] == 'BATTERY':
                self.voltage = float(split_message[2][2:]) / 1000
                self.amperage = float(split_message[4][2:]) / 1000 * -1

        # add values to lists
        self.voltage_values.append(self.voltage)
        self.amperage_values.append(self.amperage)
        self.timestamps.append(timestamp - self.t0)

        # update gauges and plot
        self.UpdateGauges()
        self.UpdatePlot()

    def UpdateGauges(self):
        self.voltageGauge.SetValue(self.voltage - MIN_VOLTAGE)
        self.voltageLabel.SetLabel("Voltage (" + str(self.voltage) + "/" +
                                   str(MAX_VOLTAGE) + ")")
        self.amperageGauge.SetValue(self.amperage - MIN_AMPERAGE)
        self.amperagLabel.SetLabel("Amperage (" + str(self.amperage) + "/" +
                                   str(MAX_AMPERAGE) + ")")
        self.rpmGauge.SetValue(self.rpm - MIN_RPM)
        self.rpmLabel.SetLabelText("RPM (" + str(self.rpm) + "/" +
                                   str(MAX_RPM) + ")")
        self.controllerTempGauge.SetValue(self.controllerTemp -
                                          MIN_CONTROLLER_TEMP)
        self.controllerTempLabel.SetLabelText("Controller Temperature (" +
                                              str(self.controllerTemp) + ")")

    def UpdatePlot(self):
        v_n = len(self.voltage_values)
        tdat = np.array(self.timestamps)
        vdat = np.array(self.voltage_values)
        adat = np.array(self.amperage_values)
        if v_n <= 2:
            self.plotPanel.plot(tdat,
                                vdat,
                                xlabel='Time (s from start)',
                                ylabel='Voltage (V)',
                                label='Voltage',
                                style='solid')
            self.plotPanel.oplot(tdat,
                                 adat,
                                 y2label='Amperage (A)',
                                 side='right',
                                 label='Amperage',
                                 style='long dashed',
                                 show_legend=True)
        else:
            self.plotPanel.update_line(0, tdat, vdat, draw=True)
            self.plotPanel.update_line(1, tdat, adat, draw=True)

    def OnPlotGoalVoltage(self, event=None):
        v = float(self.goalEndVoltage.GetValue())
        t = int(self.endTime.GetValue()) * 60
        if len(self.voltage_values) > 2 and v <= self.voltage and t >= 0:
            tdat = np.linspace(0, t, t)
            vdat = np.linspace(self.voltage_values[0], v, t)
            if not self.goalVoltageLineDisplayed:
                self.goalVoltageLineDisplayed = True
                self.plotPanel.oplot(tdat,
                                     vdat,
                                     label='Goal Voltage',
                                     style='short dashed')
            else:
                self.plotPanel.update_line(2, tdat, vdat, draw=True)

    def ResetGraph(self, event=None):
        del self.timestamps[:]
        del self.voltage_values[:]
        del self.amperage_values[:]
        self.goalVoltageLineDisplayed = False

    def ExportPlotDataToCSV(self, event=None):
        filename = 'exported_data_' + str(int(round(
            time.time() * 1000))) + '.csv'
        with open(filename, 'wb') as datafile:
            w = csv.writer(datafile)
            w.writerow(['Time (s)', 'Voltage (V)', 'Amperage (A)'])
            for i in range(len(self.timestamps)):
                w.writerow([
                    str(self.timestamps[i]),
                    str(self.voltage_values[i]),
                    str(self.amperage_values[i])
                ])

    def TelemetryThread(self):
        while True:
            if self.fake_telemetry:
                self.fake_telemetry_counter += 1
                wx.CallAfter(
                    self.TelemetryCallback, "Fake Telemetry Element " +
                    str(self.fake_telemetry_counter) + "\n")
                time.sleep(0.5)
            else:
                line = self.serial.readline()
                wx.CallAfter(self.TelemetryCallback, line)
Exemple #2
0
class StripChartFrame(wx.Frame):
    def __init__(self, parent, ID, **kws):
        kws["style"] = wx.DEFAULT_FRAME_STYLE | wx.RESIZE_BORDER | wx.TAB_TRAVERSAL

        wx.Frame.__init__(self, parent, ID, '', wx.DefaultPosition,
                          wx.Size(-1, -1), **kws)
        self.SetTitle("wxmplot StripChart Demo")

        self.tmin = 15.0

        self.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD, False))
        menu = wx.Menu()
        ID_EXIT = wx.NewId()
        ID_TIMER = 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)

        sbar = self.CreateStatusBar(2, wx.CAPTION)
        sfont = sbar.GetFont()
        sfont.SetWeight(wx.BOLD)
        sfont.SetPointSize(11)
        sbar.SetFont(sfont)
        self.SetStatusWidths([-3, -1])
        self.SetStatusText('', 0)

        mainsizer = wx.BoxSizer(wx.VERTICAL)

        btnpanel = wx.Panel(self, -1)
        btnsizer = wx.BoxSizer(wx.HORIZONTAL)

        b_on = wx.Button(btnpanel, -1, 'Start', size=(-1, -1))
        b_off = wx.Button(btnpanel, -1, 'Stop', size=(-1, -1))

        b_on.Bind(wx.EVT_BUTTON, self.onStartTimer)
        b_off.Bind(wx.EVT_BUTTON, self.onStopTimer)

        tlabel = wx.StaticText(btnpanel, -1, '  Time range:')
        self.time_range = FloatCtrl(btnpanel,
                                    size=(100, -1),
                                    value=abs(self.tmin),
                                    precision=1)

        btnsizer.Add(b_on, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 0)
        btnsizer.Add(b_off, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 0)
        btnsizer.Add(
            tlabel, 1,
            wx.GROW | wx.ALL | wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 0)
        btnsizer.Add(self.time_range, 0,
                     wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 0)

        btnpanel.SetSizer(btnsizer)
        btnsizer.Fit(btnpanel)

        self.plotpanel = PlotPanel(self, messenger=self.write_message)
        self.plotpanel.BuildPanel()
        self.plotpanel.set_xlabel('Time from Present (s)')
        mainsizer.Add(btnpanel, 0,
                      wx.GROW | wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 0)
        mainsizer.Add(
            self.plotpanel, 1,
            wx.GROW | wx.ALL | wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 0)
        self.SetSizer(mainsizer)
        mainsizer.Fit(self)

        self.Bind(wx.EVT_TIMER, self.onTimer)
        self.timer = wx.Timer(self)
        self.count = 0
        self.Refresh()
        wx.CallAfter(self.onStartTimer)

    def write_message(self, msg, panel=0):
        """write a message to the Status Bar"""
        self.SetStatusText(msg, panel)

    def onStartTimer(self, event=None):
        self.count = 0
        t0, y0 = next_data()
        self.ylist = [y0]
        self.tlist = [t0]
        self.tmin_last = -10000
        self.time0 = time.time()
        self.timer.Start(50)

    def onStopTimer(self, event=None):
        self.timer.Stop()

    def onTimer(self, event):
        self.count += 1
        etime = time.time() - self.time0
        self.tmin = float(self.time_range.GetValue())
        t1, y1 = next_data()
        self.tlist.append(t1)
        self.ylist.append(y1)
        tdat = np.array(self.tlist) - t1
        mask = np.where(tdat > -abs(self.tmin))
        ydat = np.array(self.ylist)

        n = len(self.ylist)
        if n <= 2:
            self.plotpanel.plot(tdat, ydat)
        else:
            self.plotpanel.update_line(0, tdat, ydat, draw=True)
            self.write_message(" %i points in %8.4f s" % (n, etime))

        lims = self.plotpanel.get_viewlimits()
        try:
            ymin, ymax = ydat[mask].min(), ydat[mask].max()
        except:
            ymin, ymax = ydat.min(), ydat.max()
        tmin = max(int(min(tdat)) - 1.0, -self.tmin)
        if (ymin < lims[2] or ymax > lims[3] or tmin != self.tmin_last
                or time.time() - self.last_update > 2):
            self.tmin_last = tmin
            self.last_update = time.time()
            self.plotpanel.set_xylims((tmin, 0, ymin, ymax))

    def OnAbout(self, event):
        dlg = wx.MessageDialog(self, "wxmplot example: stripchart app",
                               "About WXMPlot test",
                               wx.OK | wx.ICON_INFORMATION)
        dlg.ShowModal()
        dlg.Destroy()

    def OnExit(self, event):
        self.Destroy()
Exemple #3
0
class Viewer1DXRD(wx.Panel):
    '''
    Frame for housing all 1D XRD viewer widgets
    '''
    label='Viewer'
    def __init__(self,parent,owner=None,_larch=None):
        
        wx.Panel.__init__(self, parent)

        self.parent = parent
        self.owner = owner

        ## Default information
        self.data_name    = []
        self.xy_data      = []
        self.xy_plot      = []
        self.plotted_data = []
        self.xy_scale     = []
        self.wavelength   = None
        self.xlabel       = 'q (A^-1)'
        self.xunits        = ['q','d']

        self.cif_name     = []
        self.cif_data     = []
        self.cif_plot     = []
        self.plotted_cif  = []
        
        self.x_for_zoom = None


        self.Panel1DViewer()

##############################################
#### PANEL DEFINITIONS
    def Panel1DViewer(self):
        '''
        Frame for housing all 1D XRD viewer widgets
        '''
        leftside  = self.LeftSidePanel(self)
        rightside = self.RightSidePanel(self)        

        panel1D = wx.BoxSizer(wx.HORIZONTAL)
        panel1D.Add(leftside,flag=wx.ALL,border=10)
        panel1D.Add(rightside,proportion=1,flag=wx.EXPAND|wx.ALL,border=10)

        self.SetSizer(panel1D)
    
    def Toolbox(self,panel):
        '''
        Frame for visual toolbox
        '''
        
        tlbx = wx.StaticBox(self,label='PLOT TOOLBOX')
        vbox = wx.StaticBoxSizer(tlbx,wx.VERTICAL)

        ###########################
        ## X-Scale
        hbox_xaxis = wx.BoxSizer(wx.HORIZONTAL)
        ttl_xaxis = wx.StaticText(self, label='X-SCALE')
        self.ch_xaxis = wx.Choice(self,choices=self.xunits)

        self.ch_xaxis.Bind(wx.EVT_CHOICE, self.checkXaxis)
    
        hbox_xaxis.Add(ttl_xaxis, flag=wx.RIGHT, border=8)
        hbox_xaxis.Add(self.ch_xaxis, flag=wx.EXPAND, border=8)
        vbox.Add(hbox_xaxis, flag=wx.ALL, border=10)

        ###########################
        ## Y-Scale
        hbox_yaxis = wx.BoxSizer(wx.HORIZONTAL)
        ttl_yaxis = wx.StaticText(self, label='Y-SCALE')
        yscales = ['linear','log']
        self.ch_yaxis = wx.Choice(self,choices=yscales)

        self.ch_yaxis.Bind(wx.EVT_CHOICE,   None)
    
        hbox_yaxis.Add(ttl_yaxis, flag=wx.RIGHT, border=8)
        hbox_yaxis.Add(self.ch_yaxis, flag=wx.EXPAND, border=8)
        vbox.Add(hbox_yaxis, flag=wx.ALL, border=10)
        
        return vbox

    def DataBox(self,panel):
        '''
        Frame for data toolbox
        '''
        
        tlbx = wx.StaticBox(self,label='DATA TOOLBOX')
        vbox = wx.StaticBoxSizer(tlbx,wx.VERTICAL)


        ###########################
        ## DATA CHOICE

        self.ch_data = wx.Choice(self,choices=self.data_name)
        self.ch_data.Bind(wx.EVT_CHOICE,   self.onSELECT)
        vbox.Add(self.ch_data, flag=wx.EXPAND|wx.ALL, border=8)
    
        #self.ttl_data = wx.StaticText(self, label='')
        #vbox.Add(self.ttl_data, flag=wx.EXPAND|wx.ALL, border=8)

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

#         self.ck_bkgd = wx.CheckBox(self,label='BACKGROUND')
#         self.ck_smth = wx.CheckBox(self,label='SMOOTHING')
#         
#         self.ck_bkgd.Bind(wx.EVT_CHECKBOX,   None)
#         self.ck_smth.Bind(wx.EVT_CHECKBOX,   None)
# 
#         vbox.Add(self.ck_bkgd, flag=wx.ALL, border=8)
#         vbox.Add(self.ck_smth, flag=wx.ALL, border=8)
    
        ###########################
        ## Scale
        hbox_scl = wx.BoxSizer(wx.HORIZONTAL)
        ttl_scl = wx.StaticText(self, label='SCALE Y TO:')
        self.entr_scale = wx.TextCtrl(self,wx.TE_PROCESS_ENTER)
        btn_scale = wx.Button(self,label='set')

        btn_scale.Bind(wx.EVT_BUTTON, self.normalize1Ddata)
        
        hbox_scl.Add(ttl_scl, flag=wx.RIGHT, border=8)
        hbox_scl.Add(self.entr_scale, flag=wx.RIGHT, border=8)
        hbox_scl.Add(btn_scale, flag=wx.RIGHT, border=8)

        vbox.Add(hbox_scl, flag=wx.BOTTOM|wx.TOP, border=8)

        ###########################
        ## Hide/show and reset
        hbox_btns = wx.BoxSizer(wx.HORIZONTAL)
        
        btn_hide  = wx.Button(self,label='hide')
        btn_reset = wx.Button(self,label='reset')
        btn_rmv   = wx.Button(self,label='remove')
        
        btn_hide.Bind(wx.EVT_BUTTON,  self.hide1Ddata)
        btn_reset.Bind(wx.EVT_BUTTON, self.reset1Dscale)
        btn_rmv.Bind(wx.EVT_BUTTON,   self.remove1Ddata)

        btn_hide.Disable()
        btn_rmv.Disable()
        
        hbox_btns.Add(btn_reset, flag=wx.ALL, border=10)
        hbox_btns.Add(btn_hide,  flag=wx.ALL, border=10)
        hbox_btns.Add(btn_rmv,   flag=wx.ALL, border=10)
        vbox.Add(hbox_btns, flag=wx.ALL, border=10)
        return vbox   
        

        

    def AddPanel(self,panel):
    
        hbox = wx.BoxSizer(wx.HORIZONTAL)
        
        btn_data = wx.Button(panel,label='ADD NEW DATA SET')
        btn_data.Bind(wx.EVT_BUTTON, self.loadXYFILE)

        btn_cif = wx.Button(panel,label='ADD NEW CIF')
        btn_cif.Bind(wx.EVT_BUTTON, self.loadCIF)
    
        hbox.Add(btn_data, flag=wx.ALL, border=8)
        hbox.Add(btn_cif, flag=wx.ALL, border=8)
        return hbox

    def LeftSidePanel(self,panel):
        
        vbox = wx.BoxSizer(wx.VERTICAL)
        
        plttools = self.Toolbox(self)
        addbtns = self.AddPanel(self)
        dattools = self.DataBox(self)
        
        vbox.Add(plttools,flag=wx.ALL,border=10)
        vbox.Add(addbtns,flag=wx.ALL,border=10)
        vbox.Add(dattools,flag=wx.ALL,border=10)
        return vbox

    def RightSidePanel(self,panel):
        vbox = wx.BoxSizer(wx.VERTICAL)
        self.plot1DXRD(panel)
        btnbox = self.QuickButtons(panel)
        vbox.Add(self.plot1D,proportion=1,flag=wx.ALL|wx.EXPAND,border = 10)
        vbox.Add(btnbox,flag=wx.ALL|wx.ALIGN_RIGHT,border = 10)
        return vbox

    def QuickButtons(self,panel):
        buttonbox = wx.BoxSizer(wx.HORIZONTAL)
        btn_img = wx.Button(panel,label='SAVE FIGURE')
        btn_calib = wx.Button(panel,label='PLOT SETTINGS')
        btn_integ = wx.Button(panel,label='RESET PLOT')
        
        btn_img.Bind(wx.EVT_BUTTON,   self.onSAVEfig)
        btn_calib.Bind(wx.EVT_BUTTON, self.onPLOTset)
        btn_integ.Bind(wx.EVT_BUTTON, self.onRESETplot)
        
        buttonbox.Add(btn_img, flag=wx.ALL, border=8)
        buttonbox.Add(btn_calib, flag=wx.ALL, border=8)
        buttonbox.Add(btn_integ, flag=wx.ALL, border=8)
        return buttonbox


##############################################
#### PLOTPANEL FUNCTIONS
    def plot1DXRD(self,panel):
    
        self.plot1D = PlotPanel(panel,size=(1000, 500))
        self.plot1D.messenger = self.owner.write_message
        

        ## Set defaults for plotting  
        self.plot1D.set_ylabel('Intensity (a.u.)')
        self.plot1D.cursor_mode = 'zoom'
  
        ## trying to get this functionality into our gui
        ## mkak 2016.11.10      
#         interactive_legend().show()

    def onSAVEfig(self,event):
        self.plot1D.save_figure()
        
    def onPLOTset(self,event):
        self.plot1D.configure()
        
    def onRESETplot(self,event):
        self.plot1D.reset_config()



##############################################
#### XRD PLOTTING FUNCTIONS
       
    def add1Ddata(self,x,y,name=None,cif=False,wavelength=None):
        
        plt_no = len(self.data_name)
        
        if cif:
            if name is None:
                name = 'cif %i' % plt_no
            else:
               name = 'cif: %s' % name
        else:
            if name is None:
                name = 'dataset %i' % plt_no
            else:
                name = 'data: %s' % name
                
        if wavelength is not None:
            self.addLAMBDA(wavelength)

        ## Add to data array lists
        self.data_name.append(name)
        self.xy_scale.append(max(y))
        self.xy_data.extend([x,y])

        ## redefine x,y based on scales
        self.xy_plot.extend([x,y])
       
        ## Add to plot       
        self.plotted_data.append(self.plot1D.oplot(x,y,label=name,show_legend=True))#,xlabel=self.xlabel))

        ## Use correct x-axis units
        self.checkXaxis(None)

        self.ch_data.Set(self.data_name)
        self.ch_data.SetStringSelection(name)
        
        ## Update toolbox panel, scale all cif to 1000
        if cif is True:
            self.entr_scale.SetValue('1000')
            self.normalize1Ddata(None)
        else:
            self.entr_scale.SetValue(str(self.xy_scale[plt_no]))

    def addLAMBDA(self,wavelength,units='m'):
        
        ## convert to units A
        if units == 'm':
            self.wavelength = wavelength*1e10 
        elif units == 'cm':
            self.wavelength = wavelength*1e8
        elif units == 'mm':
            self.wavelength = wavelength*1e7        
        elif units == 'um':
            self.wavelength = wavelength*1e4
        elif units == 'nm':
            self.wavelength = wavelength*1e1
        else: ## units 'A'        
            self.wavelength = wavelength

        self.xunits.append(u'2\u03B8')
        self.ch_xaxis.Set(self.xunits)

    def normalize1Ddata(self,event):
    
        plt_no = self.ch_data.GetSelection()
        self.xy_scale[plt_no] = float(self.entr_scale.GetValue())
        if self.xy_scale[plt_no] <= 0:
            self.xy_scale[plt_no] = max(self.xy_data[(plt_no*2+1)])
            self.entr_scale.SetValue(str(self.xy_scale[plt_no]))

        y = self.xy_data[(plt_no*2+1)]
        self.xy_plot[(plt_no*2+1)] = y/np.max(y) * self.xy_scale[plt_no]

        self.updatePLOT()
        

    def remove1Ddata(self,event):
        
        ## Needs pop up warning: "Do you really want to delete this data set from plotter?
        ## Current settings will not be saved."
        ## mkak 2016.11.10
        
        plt_no = self.ch_data.GetSelection()        
        print('EVENTUALLY, button will remove plot: %s' % self.data_name[plt_no])

        ## removing name from list works... do not activate till rest is working
        ## mkak 2016.11.10
#         self.data_name.remove(self.data_name[plt_no])
#         self.ch_data.Set(self.data_name)

    def hide1Ddata(self,event):

        plt_no = self.ch_data.GetSelection()        
        print('EVENTUALLY, button will hide plot: %s' % self.data_name[plt_no])

    def onSELECT(self,event):
    
        data_str = self.ch_data.GetString(self.ch_data.GetSelection())
#         self.ttl_data.SetLabel('SELECTED: %s' % data_str)
        
        plt_no = self.ch_data.GetSelection()
        self.entr_scale.SetValue(str(self.xy_scale[plt_no]))

    def checkXaxis(self, event):
        
        if self.ch_xaxis.GetSelection() == 2:
            for plt_no in range(len(self.plotted_data)):
                self.xy_plot[plt_no*2] = calc_q_to_2th(self.xy_data[plt_no*2],self.wavelength)
        elif self.ch_xaxis.GetSelection() == 1:
            for plt_no in range(len(self.plotted_data)):
                self.xy_plot[plt_no*2] = calc_q_to_d(self.xy_data[plt_no*2])
        else:
            for plt_no in range(len(self.plotted_data)):
                self.xy_plot[plt_no*2] = self.xy_data[plt_no*2]

        if self.ch_xaxis.GetSelection() == 2:
            self.xlabel = r'$2\Theta$'+r' $(^\circ)$'
        elif self.ch_xaxis.GetSelection() == 1:
            self.xlabel = 'd ($\AA$)'
        else:
            self.xlabel = 'q (1/$\AA$)'
         
        self.plot1D.set_xlabel(self.xlabel)
        self.updatePLOT()

    def updatePLOT(self):

        xmax,xmin,ymax,ymin = None,0,None,0
    
        if len(self.plotted_data) > 0:
            for plt_no in range(len(self.plotted_data)):

                i = plt_no*2
                j = i+1
 
                x = self.xy_plot[i]
                y = self.xy_plot[j]
                
                if xmax is None or xmax < max(x):
                    xmax = max(x)
                if xmin > min(x):
                    xmin = min(x)
                if ymax is None or ymax < max(y):
                    ymax = max(y)
                if ymin > min(y):
                    ymin = min(y)
                
                self.plot1D.update_line(plt_no,x,y)
            
            self.unzoom_all()
            self.plot1D.canvas.draw()
            
            if self.ch_xaxis.GetSelection() == 1:
                xmax = 5
            self.plot1D.set_xylims([xmin, xmax, ymin, ymax])

    def reset1Dscale(self,event):

        plt_no = self.ch_data.GetSelection()        
       
        self.xy_plot[(plt_no*2+1)] = self.xy_data[(plt_no*2+1)]
        self.plot1D.update_line(plt_no,self.xy_plot[(plt_no*2)],
                                       self.xy_plot[(plt_no*2+1)])
        self.plot1D.canvas.draw()
        self.unzoom_all()
        
        self.updatePLOT()
        self.xy_scale[plt_no] = max(self.xy_data[(plt_no*2+1)])
        self.entr_scale.SetValue(str(self.xy_scale[plt_no]))

####### BEGIN #######            
## THIS IS DIRECTLY FROM XRDDISPLAY.PY
## mkak 2016.11.11
    def unzoom_all(self, event=None):

        xmid, xrange, xmin, xmax = self._get1Dlims()

        self._set_xview(xmin, xmax)
        self.xview_range = None

    def _get1Dlims(self):
        xmin, xmax = self.plot1D.axes.get_xlim()
        xrange = xmax-xmin
        xmid   = (xmax+xmin)/2.0
        if self.x_for_zoom is not None:
            xmid = self.x_for_zoom
        return (xmid, xrange, xmin, xmax)

    def _set_xview(self, x1, x2, keep_zoom=False, pan=False):

        xmin,xmax = self.abs_limits()
        xrange = x2-x1
        x1 = max(xmin,x1)
        x2 = min(xmax,x2)

        if pan:
            if x2 == xmax:
                x1 = x2-xrange
            elif x1 == xmin:
                x2 = x1+xrange
        if not keep_zoom:
            self.x_for_zoom = (x1+x2)/2.0
        self.plot1D.axes.set_xlim((x1, x2))
        self.xview_range = [x1, x2]
        self.plot1D.canvas.draw()

    def abs_limits(self):
        if len(self.data_name) > 0:
            xmin, xmax = self.xy_plot[0].min(), self.xy_plot[0].max()
   
        return xmin,xmax
#######  END  #######
       

##############################################
#### XRD FILE OPENING/SAVING 
    def loadXYFILE(self,event):
    
        wildcards = 'XRD data file (*.xy)|*.xy|All files (*.*)|*.*'
        dlg = wx.FileDialog(self, message='Choose 1D XRD data file',
                           defaultDir=os.getcwd(),
                           wildcard=wildcards, style=wx.FD_OPEN)

        path, read = None, False
        if dlg.ShowModal() == wx.ID_OK:
            read = True
            path = dlg.GetPath().replace('\\', '/')
        dlg.Destroy()
        
        if read:
            try:
                x,y = xy_file_reader(path)

                self.add1Ddata(x,y,name=os.path.split(path)[-1])
            except:
               print('incorrect xy file format: %s' % os.path.split(path)[-1])



    def saveXYFILE(self,event):
        wildcards = 'XRD data file (*.xy)|*.xy|All files (*.*)|*.*'
        dlg = wx.FileDialog(self, 'Save data as...',
                           defaultDir=os.getcwd(),
                           wildcard=wildcards,
                           style=wx.SAVE|wx.OVERWRITE_PROMPT)

        path, save = None, False
        if dlg.ShowModal() == wx.ID_OK:
            save = True
            path = dlg.GetPath().replace('\\', '/')
        dlg.Destroy()
        
        if save:
            ## mkak 2016.11.16
            print('need to write something to save data - like pyFAI does?')

    def loadCIF(self,event):
    
        wildcards = 'XRD cifile (*.cif)|*.cif|All files (*.*)|*.*'
        dlg = wx.FileDialog(self, message='Choose CIF',
                           defaultDir=os.getcwd(),
                           wildcard=wildcards, style=wx.FD_OPEN)

        path, read = None, False
        if dlg.ShowModal() == wx.ID_OK:
            read = True
            path = dlg.GetPath().replace('\\', '/')
        dlg.Destroy()
        
        if read:
            cifile = os.path.split(path)[-1]

            try:
                cif = xu.materials.Crystal.fromCIF(path)
            except:
                print('incorrect file format: %s' % os.path.split(path)[-1])
                return

            ## generate hkl list
            hkllist = []
            maxhkl = 8
            for i in range(-maxhkl,maxhkl+1):
                for j in range(-maxhkl,maxhkl+1):
                    for k in range(-maxhkl,maxhkl+1):
                        if i+j+k > 0: # as long as h,k,l all positive, eliminates 0,0,0
                            hkllist.append([i,j,k])
            
            hc = constants.value(u'Planck constant in eV s') * \
                       constants.value(u'speed of light in vacuum') * 1e-3 ## units: keV-m

            if self.wavelength is not None:
                qlist = cif.Q(hkllist)
                Flist = cif.StructureFactorForQ(qlist,(hc/(self.wavelength*(1e-10))*1e3))
            
                Fall = []
                qall = []
                hklall = []
                for i,hkl in enumerate(hkllist):
                    if np.abs(Flist[i]) > 0.01:
                        Fadd = np.abs(Flist[i])
                        qadd = np.linalg.norm(qlist[i])
                        if qadd not in qall and qadd < 6:
                            Fall.extend((0,Fadd,0))
                            qall.extend((qadd,qadd,qadd))
                if np.shape(Fall)[0] > 0:
                    Fall = np.array(Fall)
                    qall = np.array(qall)
                    self.add1Ddata(qall,Fall,name=os.path.split(path)[-1],cif=True)
                else:
                    print('Could not calculate real structure factors.')
            else:
                print('Wavelength/energy must be specified for structure factor calculations.')

    def openPONI(self,event):
             
        wildcards = 'pyFAI calibration file (*.poni)|*.poni|All files (*.*)|*.*'
        dlg = wx.FileDialog(self, message='Choose pyFAI calibration file',
                           defaultDir=os.getcwd(),
                           wildcard=wildcards, style=wx.FD_OPEN)

        path, read = None, False
        if dlg.ShowModal() == wx.ID_OK:
            read = True
            path = dlg.GetPath().replace('\\', '/')
        dlg.Destroy()
        
        if read:

            try:
                print('Loading calibration file: %s' % path)
                ai = pyFAI.load(path)
            except:
                print('Not recognized as a pyFAI calibration file.')
                return

            self.addLAMBDA(ai._wavelength,units='m')

    def setLAMBDA(self,event):

        dlg = SetLambdaDialog()

        path, okay = None, False
        if dlg.ShowModal() == wx.ID_OK:
            okay = True
            wavelength = dlg.wavelength
        dlg.Destroy()
        
        if okay:
            self.addLAMBDA(wavelength,units='A')
Exemple #4
0
class Fitting1DXRD(wx.Panel):
    '''
    Frame for housing all 1D XRD fitting widgets
    '''
    label='Fitting'
    def __init__(self,parent,owner=None,_larch=None):
        
        wx.Panel.__init__(self, parent)

        self.parent = parent
        self.owner = owner

        ## Default information
        self.xlabel       = 'q (A^-1)'
        self.xunits        = ['q','d']

        self.Panel1DFitting()
    

     
##############################################
#### PANEL DEFINITIONS
    def Panel1DFitting(self):
        '''
        Frame for housing all 1D XRD viewer widgets
        '''
        leftside  = self.LeftSidePanel(self)
        rightside = self.RightSidePanel(self)        

        panel1D = wx.BoxSizer(wx.HORIZONTAL)
        panel1D.Add(leftside,flag=wx.ALL,border=10)
        panel1D.Add(rightside,proportion=1,flag=wx.EXPAND|wx.ALL,border=10)

        self.SetSizer(panel1D)
    
    def Toolbox(self,panel):
        '''
        Frame for visual toolbox
        '''
        
        tlbx = wx.StaticBox(self,label='PLOT TOOLBOX')
        vbox = wx.StaticBoxSizer(tlbx,wx.VERTICAL)

        ###########################
        ## X-Scale
        hbox_xaxis = wx.BoxSizer(wx.HORIZONTAL)
        ttl_xaxis = wx.StaticText(self, label='X-SCALE')
        self.ch_xaxis = wx.Choice(self,choices=self.xunits)

        self.ch_xaxis.Bind(wx.EVT_CHOICE, self.checkXaxis)
    
        hbox_xaxis.Add(ttl_xaxis, flag=wx.RIGHT, border=8)
        hbox_xaxis.Add(self.ch_xaxis, flag=wx.EXPAND, border=8)
        vbox.Add(hbox_xaxis, flag=wx.ALL, border=10)

        ###########################
        ## Y-Scale
        hbox_yaxis = wx.BoxSizer(wx.HORIZONTAL)
        ttl_yaxis = wx.StaticText(self, label='Y-SCALE')
        yscales = ['linear','log']
        self.ch_yaxis = wx.Choice(self,choices=yscales)

        self.ch_yaxis.Bind(wx.EVT_CHOICE,   None)
    
        hbox_yaxis.Add(ttl_yaxis, flag=wx.RIGHT, border=8)
        hbox_yaxis.Add(self.ch_yaxis, flag=wx.EXPAND, border=8)
        vbox.Add(hbox_yaxis, flag=wx.ALL, border=10)
        
        return vbox

    def LeftSidePanel(self,panel):
        
        vbox = wx.BoxSizer(wx.VERTICAL)
        
        plttools = self.Toolbox(self)
        
        vbox.Add(plttools,flag=wx.ALL,border=10)
        return vbox

    def RightSidePanel(self,panel):
        vbox = wx.BoxSizer(wx.VERTICAL)
        self.plot1DXRD(panel)
        btnbox = self.QuickButtons(panel)
        vbox.Add(self.plot1D,proportion=1,flag=wx.ALL|wx.EXPAND,border = 10)
        vbox.Add(btnbox,flag=wx.ALL|wx.ALIGN_RIGHT,border = 10)
        return vbox

    def QuickButtons(self,panel):
        buttonbox = wx.BoxSizer(wx.HORIZONTAL)
        btn_img = wx.Button(panel,label='SAVE FIGURE')
        btn_calib = wx.Button(panel,label='PLOT SETTINGS')
        btn_integ = wx.Button(panel,label='RESET PLOT')
        
        btn_img.Bind(wx.EVT_BUTTON,   self.onSAVEfig)
        btn_calib.Bind(wx.EVT_BUTTON, self.onPLOTset)
        btn_integ.Bind(wx.EVT_BUTTON, self.onRESETplot)
        
        buttonbox.Add(btn_img, flag=wx.ALL, border=8)
        buttonbox.Add(btn_calib, flag=wx.ALL, border=8)
        buttonbox.Add(btn_integ, flag=wx.ALL, border=8)
        return buttonbox


##############################################
#### PLOTPANEL FUNCTIONS
    def plot1DXRD(self,panel):
    
        self.plot1D = PlotPanel(panel,size=(1000, 500))
        self.plot1D.messenger = self.owner.write_message
        

        ## Set defaults for plotting  
        self.plot1D.set_ylabel('Intensity (a.u.)')
        self.plot1D.cursor_mode = 'zoom'
  
        ## trying to get this functionality into our gui
        ## mkak 2016.11.10      
#         interactive_legend().show()

    def onSAVEfig(self,event):
        self.plot1D.save_figure()
        
    def onPLOTset(self,event):
        self.plot1D.configure()
        
    def onRESETplot(self,event):
        self.plot1D.reset_config()

    def checkXaxis(self, event):
        
        if self.ch_xaxis.GetSelection() == 2:
            for plt_no in range(len(self.plotted_data)):
                self.xy_plot[plt_no*2] = calc_q_to_2th(self.xy_data[plt_no*2],self.wavelength)
        elif self.ch_xaxis.GetSelection() == 1:
            for plt_no in range(len(self.plotted_data)):
                self.xy_plot[plt_no*2] = calc_q_to_d(self.xy_data[plt_no*2])
        else:
            for plt_no in range(len(self.plotted_data)):
                self.xy_plot[plt_no*2] = self.xy_data[plt_no*2]

        if self.ch_xaxis.GetSelection() == 2:
            self.xlabel = r'$2\Theta$'+r' $(^\circ)$'
        elif self.ch_xaxis.GetSelection() == 1:
            self.xlabel = 'd ($\AA$)'
        else:
            self.xlabel = 'q (1/$\AA$)'
         
        self.plot1D.set_xlabel(self.xlabel)
        self.updatePLOT()

    def updatePLOT(self):

        xmax,xmin,ymax,ymin = None,0,None,0
    
        if len(self.plotted_data) > 0:
            for plt_no in range(len(self.plotted_data)):

                i = plt_no*2
                j = i+1
 
                x = self.xy_plot[i]
                y = self.xy_plot[j]
                
                if xmax is None or xmax < max(x):
                    xmax = max(x)
                if xmin > min(x):
                    xmin = min(x)
                if ymax is None or ymax < max(y):
                    ymax = max(y)
                if ymin > min(y):
                    ymin = min(y)
                
                self.plot1D.update_line(plt_no,x,y)
            
            self.unzoom_all()
            self.plot1D.canvas.draw()
            
            if self.ch_xaxis.GetSelection() == 1:
                xmax = 5
            self.plot1D.set_xylims([xmin, xmax, ymin, ymax])

    def reset1Dscale(self,event):

        plt_no = self.ch_data.GetSelection()        
       
        self.xy_plot[(plt_no*2+1)] = self.xy_data[(plt_no*2+1)]
        self.plot1D.update_line(plt_no,self.xy_plot[(plt_no*2)],
                                       self.xy_plot[(plt_no*2+1)])
        self.plot1D.canvas.draw()
        self.unzoom_all()
        
        self.updatePLOT()
        self.xy_scale[plt_no] = max(self.xy_data[(plt_no*2+1)])
        self.entr_scale.SetValue(str(self.xy_scale[plt_no]))

####### BEGIN #######            
## THIS IS DIRECTLY FROM XRDDISPLAY.PY
## mkak 2016.11.11
    def unzoom_all(self, event=None):

        xmid, xrange, xmin, xmax = self._get1Dlims()

        self._set_xview(xmin, xmax)
        self.xview_range = None

    def _get1Dlims(self):
        xmin, xmax = self.plot1D.axes.get_xlim()
        xrange = xmax-xmin
        xmid   = (xmax+xmin)/2.0
        if self.x_for_zoom is not None:
            xmid = self.x_for_zoom
        return (xmid, xrange, xmin, xmax)

    def _set_xview(self, x1, x2, keep_zoom=False, pan=False):

        xmin,xmax = self.abs_limits()
        xrange = x2-x1
        x1 = max(xmin,x1)
        x2 = min(xmax,x2)

        if pan:
            if x2 == xmax:
                x1 = x2-xrange
            elif x1 == xmin:
                x2 = x1+xrange
        if not keep_zoom:
            self.x_for_zoom = (x1+x2)/2.0
        self.plot1D.axes.set_xlim((x1, x2))
        self.xview_range = [x1, x2]
        self.plot1D.canvas.draw()

    def abs_limits(self):
        if len(self.data_name) > 0:
            xmin, xmax = self.xy_plot[0].min(), self.xy_plot[0].max()
   
        return xmin,xmax
Exemple #5
0
class StripChartFrame(wx.Frame):
    def __init__(self, parent, ID, **kws):
        kws["style"] = wx.DEFAULT_FRAME_STYLE|wx.RESIZE_BORDER|wx.TAB_TRAVERSAL

        wx.Frame.__init__(self, parent, ID, '',
                         wx.DefaultPosition, wx.Size(-1,-1), **kws)
        self.SetTitle("wxmplot StripChart Demo")

        self.tmin = 15.0

        self.SetFont(wx.Font(12,wx.SWISS,wx.NORMAL,wx.BOLD,False))
        menu = wx.Menu()
        ID_EXIT  = wx.NewId()
        ID_TIMER = 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)

        sbar = self.CreateStatusBar(2,wx.CAPTION)
        sfont = sbar.GetFont()
        sfont.SetWeight(wx.BOLD)
        sfont.SetPointSize(11)
        sbar.SetFont(sfont)
        self.SetStatusWidths([-3,-1])
        self.SetStatusText('',0)

        mainsizer = wx.BoxSizer(wx.VERTICAL)

        btnpanel = wx.Panel(self, -1)
        btnsizer = wx.BoxSizer(wx.HORIZONTAL)

        b_on  = wx.Button(btnpanel, -1, 'Start',   size=(-1,-1))
        b_off = wx.Button(btnpanel, -1, 'Stop',    size=(-1,-1))

        b_on.Bind(wx.EVT_BUTTON, self.onStartTimer)
        b_off.Bind(wx.EVT_BUTTON, self.onStopTimer)

        tlabel = wx.StaticText(btnpanel, -1, '  Time range:')
        self.time_range = FloatCtrl(btnpanel,  size=(100, -1),
                                    value=abs(self.tmin), precision=1)

        btnsizer.Add(b_on,   0, wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.LEFT, 0)
        btnsizer.Add(b_off,  0, wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.LEFT, 0)
        btnsizer.Add(tlabel, 1, wx.GROW|wx.ALL|wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.LEFT, 0)
        btnsizer.Add(self.time_range, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.LEFT, 0)

        btnpanel.SetSizer(btnsizer)
        btnsizer.Fit(btnpanel)

        self.plotpanel = PlotPanel(self, messenger=self.write_message)
        self.plotpanel.BuildPanel()
        self.plotpanel.set_xlabel('Time from Present (s)')
        mainsizer.Add(btnpanel,       0,
                      wx.GROW|wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.LEFT, 0)
        mainsizer.Add(self.plotpanel, 1,
                      wx.GROW|wx.ALL|wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.LEFT, 0)
        self.SetSizer(mainsizer)
        mainsizer.Fit(self)

        self.Bind(wx.EVT_TIMER, self.onTimer)
        self.timer = wx.Timer(self)
        self.count    = 0
        self.Refresh()
        wx.CallAfter(self.onStartTimer)

    def write_message(self, msg, panel=0):
        """write a message to the Status Bar"""
        self.SetStatusText(msg, panel)

    def onStartTimer(self,event=None):
        self.count    = 0
        t0,y0 = next_data()
        self.ylist = [y0]
        self.tlist = [t0]
        self.tmin_last = -10000
        self.time0    = time.time()
        self.timer.Start(50)

    def onStopTimer(self,event=None):
        self.timer.Stop()

    def onTimer(self, event):
        self.count += 1
        etime = time.time() - self.time0
        self.tmin = float(self.time_range.GetValue())
        t1, y1 = next_data()
        self.tlist.append(t1)
        self.ylist.append(y1)
        tdat = np.array(self.tlist) - t1
        mask = np.where(tdat > -abs(self.tmin))
        ydat = np.array(self.ylist)

        n = len(self.ylist)
        if n <= 2:
            self.plotpanel.plot(tdat, ydat)
        else:
            self.plotpanel.update_line(0, tdat, ydat, draw=True)
            self.write_message(" %i points in %8.4f s" % (n,etime))

        lims = self.plotpanel.get_viewlimits()
        try:
            ymin, ymax = ydat[mask].min(), ydat[mask].max()
        except:
            ymin, ymax = ydat.min(), ydat.max()
        tmin = max(int(min(tdat)) - 1.0, -self.tmin)
        if (ymin < lims[2] or ymax >  lims[3] or
            tmin != self.tmin_last or time.time()-self.last_update > 2):
            self.tmin_last = tmin
            self.last_update = time.time()
            self.plotpanel.set_xylims((tmin, 0, ymin, ymax))

    def OnAbout(self, event):
        dlg = wx.MessageDialog(self, "wxmplot example: stripchart app",
                              "About WXMPlot test", wx.OK | wx.ICON_INFORMATION)
        dlg.ShowModal()
        dlg.Destroy()

    def OnExit(self, event):
        self.Destroy()
Exemple #6
0
class Runner(noname.MyFrame1):

    power_rendered = False
    data = data.Data

    def __init__(self, parent):
        noname.MyFrame1.__init__(self, parent)

    def render_input_sound(self, event):

        if wx.Event.GetEventType(event) == 10084 or wx.Event.GetEventType(
                event) == 10161:

            self.m_panel2.Refresh()

            self.canvas1 = PlotPanel(self.m_panel2,
                                     size=(self.m_panel2.GetSize()))

            if hasattr(self.data, 'time') and hasattr(self.data,
                                                      'input_sound'):
                self.canvas1.plot(self.data.time, self.data.input_sound)

            return

        else:
            self.canvas1.update_line(0,
                                     self.data.time,
                                     self.data.input_sound,
                                     draw=True)
            return

    def render_power(self, event):
        if wx.Event.GetEventType(event) == 10084 or wx.Event.GetEventType(
                event) == 10161:

            if (self.power_rendered):
                self.canvas2.update_line(0,
                                         self.data.truncated_frequency,
                                         self.data.truncated_power,
                                         draw=True)
            else:
                self.canvas2 = PlotPanel(self.m_panel3,
                                         size=(self.m_panel3.GetSize()))

                if hasattr(self.data, 'truncated_frequency') and hasattr(
                        self.data, 'truncated_power'):
                    self.canvas2.plot(self.data.truncated_frequency,
                                      self.data.truncated_power, 'r')
                    self.canvas2.oplot(
                        self.data.truncated_frequency,
                        np.full((len(self.data.truncated_frequency)),
                                self.data.min))
                    self.power_rendered = True

            return

        # For slider
        else:

            p = backend.get_cutoff_value(self.data.min, self.data.slope,
                                         self.m_slider1.GetValue())
            if (self.power_rendered):
                self.canvas2.update_line(
                    1,
                    self.data.truncated_frequency,
                    np.full((len(self.data.truncated_frequency)), p),
                    draw=True)

            else:
                self.canvas2 = PlotPanel(self.m_panel3,
                                         size=(self.m_panel3.GetSize()))
                self.canvas2.plot(self.data.truncated_frequency,
                                  self.data.truncated_power, 'r')
                self.canvas2.oplot(
                    self.data.truncated_frequency,
                    np.full((len(self.data.truncated_frequency)),
                            self.data.min))
                self.power_rendered = True

            return

    def render_output(self, event):

        if wx.Event.GetEventType(event) == 10084 or wx.Event.GetEventType(
                event) == 10161:

            self.m_panel4.Refresh()

            self.canvas3 = PlotPanel(self.m_panel4,
                                     size=(self.m_panel4.GetSize()))

            if hasattr(self.data, 'time') and hasattr(self.data, 'ifft'):
                self.canvas3.plot(self.data.time, self.data.ifft)

            return

        else:

            self.canvas3.update_line(0,
                                     self.data.time,
                                     self.data.ifft,
                                     draw=True)
            return

    def loadAudio(self, event):
        ''' 
        Loads audio from path and calls render functions.\n
        wx event: 10161
        '''

        self.data.load_sound(location=self.m_filePicker1.GetPath())
        self.data.load_power_graph()
        # Fire screen refresh event
        self.render_input_sound(event)
        self.render_power(event)
        self.render_output(event)

        return

    def slider_move(self, event):
        self.render_power(event)

        self.data.load_output(
            backend.get_cutoff_value(self.data.min, self.data.slope,
                                     self.m_slider1.GetValue()))

        self.render_output(event)

    def export(self, event):
        self.data.export()

    def play(self, event):
        sd.play(self.data.ifft, self.data.fs)
        time.sleep(len(self.data.input_sound) / self.data.fs)
        sd.stop()

    def add_noise(self, event):
        self.data.add_noise()
        self.render_input_sound(event)
        self.render_power(event)
        self.render_output(event)