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)
class AthenaImporter(wx.Frame) : """Import Athena File""" def __init__(self, parent, filename=None, read_ok_cb=None, size=(725, 450), _larch=None): self.parent = parent self.filename = filename self.larch = _larch self.read_ok_cb = read_ok_cb self.colors = GUIColors() wx.Frame.__init__(self, parent, -1, size=size, style=FRAMESTYLE) splitter = wx.SplitterWindow(self, style=wx.SP_LIVE_UPDATE) splitter.SetMinimumPaneSize(200) leftpanel = wx.Panel(splitter) ltop = wx.Panel(leftpanel) sel_none = Button(ltop, 'Select None', size=(100, 30), action=self.onSelNone) sel_all = Button(ltop, 'Select All', size=(100, 30), action=self.onSelAll) sel_imp = Button(ltop, 'Import Selected Groups', size=(200, 30), action=self.onOK) self.select_imported = sel_imp self.grouplist = FileCheckList(leftpanel, select_action=self.onShowGroup) tsizer = wx.GridBagSizer(2, 2) tsizer.Add(sel_all, (0, 0), (1, 1), LCEN, 0) tsizer.Add(sel_none, (0, 1), (1, 1), LCEN, 0) tsizer.Add(sel_imp, (1, 0), (1, 2), LCEN, 0) pack(ltop, tsizer) sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(ltop, 0, LCEN|wx.GROW, 1) sizer.Add(self.grouplist, 1, LCEN|wx.GROW|wx.ALL, 1) pack(leftpanel, sizer) # right hand side rightpanel = wx.Panel(splitter) self.SetTitle("Reading Athena Project '%s'" % self.filename) self.title = SimpleText(rightpanel, self.filename, font=Font(13), colour=self.colors.title, style=LCEN) self.plotpanel = PlotPanel(rightpanel, messenger=self.plot_messages) sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(self.title, 0, LCEN, 2) sizer.Add(self.plotpanel, 0, LCEN, 2) pack(rightpanel, sizer) splitter.SplitVertically(leftpanel, rightpanel, 1) self.statusbar = self.CreateStatusBar(2, 0) self.statusbar.SetStatusWidths([-3, -1]) statusbar_fields = [self.filename, ""] for i in range(len(statusbar_fields)): self.statusbar.SetStatusText(statusbar_fields[i], i) self.a_project = read_athena(self.filename, do_bkg=False, do_fft=False, _larch=_larch) self.allgroups = [] for item in dir(self.a_project): if not item.startswith('_athena_'): self.allgroups.append(item) self.grouplist.Append(item) self.Show() self.Raise() def plot_messages(self, msg, panel=1): self.SetStatusText(msg, panel) def onOK(self, event=None): """generate script to import groups""" namelist = [str(n) for n in self.grouplist.GetCheckedStrings()] if len(namelist) == 0: cancel = Popup(self, """No data groups selected. Cancel import from this project?""", 'Cancel Import?', style=wx.YES_NO) if wx.ID_YES == cancel: self.Destroy() else: return if self.read_ok_cb is not None: self.read_ok_cb(self.filename, namelist) self.Destroy() def onCancel(self, event=None): self.Destroy() def onSelAll(self, event=None): self.grouplist.SetCheckedStrings(self.allgroups) def onSelNone(self, event=None): self.grouplist.SetCheckedStrings([]) def onShowGroup(self, event=None): """column selections changed calc xdat and ydat""" gname = event.GetString() grp = getattr(self.a_project, gname) glist = list(self.grouplist.GetCheckedStrings()) if gname not in glist: glist.append(gname) self.grouplist.SetCheckedStrings(glist) if hasattr(grp, 'energy') and hasattr(grp, 'mu'): self.plotpanel.plot(grp.energy, grp.mu, xlabel='Energy', ylabel='mu',title=gname)
class AthenaImporter(wx.Frame): """Import Athena File""" def __init__(self, parent, filename=None, read_ok_cb=None, size=(725, 450), _larch=None): self.parent = parent self.filename = filename self.larch = _larch self.read_ok_cb = read_ok_cb self.colors = GUIColors() wx.Frame.__init__(self, parent, -1, size=size, style=FRAMESTYLE) splitter = wx.SplitterWindow(self, style=wx.SP_LIVE_UPDATE) splitter.SetMinimumPaneSize(200) leftpanel = wx.Panel(splitter) ltop = wx.Panel(leftpanel) sel_none = Button(ltop, 'Select None', size=(100, 30), action=self.onSelNone) sel_all = Button(ltop, 'Select All', size=(100, 30), action=self.onSelAll) sel_imp = Button(ltop, 'Import Selected Groups', size=(200, 30), action=self.onOK) self.select_imported = sel_imp self.select_imported.Disable() self.grouplist = FileCheckList(leftpanel, select_action=self.onShowGroup) self.grouplist.SetBackgroundColour(wx.Colour(255, 255, 255)) tsizer = wx.GridBagSizer(2, 2) tsizer.Add(sel_all, (0, 0), (1, 1), LCEN, 0) tsizer.Add(sel_none, (0, 1), (1, 1), LCEN, 0) tsizer.Add(sel_imp, (1, 0), (1, 2), LCEN, 0) pack(ltop, tsizer) sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(ltop, 0, LCEN | wx.GROW, 1) sizer.Add(self.grouplist, 1, LCEN | wx.GROW | wx.ALL, 1) pack(leftpanel, sizer) # right hand side rightpanel = wx.Panel(splitter) self.SetTitle("Reading Athena Project '%s'" % self.filename) self.title = SimpleText(rightpanel, self.filename, font=Font(13), colour=self.colors.title, style=LCEN) self.plotpanel = PlotPanel(rightpanel, messenger=self.plot_messages) sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(self.title, 0, LCEN, 2) sizer.Add(self.plotpanel, 0, LCEN, 2) pack(rightpanel, sizer) splitter.SplitVertically(leftpanel, rightpanel, 1) self.statusbar = self.CreateStatusBar(2, 0) self.statusbar.SetStatusWidths([-3, -1]) statusbar_fields = [self.filename, ""] for i in range(len(statusbar_fields)): self.statusbar.SetStatusText(statusbar_fields[i], i) self.all = read_athena(self.filename, do_bkg=False, do_fft=False, with_journal=False, _larch=_larch) for item in dir(self.all): self.grouplist.Append(item) self.Show() self.Raise() def plot_messages(self, msg, panel=1): self.SetStatusText(msg, panel) def onOK(self, event=None): """generate script to import groups""" namelist = [str(n) for n in self.grouplist.GetCheckedStrings()] if self.read_ok_cb is not None and len(namelist) > 0: self.read_ok_cb(self.filename, namelist) self.Destroy() def onCancel(self, event=None): self.Destroy() def onSelAll(self, event=None): self.grouplist.SetCheckedStrings(dir(self.all)) self.select_imported.Enable() def onSelNone(self, event=None): self.grouplist.SetCheckedStrings([]) self.select_imported.Disable() def onShowGroup(self, event=None): """column selections changed calc xdat and ydat""" self.select_imported.Enable() gname = event.GetString() grp = getattr(self.all, gname) glist = list(self.grouplist.GetCheckedStrings()) if gname not in glist: glist.append(gname) self.grouplist.SetCheckedStrings(glist) if hasattr(grp, 'energy') and hasattr(grp, 'mu'): self.plotpanel.plot(grp.energy, grp.mu, xlabel='Energy', ylabel='mu', title=gname)
class ColumnDataFileFrame(wx.Frame): """Column Data File, select columns""" def __init__(self, parent, filename=None, groupname=None, last_array_sel=None, read_ok_cb=None, edit_groupname=True, _larch=None): self.parent = parent self._larch = _larch self.path = filename group = self.initgroup = self.read_column_file(self.path) self.subframes = {} self.workgroup = Group(raw=group) for attr in ('path', 'filename', 'groupname', 'datatype', 'array_labels'): setattr(self.workgroup, attr, getattr(group, attr, None)) arr_labels = [l.lower() for l in self.initgroup.array_labels] if self.workgroup.datatype is None: self.workgroup.datatype = 'raw' if ('energ' in arr_labels[0] or 'energ' in arr_labels[1]): self.workgroup.datatype = 'xas' self.read_ok_cb = read_ok_cb self.array_sel = { 'xpop': '', 'xarr': None, 'ypop': '', 'yop': '/', 'yarr1': None, 'yarr2': None, 'use_deriv': False } if last_array_sel is not None: self.array_sel.update(last_array_sel) if self.array_sel['yarr2'] is None and 'i0' in arr_labels: self.array_sel['yarr2'] = 'i0' if self.array_sel['yarr1'] is None: if 'itrans' in arr_labels: self.array_sel['yarr1'] = 'itrans' elif 'i1' in arr_labels: self.array_sel['yarr1'] = 'i1' message = "Data Columns for %s" % group.filename wx.Frame.__init__(self, None, -1, 'Build Arrays from Data Columns for %s' % group.filename, style=FRAMESTYLE) self.SetFont(Font(10)) panel = wx.Panel(self) self.SetMinSize((600, 600)) self.colors = GUIColors() # title row title = SimpleText(panel, message, font=Font(13), colour=self.colors.title, style=LCEN) opts = dict(action=self.onUpdate, size=(120, -1)) yarr_labels = self.yarr_labels = arr_labels + ['1.0', '0.0', ''] xarr_labels = self.xarr_labels = arr_labels + ['_index'] self.xarr = Choice(panel, choices=xarr_labels, **opts) self.yarr1 = Choice(panel, choices=arr_labels, **opts) self.yarr2 = Choice(panel, choices=yarr_labels, **opts) self.yerr_arr = Choice(panel, choices=yarr_labels, **opts) self.yerr_arr.Disable() self.datatype = Choice(panel, choices=DATATYPES, **opts) self.datatype.SetStringSelection(self.workgroup.datatype) opts['size'] = (50, -1) self.yop = Choice(panel, choices=ARR_OPS, **opts) opts['size'] = (120, -1) self.use_deriv = Check(panel, label='use derivative', default=self.array_sel['use_deriv'], **opts) self.xpop = Choice(panel, choices=XPRE_OPS, **opts) self.ypop = Choice(panel, choices=YPRE_OPS, **opts) opts['action'] = self.onYerrChoice self.yerr_op = Choice(panel, choices=YERR_OPS, **opts) self.yerr_op.SetSelection(0) self.yerr_const = FloatCtrl(panel, value=1, precision=4, size=(90, -1)) ylab = SimpleText(panel, 'Y = ') xlab = SimpleText(panel, 'X = ') yerr_lab = SimpleText(panel, 'Yerror = ') self.xsuf = SimpleText(panel, '') self.ysuf = SimpleText(panel, '') self.xpop.SetStringSelection(self.array_sel['xpop']) self.ypop.SetStringSelection(self.array_sel['ypop']) self.yop.SetStringSelection(self.array_sel['yop']) if '(' in self.array_sel['ypop']: self.ysuf.SetLabel(')') ixsel, iysel, iy2sel = 0, 1, len(yarr_labels) - 1 if self.array_sel['xarr'] in xarr_labels: ixsel = xarr_labels.index(self.array_sel['xarr']) if self.array_sel['yarr1'] in arr_labels: iysel = arr_labels.index(self.array_sel['yarr1']) if self.array_sel['yarr2'] in yarr_labels: iy2sel = yarr_labels.index(self.array_sel['yarr2']) self.xarr.SetSelection(ixsel) self.yarr1.SetSelection(iysel) self.yarr2.SetSelection(iy2sel) bpanel = wx.Panel(panel) bsizer = wx.BoxSizer(wx.HORIZONTAL) _ok = Button(bpanel, 'OK', action=self.onOK) _cancel = Button(bpanel, 'Cancel', action=self.onCancel) _edit = Button(bpanel, 'Edit Array Names', action=self.onEditNames) bsizer.Add(_ok) bsizer.Add(_cancel) bsizer.Add(_edit) _ok.SetDefault() pack(bpanel, bsizer) sizer = wx.GridBagSizer(4, 8) sizer.Add(title, (0, 0), (1, 7), LCEN, 5) ir = 1 sizer.Add(xlab, (ir, 0), (1, 1), LCEN, 0) sizer.Add(self.xpop, (ir, 1), (1, 1), CEN, 0) sizer.Add(self.xarr, (ir, 2), (1, 1), CEN, 0) sizer.Add(self.xsuf, (ir, 3), (1, 1), CEN, 0) ir += 1 sizer.Add(ylab, (ir, 0), (1, 1), LCEN, 0) sizer.Add(self.ypop, (ir, 1), (1, 1), CEN, 0) sizer.Add(self.yarr1, (ir, 2), (1, 1), CEN, 0) sizer.Add(self.yop, (ir, 3), (1, 1), CEN, 0) sizer.Add(self.yarr2, (ir, 4), (1, 1), CEN, 0) sizer.Add(self.ysuf, (ir, 5), (1, 1), CEN, 0) sizer.Add(self.use_deriv, (ir, 6), (1, 1), LCEN, 0) ir += 1 sizer.Add(yerr_lab, (ir, 0), (1, 1), LCEN, 0) sizer.Add(self.yerr_op, (ir, 1), (1, 1), CEN, 0) sizer.Add(self.yerr_arr, (ir, 2), (1, 1), CEN, 0) sizer.Add(SimpleText(panel, 'Value:'), (ir, 3), (1, 1), CEN, 0) sizer.Add(self.yerr_const, (ir, 4), (1, 2), CEN, 0) ir += 1 sizer.Add(SimpleText(panel, 'Data Type:'), (ir, 0), (1, 1), LCEN, 0) sizer.Add(self.datatype, (ir, 1), (1, 2), LCEN, 0) ir += 1 self.wid_groupname = wx.TextCtrl(panel, value=group.groupname, size=(240, -1)) if not edit_groupname: self.wid_groupname.Disable() sizer.Add(SimpleText(panel, 'Group Name:'), (ir, 0), (1, 1), LCEN, 0) sizer.Add(self.wid_groupname, (ir, 1), (1, 2), LCEN, 0) ir += 1 sizer.Add(bpanel, (ir, 0), (1, 5), LCEN, 3) pack(panel, sizer) self.nb = fnb.FlatNotebook(self, -1, agwStyle=FNB_STYLE) self.nb.SetTabAreaColour(wx.Colour(248, 248, 240)) self.nb.SetActiveTabColour(wx.Colour(254, 254, 195)) self.nb.SetNonActiveTabTextColour(wx.Colour(40, 40, 180)) self.nb.SetActiveTabTextColour(wx.Colour(80, 0, 0)) self.plotpanel = PlotPanel(self, messenger=self.plot_messages) textpanel = wx.Panel(self) ftext = wx.TextCtrl(textpanel, style=wx.TE_MULTILINE | wx.TE_READONLY, size=(400, 250)) ftext.SetValue(group.text) ftext.SetFont(Font(10)) textsizer = wx.BoxSizer(wx.VERTICAL) textsizer.Add(ftext, 1, LCEN | wx.GROW, 1) pack(textpanel, textsizer) self.nb.AddPage(textpanel, ' Text of Data File ', True) self.nb.AddPage(self.plotpanel, ' Plot of Selected Arrays ', True) mainsizer = wx.BoxSizer(wx.VERTICAL) mainsizer.Add(panel, 0, wx.GROW | wx.ALL, 2) mainsizer.Add(self.nb, 1, LCEN | wx.GROW, 2) pack(self, mainsizer) self.statusbar = self.CreateStatusBar(2, 0) self.statusbar.SetStatusWidths([-1, -1]) statusbar_fields = [group.filename, ""] for i in range(len(statusbar_fields)): self.statusbar.SetStatusText(statusbar_fields[i], i) self.Show() self.Raise() self.onUpdate(self) def read_column_file(self, path): """read column file, generally as initial read""" parent, filename = os.path.split(path) with open(path, 'r') as fh: lines = fh.readlines() text = ''.join(lines) line1 = lines[0].lower() reader = 'read_ascii' if 'epics stepscan file' in line1: reader = 'read_gsexdi' elif 'xdi' in line1: reader = 'read_xdi' elif 'epics scan' in line1: reader = 'read_gsescan' tmpname = '_tmp_file_' read_cmd = "%s = %s('%s')" % (tmpname, reader, path) self.reader = reader deeplarch = self._larch._larch try: deeplarch.eval(read_cmd, add_history=False) except: pass if deeplarch.error: # self._larch.input.clear() msg = ["Error trying to read '%s':" % path, ""] for err in deeplarch.error: exc_name, errmsg = err.get_error() msg.append(errmsg) title = "Cannot read %s" % path r = Popup(self.parent, "\n".join(msg), title) return None group = self._larch.symtable.get_symbol(tmpname) self._larch.symtable.del_symbol(tmpname) group.text = text group.path = path group.filename = filename group.groupname = file2groupname(filename, symtable=self._larch.symtable) return group def show_subframe(self, name, frameclass, **opts): shown = False if name in self.subframes: try: self.subframes[name].Raise() shown = True except: del self.subframes[name] if not shown: self.subframes[name] = frameclass(self, **opts) def onEditNames(self, evt=None): self.show_subframe('editcol', EditColumnFrame, group=self.workgroup, on_ok=self.set_array_labels) def set_array_labels(self, arr_labels): self.workgroup.array_labels = arr_labels yarr_labels = self.yarr_labels = arr_labels + ['1.0', '0.0', ''] xarr_labels = self.xarr_labels = arr_labels + ['_index'] def update(wid, choices): curstr = wid.GetStringSelection() curind = wid.GetSelection() wid.SetChoices(choices) if curstr in choices: wid.SetStringSelection(curstr) else: wid.SetSelection(curind) update(self.xarr, xarr_labels) update(self.yarr1, yarr_labels) update(self.yarr2, yarr_labels) update(self.yerr_arr, yarr_labels) self.onUpdate() def onOK(self, event=None): """ build arrays according to selection """ if self.wid_groupname is not None: groupname = fix_varname(self.wid_groupname.GetValue()) yerr_op = self.yerr_op.GetStringSelection().lower() yerr_expr = '1' if yerr_op.startswith('const'): yerr_expr = "%f" % self.yerr_const.GetValue() elif yerr_op.startswith('array'): yerr_expr = '%%s.data[%i, :]' % self.yerr_arr.GetSelection() elif yerr_op.startswith('sqrt'): yerr_expr = 'sqrt(%s.ydat)' self.expressions['yerr'] = yerr_expr # generate script to pass back to calling program: labels = ', '.join(self.workgroup.array_labels) read_cmd = "%s('{path:s}', labels='%s')" % (self.reader, labels) buff = ["{group:s} = %s" % read_cmd, "{group:s}.path = '{path:s}'"] for attr in ('datatype', 'plot_xlabel', 'plot_ylabel'): val = getattr(self.workgroup, attr) buff.append("{group:s}.%s = '%s'" % (attr, val)) for aname in ('xdat', 'ydat', 'yerr'): expr = self.expressions[aname].replace('%s', '{group:s}') buff.append("{group:s}.%s = %s" % (aname, expr)) if getattr(self.workgroup, 'datatype', 'raw') == 'xas': if self.reader == 'read_gsescan': buff.append("{group:s}.energy = {group:s}.x") else: buff.append("{group:s}.energy = {group:s}.xdat") buff.append("{group:s}.mu = {group:s}.ydat") script = "\n".join(buff) if self.read_ok_cb is not None: self.read_ok_cb(script, self.path, groupname=groupname, array_sel=self.array_sel) self.Destroy() def onCancel(self, event=None): self.workgroup.import_ok = False self.Destroy() def onYerrChoice(self, evt=None): yerr_choice = evt.GetString() self.yerr_arr.Disable() self.yerr_const.Disable() if 'const' in yerr_choice.lower(): self.yerr_const.Enable() elif 'array' in yerr_choice.lower(): self.yerr_arr.Enable() self.onUpdate() def onUpdate(self, value=None, evt=None): """column selections changed calc xdat and ydat""" # dtcorr = self.dtcorr.IsChecked() # print("Column Frame on Update ") dtcorr = False use_deriv = self.use_deriv.IsChecked() rawgroup = self.initgroup workgroup = self.workgroup rdata = self.initgroup.data # print("onUpdate ", dir(rawgroup)) ix = self.xarr.GetSelection() xname = self.xarr.GetStringSelection() exprs = dict(xdat=None, ydat=None, yerr=None) ncol, npts = rdata.shape if xname.startswith('_index') or ix >= ncol: workgroup.xdat = 1.0 * np.arange(npts) xname = '_index' exprs['xdat'] = 'arange(%i)' % npts else: workgroup.xdat = rdata[ix, :] exprs['xdat'] = '%%s.data[%i, : ]' % ix workgroup.datatype = self.datatype.GetStringSelection().strip().lower() def pre_op(opwid, arr): opstr = opwid.GetStringSelection().strip() suf = '' if opstr in ('-log(', 'log('): suf = ')' if opstr == 'log(': arr = np.log(arr) elif opstr == '-log(': arr = -np.log(arr) return suf, opstr, arr try: xsuf, xpop, workgroup.xdat = pre_op(self.xpop, workgroup.xdat) self.xsuf.SetLabel(xsuf) exprs['xdat'] = '%s%s%s' % (xpop, exprs['xdat'], xsuf) except: return try: xunits = rawgroup.array_units[ix].strip() xlabel = '%s (%s)' % (xname, xunits) except: xlabel = xname yname1 = self.yarr1.GetStringSelection().strip() yname2 = self.yarr2.GetStringSelection().strip() iy1 = self.yarr1.GetSelection() iy2 = self.yarr2.GetSelection() yop = self.yop.GetStringSelection().strip() ylabel = yname1 if len(yname2) == 0: yname2 = '1.0' else: ylabel = "%s%s%s" % (ylabel, yop, yname2) if yname1 == '0.0': yarr1 = np.zeros(npts) * 1.0 yexpr1 = 'zeros(%i)' % npts elif len(yname1) == 0 or yname1 == '1.0' or iy1 >= ncol: yarr1 = np.ones(npts) * 1.0 yexpr1 = 'ones(%i)' % npts else: yarr1 = rdata[iy1, :] yexpr1 = '%%s.data[%i, : ]' % iy1 if yname2 == '0.0': yarr2 = np.zeros(npts) * 1.0 yexpr2 = '0.0' elif len(yname2) == 0 or yname2 == '1.0' or iy2 >= ncol: yarr2 = np.ones(npts) * 1.0 yexpr2 = '1.0' else: yarr2 = rdata[iy2, :] yexpr2 = '%%s.data[%i, : ]' % iy2 workgroup.ydat = yarr1 exprs['ydat'] = yexpr1 if yop in ('+', '-', '*', '/'): exprs['ydat'] = "%s %s %s" % (yexpr1, yop, yexpr2) if yop == '+': workgroup.ydat = yarr1.__add__(yarr2) elif yop == '-': workgroup.ydat = yarr1.__sub__(yarr2) elif yop == '*': workgroup.ydat = yarr1.__mul__(yarr2) elif yop == '/': workgroup.ydat = yarr1.__truediv__(yarr2) ysuf, ypop, workgroup.ydat = pre_op(self.ypop, workgroup.ydat) self.ysuf.SetLabel(ysuf) exprs['ydat'] = '%s%s%s' % (ypop, exprs['ydat'], ysuf) yerr_op = self.yerr_op.GetStringSelection().lower() exprs['yerr'] = '1' if yerr_op.startswith('const'): yerr = self.yerr_const.GetValue() exprs['yerr'] = '%f' % yerr elif yerr_op.startswith('array'): iyerr = self.yerr_arr.GetSelection() yerr = rdata[iyerr, :] exprs['yerr'] = '%%s.data[%i, :]' % iyerr elif yerr_op.startswith('sqrt'): yerr = np.sqrt(workgroup.ydat) exprs['yerr'] = 'sqrt(%s.ydat)' if use_deriv: try: workgroup.ydat = (np.gradient(workgroup.ydat) / np.gradient(workgroup.xdat)) exprs['ydat'] = 'deriv(%s)/deriv(%s)' % (exprs['ydat'], exprs['xdat']) except: pass self.expressions = exprs self.array_sel = { 'xpop': xpop, 'xarr': xname, 'ypop': ypop, 'yop': yop, 'yarr1': yname1, 'yarr2': yname2, 'use_deriv': use_deriv } try: npts = min(len(workgroup.xdat), len(workgroup.ydat)) except AttributeError: return workgroup.filename = rawgroup.filename workgroup.npts = npts workgroup.plot_xlabel = xlabel workgroup.plot_ylabel = ylabel workgroup.xdat = np.array(workgroup.xdat[:npts]) workgroup.ydat = np.array(workgroup.ydat[:npts]) workgroup.y = workgroup.ydat workgroup.yerr = yerr if isinstance(yerr, np.ndarray): workgroup.yerr = np.array(yerr[:npts]) if workgroup.datatype == 'xas': workgroup.energy = workgroup.xdat workgroup.mu = workgroup.ydat path, fname = os.path.split(workgroup.filename) popts = dict(marker='o', markersize=4, linewidth=1.5, title=fname, ylabel=ylabel, xlabel=xlabel, label="%s: %s" % (fname, workgroup.plot_ylabel)) self.plotpanel.plot(workgroup.xdat, workgroup.ydat, **popts) for i in range(self.nb.GetPageCount()): if 'plot' in self.nb.GetPageText(i).lower(): self.nb.SetSelection(i) def plot_messages(self, msg, panel=1): self.SetStatusText(msg, panel)
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()
class AthenaImporter(wx.Frame): """Import Athena File""" def __init__(self, parent, filename=None, read_ok_cb=None, size=(725, 450), _larch=None): self.parent = parent self.filename = filename self.larch = _larch self.read_ok_cb = read_ok_cb self.colors = GUIColors() wx.Frame.__init__(self, parent, -1, size=size, style=FRAMESTYLE) splitter = wx.SplitterWindow(self, style=wx.SP_LIVE_UPDATE) splitter.SetMinimumPaneSize(200) leftpanel = wx.Panel(splitter) ltop = wx.Panel(leftpanel) sel_none = Button(ltop, 'Select None', size=(100, 30), action=self.onSelNone) sel_all = Button(ltop, 'Select All', size=(100, 30), action=self.onSelAll) sel_imp = Button(ltop, 'Import Selected Groups', size=(200, 30), action=self.onOK) self.grouplist = FileCheckList(leftpanel, select_action=self.onShowGroup) self.grouplist.SetBackgroundColour(wx.Colour(255, 255, 255)) tsizer = wx.GridBagSizer(2, 2) tsizer.Add(sel_all, (0, 0), (1, 1), LCEN, 0) tsizer.Add(sel_none, (0, 1), (1, 1), LCEN, 0) tsizer.Add(sel_imp, (1, 0), (1, 2), LCEN, 0) pack(ltop, tsizer) sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(ltop, 0, LCEN | wx.GROW, 1) sizer.Add(self.grouplist, 1, LCEN | wx.GROW | wx.ALL, 1) pack(leftpanel, sizer) # right hand side rightpanel = wx.Panel(splitter) self.SetTitle("Reading Athena Project '%s'" % self.filename) self.title = SimpleText(rightpanel, self.filename, font=Font(13), colour=self.colors.title, style=LCEN) self.plotpanel = PlotPanel(rightpanel, messenger=self.plot_messages) sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(self.title, 0, LCEN, 2) sizer.Add(self.plotpanel, 0, LCEN, 2) pack(rightpanel, sizer) splitter.SplitVertically(leftpanel, rightpanel, 1) self.statusbar = self.CreateStatusBar(2, 0) self.statusbar.SetStatusWidths([-3, -1]) statusbar_fields = [self.filename, ""] for i in range(len(statusbar_fields)): self.statusbar.SetStatusText(statusbar_fields[i], i) self.all = read_athena(filename, do_bkg=False, do_fft=False, _larch=_larch) for item in dir(self.all): self.grouplist.Append(item) self.Show() self.Raise() def plot_messages(self, msg, panel=1): self.SetStatusText(msg, panel) def onOK(self, event=None): """ import groups """ for name in self.grouplist.GetCheckedStrings(): rawgroup = getattr(self.all, name) npts = len(rawgroup.energy) outgroup = Group(datatype='xas', path="%s::%s" % (self.filename, name), filename=name, groupname=fix_varname(name), raw=rawgroup, xdat=rawgroup.energy, ydat=rawgroup.mu, y=rawgroup.mu, yerr=1.0, npts=npts, _index=1.0 * np.arange(npts), plot_xlabel='Energy (eV)', plot_ylabel='mu') if self.read_ok_cb is not None: self.read_ok_cb(outgroup, array_sel=None, overwrite=True) self.Destroy() def onCancel(self, event=None): self.Destroy() def onSelAll(self, event=None): self.grouplist.SetCheckedStrings(dir(self.all)) def onSelNone(self, event=None): self.grouplist.SetCheckedStrings([]) def onShowGroup(self, event=None): """column selections changed calc xdat and ydat""" gname = event.GetString() grp = getattr(self.all, gname) if hasattr(grp, 'energy') and hasattr(grp, 'mu'): self.plotpanel.plot(grp.energy, grp.mu, xlabel='Energy', ylabel='mu', title=gname)
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()
class AthenaImporter(wx.Frame) : """Import Athena File""" def __init__(self, parent, filename=None, read_ok_cb=None, size=(725, 450), _larch=None): self.parent = parent self.filename = filename self.larch = _larch self.read_ok_cb = read_ok_cb self.colors = GUIColors() wx.Frame.__init__(self, parent, -1, size=size, style=FRAMESTYLE) splitter = wx.SplitterWindow(self, style=wx.SP_LIVE_UPDATE) splitter.SetMinimumPaneSize(200) leftpanel = wx.Panel(splitter) ltop = wx.Panel(leftpanel) sel_none = Button(ltop, 'Select None', size=(100, 30), action=self.onSelNone) sel_all = Button(ltop, 'Select All', size=(100, 30), action=self.onSelAll) sel_imp = Button(ltop, 'Import Selected Groups', size=(200, 30), action=self.onOK) self.grouplist = FileCheckList(leftpanel, select_action=self.onShowGroup) self.grouplist.SetBackgroundColour(wx.Colour(255, 255, 255)) tsizer = wx.GridBagSizer(2, 2) tsizer.Add(sel_all, (0, 0), (1, 1), LCEN, 0) tsizer.Add(sel_none, (0, 1), (1, 1), LCEN, 0) tsizer.Add(sel_imp, (1, 0), (1, 2), LCEN, 0) pack(ltop, tsizer) sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(ltop, 0, LCEN|wx.GROW, 1) sizer.Add(self.grouplist, 1, LCEN|wx.GROW|wx.ALL, 1) pack(leftpanel, sizer) # right hand side rightpanel = wx.Panel(splitter) self.SetTitle("Reading Athena Project '%s'" % self.filename) self.title = SimpleText(rightpanel, self.filename, font=Font(13), colour=self.colors.title, style=LCEN) self.plotpanel = PlotPanel(rightpanel, messenger=self.plot_messages) sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(self.title, 0, LCEN, 2) sizer.Add(self.plotpanel, 0, LCEN, 2) pack(rightpanel, sizer) splitter.SplitVertically(leftpanel, rightpanel, 1) self.statusbar = self.CreateStatusBar(2, 0) self.statusbar.SetStatusWidths([-3, -1]) statusbar_fields = [self.filename, ""] for i in range(len(statusbar_fields)): self.statusbar.SetStatusText(statusbar_fields[i], i) self.all = read_athena(filename, do_bkg=False, do_fft=False, _larch=_larch) for item in dir(self.all): self.grouplist.Append(item) self.Show() self.Raise() def plot_messages(self, msg, panel=1): self.SetStatusText(msg, panel) def onOK(self, event=None): """ import groups """ for name in self.grouplist.GetCheckedStrings(): rawgroup = getattr(self.all, name) npts = len(rawgroup.energy) outgroup = Group(datatype='xas', path="%s::%s" %(self.filename, name), filename=name, groupname = fix_varname(name), raw=rawgroup, xdat=rawgroup.energy, ydat=rawgroup.mu, y=rawgroup.mu, yerr=1.0, npts=npts, _index=1.0*np.arange(npts), plot_xlabel='Energy (eV)', plot_ylabel='mu') self.read_ok_cb(outgroup, array_sel=None, overwrite=True) self.Destroy() def onCancel(self, event=None): self.Destroy() def onSelAll(self, event=None): self.grouplist.SetCheckedStrings(dir(self.all)) def onSelNone(self, event=None): self.grouplist.SetCheckedStrings([]) def onShowGroup(self, event=None): """column selections changed calc xdat and ydat""" gname = event.GetString() grp = getattr(self.all, gname) if hasattr(grp, 'energy') and hasattr(grp, 'mu'): self.plotpanel.plot(grp.energy, grp.mu, xlabel='Energy', ylabel='mu',title=gname)
class ColumnDataFileFrame(wx.Frame) : """Column Data File, select columns""" def __init__(self, parent, filename=None, groupname=None, last_array_sel=None, read_ok_cb=None, edit_groupname=True, _larch=None): self.parent = parent self._larch = _larch self.path = filename self.extra_sums = {} group = self.initgroup = self.read_column_file(self.path) self.subframes = {} self.workgroup = Group(raw=group) for attr in ('path', 'filename', 'groupname', 'datatype', 'array_labels', 'data'): setattr(self.workgroup, attr, getattr(group, attr, None)) arr_labels = [l.lower() for l in self.initgroup.array_labels] if self.workgroup.datatype is None: self.workgroup.datatype = 'raw' for arrlab in arr_labels[:4]: if 'energ' in arrlab: self.workgroup.datatype = 'xas' self.read_ok_cb = read_ok_cb self.array_sel = {'xpop': '', 'xarr': None, 'ypop': '', 'yop': '/', 'yarr1': None, 'yarr2': None, 'use_deriv': False} if last_array_sel is not None: self.array_sel.update(last_array_sel) if self.array_sel['yarr2'] is None and 'i0' in arr_labels: self.array_sel['yarr2'] = 'i0' if self.array_sel['yarr1'] is None: if 'itrans' in arr_labels: self.array_sel['yarr1'] = 'itrans' elif 'i1' in arr_labels: self.array_sel['yarr1'] = 'i1' message = "Data Columns for %s" % group.filename wx.Frame.__init__(self, None, -1, 'Build Arrays from Data Columns for %s' % group.filename, style=FRAMESTYLE) self.SetFont(Font(10)) panel = wx.Panel(self) self.SetMinSize((600, 600)) self.colors = GUIColors() # title row title = SimpleText(panel, message, font=Font(13), colour=self.colors.title, style=LCEN) opts = dict(action=self.onUpdate, size=(120, -1)) yarr_labels = self.yarr_labels = arr_labels + ['1.0', '0.0', ''] xarr_labels = self.xarr_labels = arr_labels + ['_index'] self.xarr = Choice(panel, choices=xarr_labels, **opts) self.yarr1 = Choice(panel, choices= arr_labels, **opts) self.yarr2 = Choice(panel, choices=yarr_labels, **opts) self.yerr_arr = Choice(panel, choices=yarr_labels, **opts) self.yerr_arr.Disable() self.datatype = Choice(panel, choices=DATATYPES, **opts) self.datatype.SetStringSelection(self.workgroup.datatype) opts['size'] = (50, -1) self.yop = Choice(panel, choices=ARR_OPS, **opts) opts['size'] = (150, -1) self.use_deriv = Check(panel, label='use derivative', default=self.array_sel['use_deriv'], **opts) self.xpop = Choice(panel, choices=XPRE_OPS, **opts) self.ypop = Choice(panel, choices=YPRE_OPS, **opts) opts['action'] = self.onYerrChoice self.yerr_op = Choice(panel, choices=YERR_OPS, **opts) self.yerr_op.SetSelection(0) self.yerr_const = FloatCtrl(panel, value=1, precision=4, size=(90, -1)) ylab = SimpleText(panel, 'Y = ') xlab = SimpleText(panel, 'X = ') yerr_lab = SimpleText(panel, 'Yerror = ') self.xsuf = SimpleText(panel, '') self.ysuf = SimpleText(panel, '') self.message = SimpleText(panel, '', font=Font(11), colour=self.colors.title, style=LCEN) self.xpop.SetStringSelection(self.array_sel['xpop']) self.ypop.SetStringSelection(self.array_sel['ypop']) self.yop.SetStringSelection(self.array_sel['yop']) if '(' in self.array_sel['ypop']: self.ysuf.SetLabel(')') ixsel, iysel, iy2sel = 0, 1, len(yarr_labels)-1 if self.array_sel['xarr'] in xarr_labels: ixsel = xarr_labels.index(self.array_sel['xarr']) if self.array_sel['yarr1'] in arr_labels: iysel = arr_labels.index(self.array_sel['yarr1']) if self.array_sel['yarr2'] in yarr_labels: iy2sel = yarr_labels.index(self.array_sel['yarr2']) self.xarr.SetSelection(ixsel) self.yarr1.SetSelection(iysel) self.yarr2.SetSelection(iy2sel) bpanel = wx.Panel(panel) bsizer = wx.BoxSizer(wx.HORIZONTAL) _ok = Button(bpanel, 'OK', action=self.onOK) _cancel = Button(bpanel, 'Cancel', action=self.onCancel) _edit = Button(bpanel, 'Edit Array Names', action=self.onEditNames) _add = Button(bpanel, 'Select Columns to Sum', action=self.onAddColumns) bsizer.Add(_ok) bsizer.Add(_cancel) bsizer.Add(_edit) bsizer.Add(_add) _ok.SetDefault() pack(bpanel, bsizer) sizer = wx.GridBagSizer(4, 8) sizer.Add(title, (0, 0), (1, 7), LCEN, 5) ir = 1 sizer.Add(xlab, (ir, 0), (1, 1), LCEN, 0) sizer.Add(self.xpop, (ir, 1), (1, 1), CEN, 0) sizer.Add(self.xarr, (ir, 2), (1, 1), CEN, 0) sizer.Add(self.xsuf, (ir, 3), (1, 1), CEN, 0) ir += 1 sizer.Add(ylab, (ir, 0), (1, 1), LCEN, 0) sizer.Add(self.ypop, (ir, 1), (1, 1), CEN, 0) sizer.Add(self.yarr1, (ir, 2), (1, 1), CEN, 0) sizer.Add(self.yop, (ir, 3), (1, 1), CEN, 0) sizer.Add(self.yarr2, (ir, 4), (1, 1), CEN, 0) sizer.Add(self.ysuf, (ir, 5), (1, 1), CEN, 0) sizer.Add(self.use_deriv, (ir, 6), (1, 1), LCEN, 0) ir += 1 sizer.Add(yerr_lab, (ir, 0), (1, 1), LCEN, 0) sizer.Add(self.yerr_op, (ir, 1), (1, 1), CEN, 0) sizer.Add(self.yerr_arr, (ir, 2), (1, 1), CEN, 0) sizer.Add(SimpleText(panel, 'Value:'), (ir, 3), (1, 1), CEN, 0) sizer.Add(self.yerr_const, (ir, 4), (1, 2), CEN, 0) ir += 1 sizer.Add(SimpleText(panel, 'Data Type:'), (ir, 0), (1, 1), LCEN, 0) sizer.Add(self.datatype, (ir, 1), (1, 2), LCEN, 0) ir += 1 self.wid_groupname = wx.TextCtrl(panel, value=group.groupname, size=(200, -1)) if not edit_groupname: self.wid_groupname.Disable() sizer.Add(SimpleText(panel, 'Group Name:'), (ir, 0), (1, 1), LCEN, 0) sizer.Add(self.wid_groupname, (ir, 1), (1, 2), LCEN, 0) sizer.Add(self.message, (ir, 3), (1, 4), LCEN, 0) ir += 1 sizer.Add(bpanel, (ir, 0), (1, 5), LCEN, 3) pack(panel, sizer) self.nb = fnb.FlatNotebook(self, -1, agwStyle=FNB_STYLE) self.nb.SetTabAreaColour(wx.Colour(248,248,240)) self.nb.SetActiveTabColour(wx.Colour(254,254,195)) self.nb.SetNonActiveTabTextColour(wx.Colour(40,40,180)) self.nb.SetActiveTabTextColour(wx.Colour(80,0,0)) self.plotpanel = PlotPanel(self, messenger=self.plot_messages) textpanel = wx.Panel(self) ftext = wx.TextCtrl(textpanel, style=wx.TE_MULTILINE|wx.TE_READONLY, size=(400, 250)) ftext.SetValue(group.text) ftext.SetFont(Font(10)) textsizer = wx.BoxSizer(wx.VERTICAL) textsizer.Add(ftext, 1, LCEN|wx.GROW, 1) pack(textpanel, textsizer) self.nb.AddPage(textpanel, ' Text of Data File ', True) self.nb.AddPage(self.plotpanel, ' Plot of Selected Arrays ', True) mainsizer = wx.BoxSizer(wx.VERTICAL) mainsizer.Add(panel, 0, wx.GROW|wx.ALL, 2) mainsizer.Add(self.nb, 1, LCEN|wx.GROW, 2) pack(self, mainsizer) self.statusbar = self.CreateStatusBar(2, 0) self.statusbar.SetStatusWidths([-1, -1]) statusbar_fields = [group.filename, ""] for i in range(len(statusbar_fields)): self.statusbar.SetStatusText(statusbar_fields[i], i) self.Show() self.Raise() self.onUpdate(self) def read_column_file(self, path): """read column file, generally as initial read""" parent, filename = os.path.split(path) with open(path, 'r') as fh: lines = fh.readlines() text = ''.join(lines) line1 = lines[0].lower() reader = 'read_ascii' if 'epics stepscan file' in line1: reader = 'read_gsexdi' elif 'xdi' in line1: reader = 'read_xdi' elif 'epics scan' in line1: reader = 'read_gsescan' tmpname = '_tmp_file_' read_cmd = "%s = %s('%s')" % (tmpname, reader, path) self.reader = reader _larch = self._larch if (not isinstance(_larch, larch.Interpreter) and hasattr(_larch, '_larch')): _larch = _larch._larch try: _larch.eval(read_cmd, add_history=False) except: pass if _larch.error: msg = ["Error trying to read '%s':" % path, ""] for err in _larch.error: exc_name, errmsg = err.get_error() msg.append(errmsg) title = "Cannot read %s" % path r = Popup(self.parent, "\n".join(msg), title) return None group = _larch.symtable.get_symbol(tmpname) _larch.symtable.del_symbol(tmpname) group.text = text group.path = path group.filename = filename group.groupname = file2groupname(filename, symtable=self._larch.symtable) return group def show_subframe(self, name, frameclass, **opts): shown = False if name in self.subframes: try: self.subframes[name].Raise() shown = True except: del self.subframes[name] if not shown: self.subframes[name] = frameclass(self, **opts) def onAddColumns(self, event=None): self.show_subframe('addcol', AddColumnsFrame, group=self.workgroup, on_ok=self.add_columns) def add_columns(self, label, selection): new_labels = self.workgroup.array_labels self.set_array_labels(new_labels) self.yarr1.SetStringSelection(new_labels[-1]) self.extra_sums[label] = selection self.onUpdate() def onEditNames(self, evt=None): self.show_subframe('editcol', EditColumnFrame, group=self.workgroup, on_ok=self.set_array_labels) def set_array_labels(self, arr_labels): self.workgroup.array_labels = arr_labels yarr_labels = self.yarr_labels = arr_labels + ['1.0', '0.0', ''] xarr_labels = self.xarr_labels = arr_labels + ['_index'] def update(wid, choices): curstr = wid.GetStringSelection() curind = wid.GetSelection() wid.SetChoices(choices) if curstr in choices: wid.SetStringSelection(curstr) else: wid.SetSelection(curind) update(self.xarr, xarr_labels) update(self.yarr1, yarr_labels) update(self.yarr2, yarr_labels) update(self.yerr_arr, yarr_labels) self.onUpdate() def onOK(self, event=None): """ build arrays according to selection """ if self.wid_groupname is not None: groupname = fix_varname(self.wid_groupname.GetValue()) yerr_op = self.yerr_op.GetStringSelection().lower() yerr_expr = '1' if yerr_op.startswith('const'): yerr_expr = "%f" % self.yerr_const.GetValue() elif yerr_op.startswith('array'): yerr_expr = '%%s.data[%i, :]' % self.yerr_arr.GetSelection() elif yerr_op.startswith('sqrt'): yerr_expr = 'sqrt(%s.ydat)' self.expressions['yerr'] = yerr_expr # generate script to pass back to calling program: labels = ', '.join(self.workgroup.array_labels) read_cmd = "%s('{path}', labels='%s')" % (self.reader, labels) buff = ["{group} = %s" % read_cmd, "{group}.path = '{path}'", "{group}.is_frozen = False"] for label, selection in self.extra_sums.items(): buff.append("{group}.array_labels.append('%s')" % label) buff.append("_tmparr = {group}.data[%s, :].sum(axis=0)" % repr(selection)) buff.append("_tmpn = len(_tmparr)") buff.append("{group}.data = append({group}.data, _tmparr.reshape(1, _tmpn), axis=0)") buff.append("del _tmparr, _tmpn") for attr in ('datatype', 'plot_xlabel', 'plot_ylabel'): val = getattr(self.workgroup, attr) buff.append("{group}.%s = '%s'" % (attr, val)) for aname in ('xdat', 'ydat', 'yerr'): expr = self.expressions[aname].replace('%s', '{group:s}') buff.append("{group}.%s = %s" % (aname, expr)) if getattr(self.workgroup, 'datatype', 'raw') == 'xas': if self.reader == 'read_gsescan': buff.append("{group}.energy = {group}.x") else: buff.append("{group}.energy = {group}.xdat") buff.append("{group}.mu = {group}.ydat") buff.append("sort_xafs({group}, overwrite=True, fix_repeats=True)") script = "\n".join(buff) if self.read_ok_cb is not None: self.read_ok_cb(script, self.path, groupname=groupname, array_sel=self.array_sel) for f in self.subframes.values(): try: f.Destroy() except: pass self.Destroy() def onCancel(self, event=None): self.workgroup.import_ok = False for f in self.subframes.values(): try: f.Destroy() except: pass self.Destroy() def onYerrChoice(self, evt=None): yerr_choice = evt.GetString() self.yerr_arr.Disable() self.yerr_const.Disable() if 'const' in yerr_choice.lower(): self.yerr_const.Enable() elif 'array' in yerr_choice.lower(): self.yerr_arr.Enable() self.onUpdate() def onUpdate(self, value=None, evt=None): """column selections changed calc xdat and ydat""" # dtcorr = self.dtcorr.IsChecked() # print("Column Frame on Update ") dtcorr = False use_deriv = self.use_deriv.IsChecked() rawgroup = self.initgroup workgroup = self.workgroup rdata = self.initgroup.data ix = self.xarr.GetSelection() xname = self.xarr.GetStringSelection() exprs = dict(xdat=None, ydat=None, yerr=None) ncol, npts = rdata.shape workgroup.index = 1.0*np.arange(npts) if xname.startswith('_index') or ix >= ncol: workgroup.xdat = 1.0*np.arange(npts) xname = '_index' exprs['xdat'] = 'arange(%i)' % npts else: workgroup.xdat = rdata[ix, :] exprs['xdat'] = '%%s.data[%i, : ]' % ix workgroup.datatype = self.datatype.GetStringSelection().strip().lower() def pre_op(opwid, arr): opstr = opwid.GetStringSelection().strip() suf = '' if opstr in ('-log(', 'log('): suf = ')' if opstr == 'log(': arr = np.log(arr) elif opstr == '-log(': arr = -np.log(arr) return suf, opstr, arr try: xsuf, xpop, workgroup.xdat = pre_op(self.xpop, workgroup.xdat) self.xsuf.SetLabel(xsuf) exprs['xdat'] = '%s%s%s' % (xpop, exprs['xdat'], xsuf) except: return try: xunits = rawgroup.array_units[ix].strip() xlabel = '%s (%s)' % (xname, xunits) except: xlabel = xname yname1 = self.yarr1.GetStringSelection().strip() yname2 = self.yarr2.GetStringSelection().strip() iy1 = self.yarr1.GetSelection() iy2 = self.yarr2.GetSelection() yop = self.yop.GetStringSelection().strip() ylabel = yname1 if len(yname2) == 0: yname2 = '1.0' else: ylabel = "%s%s%s" % (ylabel, yop, yname2) if yname1 == '0.0': yarr1 = np.zeros(npts)*1.0 yexpr1 = 'zeros(%i)' % npts elif len(yname1) == 0 or yname1 == '1.0' or iy1 >= ncol: yarr1 = np.ones(npts)*1.0 yexpr1 = 'ones(%i)' % npts else: yarr1 = rdata[iy1, :] yexpr1 = '%%s.data[%i, : ]' % iy1 if yname2 == '0.0': yarr2 = np.zeros(npts)*1.0 yexpr2 = '0.0' elif len(yname2) == 0 or yname2 == '1.0' or iy2 >= ncol: yarr2 = np.ones(npts)*1.0 yexpr2 = '1.0' else: yarr2 = rdata[iy2, :] yexpr2 = '%%s.data[%i, : ]' % iy2 workgroup.ydat = yarr1 exprs['ydat'] = yexpr1 if yop in ('+', '-', '*', '/'): exprs['ydat'] = "%s %s %s" % (yexpr1, yop, yexpr2) if yop == '+': workgroup.ydat = yarr1.__add__(yarr2) elif yop == '-': workgroup.ydat = yarr1.__sub__(yarr2) elif yop == '*': workgroup.ydat = yarr1.__mul__(yarr2) elif yop == '/': workgroup.ydat = yarr1.__truediv__(yarr2) ysuf, ypop, workgroup.ydat = pre_op(self.ypop, workgroup.ydat) self.ysuf.SetLabel(ysuf) exprs['ydat'] = '%s%s%s' % (ypop, exprs['ydat'], ysuf) yerr_op = self.yerr_op.GetStringSelection().lower() exprs['yerr'] = '1' if yerr_op.startswith('const'): yerr = self.yerr_const.GetValue() exprs['yerr'] = '%f' % yerr elif yerr_op.startswith('array'): iyerr = self.yerr_arr.GetSelection() yerr = rdata[iyerr, :] exprs['yerr'] = '%%s.data[%i, :]' % iyerr elif yerr_op.startswith('sqrt'): yerr = np.sqrt(workgroup.ydat) exprs['yerr'] = 'sqrt(%s.ydat)' if use_deriv: try: workgroup.ydat = (np.gradient(workgroup.ydat) / np.gradient(workgroup.xdat)) exprs['ydat'] = 'deriv(%s)/deriv(%s)' % (exprs['ydat'], exprs['xdat']) except: pass self.expressions = exprs self.array_sel = {'xpop': xpop, 'xarr': xname, 'ypop': ypop, 'yop': yop, 'yarr1': yname1, 'yarr2': yname2, 'use_deriv': use_deriv} try: npts = min(len(workgroup.xdat), len(workgroup.ydat)) except AttributeError: return except ValueError: return en = workgroup.xdat if ((workgroup.datatype == 'xas') and ((len(en) > 1000 or any(np.diff(en) < 0) or ((max(en)-min(en)) > 350 and (np.diff(en[:100]).mean() < 1.0))))): self.message.SetLabel("Warning: XAS data may need to be rebinned!") else: self.message.SetLabel("") workgroup.filename = rawgroup.filename workgroup.npts = npts workgroup.plot_xlabel = xlabel workgroup.plot_ylabel = ylabel workgroup.xdat = np.array(workgroup.xdat[:npts]) workgroup.ydat = np.array(workgroup.ydat[:npts]) workgroup.y = workgroup.ydat workgroup.yerr = yerr if isinstance(yerr, np.ndarray): workgroup.yerr = np.array(yerr[:npts]) if workgroup.datatype == 'xas': workgroup.energy = workgroup.xdat workgroup.mu = workgroup.ydat path, fname = os.path.split(workgroup.filename) popts = dict(marker='o', markersize=4, linewidth=1.5, title=fname, ylabel=ylabel, xlabel=xlabel, label="%s: %s" % (fname, workgroup.plot_ylabel)) self.plotpanel.plot(workgroup.xdat, workgroup.ydat, **popts) for i in range(self.nb.GetPageCount()): if 'plot' in self.nb.GetPageText(i).lower(): self.nb.SetSelection(i) def plot_messages(self, msg, panel=1): self.SetStatusText(msg, panel)
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)
class EditColumnFrame(wx.Frame) : """Set Column Labels for a file""" def __init__(self, parent, group=None, last_array_sel=None, read_ok_cb=None, edit_groupname=True, with_smooth=False, _larch=None): self.parent = parent self.larch = _larch self.rawgroup = group self.with_smooth = with_smooth self.outgroup = Group(raw=group) for attr in ('path', 'filename', 'groupname', 'datatype'): setattr(self.outgroup, attr, getattr(group, attr, None)) if self.outgroup.datatype is None: self.outgroup.datatype = 'raw' if ('energ' in self.rawgroup.array_labels[0].lower() or 'energ' in self.rawgroup.array_labels[1].lower()): self.outgroup.datatype = 'xas' self.read_ok_cb = read_ok_cb self.array_sel = {'xpop': '', 'xarr': None, 'ypop': '', 'yop': '/', 'yarr1': None, 'yarr2': None, 'use_deriv': False} if last_array_sel is not None: self.array_sel.update(last_array_sel) if self.array_sel['yarr2'] is None and 'i0' in self.rawgroup.array_labels: self.array_sel['yarr2'] = 'i0' if self.array_sel['yarr1'] is None: if 'itrans' in self.rawgroup.array_labels: self.array_sel['yarr1'] = 'itrans' elif 'i1' in self.rawgroup.array_labels: self.array_sel['yarr1'] = 'i1' message = "Data Columns for %s" % self.rawgroup.filename wx.Frame.__init__(self, None, -1, 'Build Arrays from Data Columns for %s' % self.rawgroup.filename, style=FRAMESTYLE) self.SetFont(Font(10)) panel = wx.Panel(self) self.SetMinSize((600, 600)) self.colors = GUIColors() # title row title = SimpleText(panel, message, font=Font(13), colour=self.colors.title, style=LCEN) opts = dict(action=self.onUpdate, size=(120, -1)) arr_labels = self.rawgroup.array_labels yarr_labels = arr_labels + ['1.0', '0.0', ''] xarr_labels = arr_labels + ['<index>'] self.xarr = Choice(panel, choices=xarr_labels, **opts) self.yarr1 = Choice(panel, choices= arr_labels, **opts) self.yarr2 = Choice(panel, choices=yarr_labels, **opts) self.yerr_arr = Choice(panel, choices=yarr_labels, **opts) self.yerr_arr.Disable() self.datatype = Choice(panel, choices=DATATYPES, **opts) self.datatype.SetStringSelection(self.outgroup.datatype) opts['size'] = (50, -1) self.yop = Choice(panel, choices=ARR_OPS, **opts) opts['size'] = (120, -1) self.use_deriv = Check(panel, label='use derivative', default=self.array_sel['use_deriv'], **opts) self.xpop = Choice(panel, choices=XPRE_OPS, **opts) self.ypop = Choice(panel, choices=YPRE_OPS, **opts) opts['action'] = self.onYerrChoice self.yerr_op = Choice(panel, choices=YERR_OPS, **opts) self.yerr_op.SetSelection(0) self.yerr_const = FloatCtrl(panel, value=1, precision=4, size=(90, -1)) if with_smooth: opts['action'] = self.onSmoothChoice self.smooth_op = Choice(panel, choices=SMOOTH_OPS, **opts) self.smooth_op.SetSelection(0) opts['size'] = (100, -1) opts['action'] = self.onUpdate smooth_panel = wx.Panel(panel) smooth_sizer = wx.BoxSizer(wx.HORIZONTAL) self.smooth_conv = Choice(smooth_panel, choices=CONV_OPS, **opts) opts['size'] = (30, -1) self.smooth_c0 = FloatCtrl(smooth_panel, value=3, precision=0, **opts) self.smooth_c1 = FloatCtrl(smooth_panel, value=1, precision=0, **opts) opts['size'] = (75, -1) self.smooth_sig = FloatCtrl(smooth_panel, value=1, precision=4, **opts) self.smooth_c0.Disable() self.smooth_c1.Disable() self.smooth_sig.Disable() self.smooth_conv.SetSelection(0) self.smooth_conv.Disable() ylab = SimpleText(panel, 'Y = ') xlab = SimpleText(panel, 'X = ') yerr_lab = SimpleText(panel, 'Yerror = ') self.xsuf = SimpleText(panel, '') self.ysuf = SimpleText(panel, '') self.xpop.SetStringSelection(self.array_sel['xpop']) self.ypop.SetStringSelection(self.array_sel['ypop']) self.yop.SetStringSelection(self.array_sel['yop']) if '(' in self.array_sel['ypop']: self.ysuf.SetLabel(')') ixsel, iysel, iy2sel = 0, 1, len(yarr_labels)-1 if self.array_sel['xarr'] in xarr_labels: ixsel = xarr_labels.index(self.array_sel['xarr']) if self.array_sel['yarr1'] in arr_labels: iysel = arr_labels.index(self.array_sel['yarr1']) if self.array_sel['yarr2'] in yarr_labels: iy2sel = yarr_labels.index(self.array_sel['yarr2']) self.xarr.SetSelection(ixsel) self.yarr1.SetSelection(iysel) self.yarr2.SetSelection(iy2sel) bpanel = wx.Panel(panel) bsizer = wx.BoxSizer(wx.HORIZONTAL) bsizer.Add(Button(bpanel, 'OK', action=self.onOK), 4) bsizer.Add(Button(bpanel, 'Cancel', action=self.onCancel), 4) pack(bpanel, bsizer) sizer = wx.GridBagSizer(4, 8) sizer.Add(title, (0, 0), (1, 7), LCEN, 5) ir = 1 sizer.Add(xlab, (ir, 0), (1, 1), LCEN, 0) sizer.Add(self.xpop, (ir, 1), (1, 1), CEN, 0) sizer.Add(self.xarr, (ir, 2), (1, 1), CEN, 0) sizer.Add(self.xsuf, (ir, 3), (1, 1), CEN, 0) ir += 1 sizer.Add(ylab, (ir, 0), (1, 1), LCEN, 0) sizer.Add(self.ypop, (ir, 1), (1, 1), CEN, 0) sizer.Add(self.yarr1, (ir, 2), (1, 1), CEN, 0) sizer.Add(self.yop, (ir, 3), (1, 1), CEN, 0) sizer.Add(self.yarr2, (ir, 4), (1, 1), CEN, 0) sizer.Add(self.ysuf, (ir, 5), (1, 1), CEN, 0) sizer.Add(self.use_deriv, (ir, 6), (1, 1), LCEN, 0) ir += 1 sizer.Add(yerr_lab, (ir, 0), (1, 1), LCEN, 0) sizer.Add(self.yerr_op, (ir, 1), (1, 1), CEN, 0) sizer.Add(self.yerr_arr, (ir, 2), (1, 1), CEN, 0) sizer.Add(SimpleText(panel, 'Value:'), (ir, 3), (1, 1), CEN, 0) sizer.Add(self.yerr_const, (ir, 4), (1, 2), CEN, 0) if with_smooth: ir += 1 sizer.Add(SimpleText(panel, 'Smoothing:'), (ir, 0), (1, 1), LCEN, 0) sizer.Add(self.smooth_op, (ir, 1), (1, 1), CEN, 0) smooth_sizer.Add(SimpleText(smooth_panel, ' n='), 0, LCEN, 1) smooth_sizer.Add(self.smooth_c0, 0, LCEN, 1) smooth_sizer.Add(SimpleText(smooth_panel, ' order='), 0, LCEN, 1) smooth_sizer.Add(self.smooth_c1, 0, LCEN, 1) smooth_sizer.Add(SimpleText(smooth_panel, ' form='), 0, LCEN, 1) smooth_sizer.Add(self.smooth_conv, 0, LCEN, 1) smooth_sizer.Add(SimpleText(smooth_panel, ' sigma='), 0, LCEN, 1) smooth_sizer.Add(self.smooth_sig, 0, LCEN, 1) pack(smooth_panel, smooth_sizer) sizer.Add(smooth_panel, (ir, 2), (1, 5), LCEN, 1) ir += 1 sizer.Add(SimpleText(panel, 'Data Type:'), (ir, 0), (1, 1), LCEN, 0) sizer.Add(self.datatype, (ir, 1), (1, 2), LCEN, 0) ir += 1 self.wid_groupname = wx.TextCtrl(panel, value=self.rawgroup.groupname, size=(120, -1)) if not edit_groupname: self.wid_groupname.Disable() sizer.Add(SimpleText(panel, 'Group Name:'), (ir, 0), (1, 1), LCEN, 0) sizer.Add(self.wid_groupname, (ir, 1), (1, 1), LCEN, 0) ir += 1 sizer.Add(bpanel, (ir, 0), (1, 5), LCEN, 3) pack(panel, sizer) self.nb = fnb.FlatNotebook(self, -1, agwStyle=FNB_STYLE) self.nb.SetTabAreaColour(wx.Colour(248,248,240)) self.nb.SetActiveTabColour(wx.Colour(254,254,195)) self.nb.SetNonActiveTabTextColour(wx.Colour(40,40,180)) self.nb.SetActiveTabTextColour(wx.Colour(80,0,0)) self.plotpanel = PlotPanel(self, messenger=self.plot_messages) textpanel = wx.Panel(self) ftext = wx.TextCtrl(textpanel, style=wx.TE_MULTILINE|wx.TE_READONLY, size=(400, 250)) try: m = open(self.rawgroup.filename, 'r') text = m.read() m.close() except: text = "The file '%s'\n could not be read" % self.rawgroup.filename ftext.SetValue(text) ftext.SetFont(Font(11)) textsizer = wx.BoxSizer(wx.VERTICAL) textsizer.Add(ftext, 1, LCEN|wx.GROW, 1) pack(textpanel, textsizer) self.nb.AddPage(textpanel, ' Text of Data File ', True) self.nb.AddPage(self.plotpanel, ' Plot of Selected Arrays ', True) mainsizer = wx.BoxSizer(wx.VERTICAL) mainsizer.Add(panel, 0, wx.GROW|wx.ALL, 2) mainsizer.Add(self.nb, 1, LCEN|wx.GROW, 2) pack(self, mainsizer) self.statusbar = self.CreateStatusBar(2, 0) self.statusbar.SetStatusWidths([-1, -1]) statusbar_fields = [self.rawgroup.filename, ""] for i in range(len(statusbar_fields)): self.statusbar.SetStatusText(statusbar_fields[i], i) self.Show() self.Raise() self.onUpdate(self) def onOK(self, event=None): """ build arrays according to selection """ if self.wid_groupname is not None: self.outgroup.groupname = fix_varname(self.wid_groupname.GetValue()) yerr_op = self.yerr_op.GetStringSelection().lower() if yerr_op.startswith('const'): self.outgroup.yerr = self.yerr_const.GetValue() elif yerr_op.startswith('array'): yerr = self.yerr_arr.GetStringSelection().strip() self.outgroup.yerr = get_data(rawgroup, yerr) elif yerr_op.startswith('sqrt'): self.outgroup.yerr = np.sqrt(outgroup.ydat) if self.read_ok_cb is not None: self.read_ok_cb(self.outgroup, array_sel=self.array_sel) self.Destroy() def onCancel(self, event=None): self.outgroup.import_ok = False self.Destroy() def onYerrChoice(self, evt=None): yerr_choice = evt.GetString() self.yerr_arr.Disable() self.yerr_const.Disable() if 'const' in yerr_choice.lower(): self.yerr_const.Enable() elif 'array' in yerr_choice.lower(): self.yerr_arr.Enable() self.onUpdate() def onSmoothChoice(self, evt=None): choice = self.smooth_op.GetStringSelection().lower() conv = self.smooth_conv.GetStringSelection() self.smooth_c0.Disable() self.smooth_c1.Disable() self.smooth_conv.Disable() self.smooth_sig.Disable() if choice.startswith('box'): self.smooth_c0.Enable() elif choice.startswith('savi'): self.smooth_c0.Enable() self.smooth_c1.Enable() elif choice.startswith('conv'): self.smooth_conv.Enable() self.smooth_sig.Enable() self.onUpdate() def onUpdate(self, value=None, evt=None): """column selections changed calc xdat and ydat""" # dtcorr = self.dtcorr.IsChecked() dtcorr = False use_deriv = self.use_deriv.IsChecked() rawgroup = self.rawgroup outgroup = self.outgroup ix = self.xarr.GetSelection() xname = self.xarr.GetStringSelection() if xname == '<index>': xname = self.rawgroup.array_labels[0] outgroup._index = 1.0*np.arange(len(getattr(rawgroup, xname))) xname = '_index' outgroup.datatype = self.datatype.GetStringSelection().strip().lower() outgroup.xdat = getattr(rawgroup, xname) def pre_op(opwid, arr): opstr = opwid.GetStringSelection().strip() suf = '' if opstr in ('-log(', 'log('): suf = ')' if opstr == 'log(': arr = np.log(arr) elif opstr == '-log(': arr = -np.log(arr) return suf, opstr, arr try: xsuf, xpop, outgroup.xdat = pre_op(self.xpop, outgroup.xdat) self.xsuf.SetLabel(xsuf) except: return try: xunits = rawgroup.array_units[ix].strip() xlabel = '%s (%s)' % (xname, xunits) except: xlabel = xname def get_data(grp, arrayname, correct=False): if hasattr(grp, 'get_data'): return grp.get_data(arrayname, correct=correct) return getattr(grp, arrayname, None) yname1 = self.yarr1.GetStringSelection().strip() yname2 = self.yarr2.GetStringSelection().strip() yop = self.yop.GetStringSelection().strip() ylabel = yname1 if len(yname2) == 0: yname2 = '1.0' else: ylabel = "%s%s%s" % (ylabel, yop, yname2) yarr1 = get_data(rawgroup, yname1, correct=dtcorr) if yname2 in ('0.0', '1.0'): yarr2 = float(yname2) if yop == '/': yarr2 = 1.0 else: yarr2 = get_data(rawgroup, yname2, correct=dtcorr) outgroup.ydat = yarr1 if yop == '+': outgroup.ydat = yarr1.__add__(yarr2) elif yop == '-': outgroup.ydat = yarr1.__sub__(yarr2) elif yop == '*': outgroup.ydat = yarr1.__mul__(yarr2) elif yop == '/': outgroup.ydat = yarr1.__truediv__(yarr2) yerr_op = self.yerr_op.GetStringSelection().lower() if yerr_op.startswith('const'): yerr = self.yerr_const.GetValue() elif yerr_op.startswith('array'): yerr = self.yerr_arr.GetStringSelection().strip() yerr = get_data(rawgroup, yerr) elif yerr_op.startswith('sqrt'): yerr = np.sqrt(outgroup.ydat) ysuf, ypop, outgroup.ydat = pre_op(self.ypop, outgroup.ydat) self.ysuf.SetLabel(ysuf) if use_deriv: try: outgroup.ydat = (np.gradient(outgroup.ydat) / np.gradient(outgroup.xdat)) except: pass # apply smoothhing here if self.with_smooth: smoother = self.smooth_op.GetStringSelection().lower() if smoother.startswith('box'): n = int(self.smooth_c0.GetValue()) outgroup.ydat = boxcar(outgroup.ydat, n) elif smoother.startswith('savit'): n = int(self.smooth_c0.GetValue()) win_size = 2*n + 1 order = int(self.smooth_c1.GetValue()) outgroup.ydat = savitzky_golay(outgroup.ydat, win_size, order) elif smoother.startswith('conv'): sigma = float(self.smooth_sig.GetValue()) form = str(self.smooth_conv.GetStringSelection()).lower() outgroup.ydat = smooth(outgroup.xdat, outgroup.ydat, sigma=sigma, form=form) self.array_sel = {'xpop': xpop, 'xarr': xname, 'ypop': ypop, 'yop': yop, 'yarr1': yname1, 'yarr2': yname2, 'use_deriv': use_deriv} try: npts = min(len(outgroup.xdat), len(outgroup.ydat)) except AttributeError: return outgroup.filename = rawgroup.filename outgroup.npts = npts outgroup.plot_xlabel = xlabel outgroup.plot_ylabel = ylabel outgroup.xdat = np.array(outgroup.xdat[:npts]) outgroup.ydat = np.array(outgroup.ydat[:npts]) outgroup.y = outgroup.ydat outgroup.yerr = yerr if isinstance(yerr, np.ndarray): outgroup.yerr = np.array(yerr[:npts]) if outgroup.datatype == 'xas': outgroup.energy = outgroup.xdat outgroup.mu = outgroup.ydat popts = {} path, fname = os.path.split(outgroup.filename) popts['label'] = "%s: %s" % (fname, outgroup.plot_ylabel) popts['title'] = fname popts['ylabel'] = outgroup.plot_ylabel popts['xlabel'] = outgroup.plot_xlabel self.plotpanel.plot(outgroup.xdat, outgroup.ydat, **popts) for i in range(self.nb.GetPageCount()): if 'plot' in self.nb.GetPageText(i).lower(): self.nb.SetSelection(i) def plot_messages(self, msg, panel=1): self.SetStatusText(msg, panel)
class MainFrame(wx.Frame): # monitor_address = 'C3/hr_monitor/1' yellow_alrm_thrsh = 0.25 red_alrm_thrsh = 0.5 sleep_time = 5 def __init__(self, *args, **kwds): # begin wxGlade: MainFrame.__init__ kwds["style"] = wx.DEFAULT_FRAME_STYLE wx.Frame.__init__(self, *args, **kwds) self.alarm_plt = PlotPanel(self) #self.timestamp_sld = wx.Slider(self, -1, 0, 0, 10) self.avg_hr_title_lbl = wx.StaticText(self, -1, "Current avg. HR:") self.avg_hr_lbl = wx.StaticText(self, -1, "nan") self.panel_1 = wx.Panel(self, -1) self.avg_acc_title_lbl = wx.StaticText(self, -1, "Current avg. Acceleration:") self.avg_acc_lbl = wx.StaticText(self, -1, "nan") self.panel_2 = wx.Panel(self, -1) self.anomaly_lvl_curr_title_lbl = wx.StaticText( self, -1, "Anomaly level: Current:") self.anomaly_lvl_curr_lbl = wx.StaticText(self, -1, "nan") self.panel_3 = wx.Panel(self, -1) self.anomaly_lvl_max_title_lbl = wx.StaticText( self, -1, " Max:") self.anomaly_lvl_max_lbl = wx.StaticText(self, -1, "nan") self.red_alarm_lbl = wx.Panel(self, -1) self.anomaly_lvl_min_title_lbl = wx.StaticText( self, -1, " Min:") self.anomaly_lvl_min_lbl = wx.StaticText(self, -1, "nan") self.yellow_alarm_lbl = wx.Panel(self, -1) self.anomaly_lvl_avg_title_lbl = wx.StaticText( self, -1, " Average:") self.anomaly_lvl_avg_lbl = wx.StaticText(self, -1, "nan") self.green_alarm_lbl = wx.Panel(self, -1) self.collect_btn = wx.Button(self, -1, "Collect data") self.__set_properties() self.__do_layout() #self.Bind(wx.EVT_COMMAND_SCROLL, self.timestamp_sld_scroll, self.timestamp_sld) self.Bind(wx.EVT_BUTTON, self.collect_btn_click, self.collect_btn) # end wxGlade self.timer_thread = Timer(target=self.timer_tick) self.proxy = DeviceProxy(MainFrame.monitor_address) self.alarms = set() def __set_properties(self): # begin wxGlade: MainFrame.__set_properties self.SetTitle("HRMonitor GUI") self.red_alarm_lbl.SetBackgroundColour(wx.NullColor) self.yellow_alarm_lbl.SetBackgroundColour(wx.NullColor) self.green_alarm_lbl.SetBackgroundColour(wx.NullColor) # end wxGlade def __do_layout(self): # begin wxGlade: MainFrame.__do_layout sizer_1 = wx.BoxSizer(wx.VERTICAL) sizer_2 = wx.BoxSizer(wx.VERTICAL) sizer_3 = wx.BoxSizer(wx.HORIZONTAL) grid_sizer_2 = wx.GridSizer(6, 3, 0, 0) sizer_1.Add(self.alarm_plt, 1, wx.EXPAND, 0) #sizer_1.Add(self.timestamp_sld, 0, wx.EXPAND, 0) grid_sizer_2.Add(self.avg_hr_title_lbl, 0, 0, 0) grid_sizer_2.Add(self.avg_hr_lbl, 0, 0, 0) grid_sizer_2.Add(self.panel_1, 1, wx.EXPAND, 0) grid_sizer_2.Add(self.avg_acc_title_lbl, 0, 0, 0) grid_sizer_2.Add(self.avg_acc_lbl, 0, 0, 0) grid_sizer_2.Add(self.panel_2, 1, wx.EXPAND, 0) grid_sizer_2.Add(self.anomaly_lvl_curr_title_lbl, 0, 0, 0) grid_sizer_2.Add(self.anomaly_lvl_curr_lbl, 0, 0, 0) grid_sizer_2.Add(self.panel_3, 1, wx.EXPAND, 0) grid_sizer_2.Add(self.anomaly_lvl_max_title_lbl, 0, 0, 0) grid_sizer_2.Add(self.anomaly_lvl_max_lbl, 0, 0, 0) grid_sizer_2.Add(self.red_alarm_lbl, 0, wx.EXPAND, 0) grid_sizer_2.Add(self.anomaly_lvl_min_title_lbl, 0, 0, 0) grid_sizer_2.Add(self.anomaly_lvl_min_lbl, 0, 0, 0) grid_sizer_2.Add(self.yellow_alarm_lbl, 0, wx.EXPAND, 0) grid_sizer_2.Add(self.anomaly_lvl_avg_title_lbl, 0, 0, 0) grid_sizer_2.Add(self.anomaly_lvl_avg_lbl, 0, 0, 0) grid_sizer_2.Add(self.green_alarm_lbl, 0, wx.EXPAND, 0) sizer_2.Add(grid_sizer_2, 9, wx.EXPAND, 0) sizer_3.Add(self.collect_btn, 0, wx.ALL, 0) sizer_2.Add(sizer_3, 1, wx.EXPAND | wx.SHAPED, 0) sizer_1.Add(sizer_2, 1, wx.EXPAND, 0) self.SetSizer(sizer_1) sizer_1.Fit(self) self.Layout() # end wxGlade # wxGlade: MainFrame.<event_handler> def timestamp_sld_scroll(self, event): print("Event handler `timestamp_sld_scroll' not implemented") event.Skip() # wxGlade: MainFrame.<event_handler> def collect_btn_click(self, event): if self.collect_btn.GetLabel() == "Stop collecting": self.collect_btn.SetLabel("Collect data") self.timer_thread.stop() del self.timer_thread self.timer_thread = Timer(target=self.timer_tick) else: self.collect_btn.SetLabel("Stop collecting") self.timer_thread.start() event.Skip() # end of class MainFrame def timer_tick(self): timer = current_thread() proxy = self.proxy while not timer.stopped(): try: avg_hr_idx = proxy.command_inout_asynch('get_avg_hr', 4) avg_acc_idx = proxy.command_inout_asynch('get_avg_acc', 4) alarms_idx = proxy.command_inout_asynch( 'get_current_alarms', 4) init = datetime.now() avg_hr = proxy.command_inout_reply(avg_hr_idx, timeout=0) avg_acc = proxy.command_inout_reply(avg_acc_idx, timeout=0) alarms = proxy.command_inout_reply(alarms_idx, timeout=0) sleep_time = timedelta(seconds=MainFrame.sleep_time) sleep_time -= (datetime.now() - init) sleep_time = max(sleep_time, timedelta(0)).total_seconds() alarms[0], alarms[1] = alarms[1], alarms[0] alarms[0] = [ float( datetime.strptime( x, '%Y-%m-%d %H:%M:%S.%f').strftime('%s.%f')) for x in alarms[0] ] alarms[0] = [x % 100000 for x in alarms[0]] if not isnan(avg_hr): wx.CallAfter(self.avg_hr_lbl.SetLabel, str(avg_hr)) if not isnan(avg_acc): wx.CallAfter(self.avg_acc_lbl.SetLabel, str(avg_acc)) if len(alarms[0]) > 0: self.alarms.update(zip(*alarms)) wx.CallAfter(self.set_alarm_text) data = sorted(self.alarms) if len(data) > 0: wx.CallAfter(self.plot, zip(*data)) wx.CallAfter(self.set_alarm_color, max(data)[1]) sleep(sleep_time) except ConnectionFailed: wx.CallAfter(self.collect_btn_click, None) break del proxy def plot(self, data): x_data, y_data = data self.alarm_plt.plot(x_data, y_data, title="Alarm Level History") def set_alarm_text(self): alarms = sorted(self.alarms) if len(alarms) > 0: vals = [x for _, x in alarms] else: vals = [nan] alarms = [(nan, nan)] avg = sum(vals) / len(vals) self.anomaly_lvl_curr_lbl.SetLabel(str(alarms[-1][1])) self.anomaly_lvl_max_lbl.SetLabel(str(max(vals))) self.anomaly_lvl_min_lbl.SetLabel(str(min(vals))) self.anomaly_lvl_avg_lbl.SetLabel(str(avg)) def set_alarm_color(self, alarm_lvl): if alarm_lvl < MainFrame.yellow_alrm_thrsh: self.red_alarm_lbl.SetBackgroundColour(wx.NullColor) self.yellow_alarm_lbl.SetBackgroundColour(wx.NullColor) self.green_alarm_lbl.SetBackgroundColour('Green') elif MainFrame.yellow_alrm_thrsh <= alarm_lvl < MainFrame.red_alrm_thrsh: self.red_alarm_lbl.SetBackgroundColour(wx.NullColor) self.yellow_alarm_lbl.SetBackgroundColour('Yellow') self.green_alarm_lbl.SetBackgroundColour(wx.NullColor) else: self.red_alarm_lbl.SetBackgroundColour('Red') self.yellow_alarm_lbl.SetBackgroundColour(wx.NullColor) self.green_alarm_lbl.SetBackgroundColour(wx.NullColor) # get a color between green and red, going through yellow # offset = 0.2 # adjusted_lvl = min(alarm_lvl + offset, 1) # r, g, b = hsv_to_rgb((1 - adjusted_lvl) / 3, 1, 1) # r = int(255 * r) # g = int(255 * g) # b = int(255 * b) # color = wx.Color(r, g, b) # self.green_alarm_lbl.SetBackgroundColour(color) self.red_alarm_lbl.Refresh() self.yellow_alarm_lbl.Refresh() self.green_alarm_lbl.Refresh() self.Refresh()